Commit d56ca209 authored by Magix's avatar Magix Committed by GitHub
Browse files

Implement working* burst/ultimate invincibility

Merge pull request #1622 from Grasscutters/ult-invincibility
parents 423b235c 6ec372e6
...@@ -17,43 +17,84 @@ import emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityM ...@@ -17,43 +17,84 @@ import emu.grasscutter.net.proto.AbilityMetaReInitOverrideMapOuterClass.AbilityM
import emu.grasscutter.net.proto.AbilityMixinCostStaminaOuterClass.AbilityMixinCostStamina; import emu.grasscutter.net.proto.AbilityMixinCostStaminaOuterClass.AbilityMixinCostStamina;
import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry; import emu.grasscutter.net.proto.AbilityScalarValueEntryOuterClass.AbilityScalarValueEntry;
import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction; import emu.grasscutter.net.proto.ModifierActionOuterClass.ModifierAction;
import lombok.Getter;
public class AbilityManager extends BasePlayerManager { public final class AbilityManager extends BasePlayerManager {
HealAbilityManager healAbilityManager; HealAbilityManager healAbilityManager;
@Getter private boolean abilityInvulnerable = false;
public AbilityManager(Player player) { public AbilityManager(Player player) {
super(player); super(player);
this.healAbilityManager = new HealAbilityManager(player); this.healAbilityManager = new HealAbilityManager(player);
} }
public void onAbilityInvoke(AbilityInvokeEntry invoke) throws Exception { public void onAbilityInvoke(AbilityInvokeEntry invoke) throws Exception {
healAbilityManager.healHandler(invoke); this.healAbilityManager.healHandler(invoke);
//Grasscutter.getLogger().info(invoke.getArgumentType() + " (" + invoke.getArgumentTypeValue() + "): " + Utils.bytesToHex(invoke.toByteArray())); //Grasscutter.getLogger().info(invoke.getArgumentType() + " (" + invoke.getArgumentTypeValue() + "): " + Utils.bytesToHex(invoke.toByteArray()));
switch (invoke.getArgumentType()) { switch (invoke.getArgumentType()) {
case ABILITY_INVOKE_ARGUMENT_META_OVERRIDE_PARAM: case ABILITY_INVOKE_ARGUMENT_META_OVERRIDE_PARAM -> this.handleOverrideParam(invoke);
handleOverrideParam(invoke); case ABILITY_INVOKE_ARGUMENT_META_REINIT_OVERRIDEMAP -> this.handleReinitOverrideMap(invoke);
break; case ABILITY_INVOKE_ARGUMENT_META_MODIFIER_CHANGE -> this.handleModifierChange(invoke);
case ABILITY_INVOKE_ARGUMENT_META_REINIT_OVERRIDEMAP: case ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA -> this.handleMixinCostStamina(invoke);
handleReinitOverrideMap(invoke); case ABILITY_INVOKE_ARGUMENT_ACTION_GENERATE_ELEM_BALL -> this.handleGenerateElemBall(invoke);
break; default -> {}
case ABILITY_INVOKE_ARGUMENT_META_MODIFIER_CHANGE: }
handleModifierChange(invoke); }
break;
case ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA: /**
handleMixinCostStamina(invoke); * Invoked when a player starts a skill.
break; * @param player The player who started the skill.
case ABILITY_INVOKE_ARGUMENT_ACTION_GENERATE_ELEM_BALL: * @param skillId The skill ID.
handleGenerateElemBall(invoke); * @param casterId The caster ID.
break; */
default: public void onSkillStart(Player player, int skillId, int casterId) {
break; // Check if the player matches this player.
if (player.getUid() != this.player.getUid()) {
return;
}
// Check if the caster matches the player.
if(player.getTeamManager().getCurrentAvatarEntity().getId() != casterId) {
return;
}
var skillData = GameData.getAvatarSkillDataMap().get(skillId);
if (skillData == null) {
return;
}
// Check if the skill is an elemental burst.
if(skillData.getCostElemVal() <= 0) {
return;
}
// Set the player as invulnerable.
this.abilityInvulnerable = true;
}
/**
* Invoked when a player ends a skill.
* @param player The player who started the skill.
*/
public void onSkillEnd(Player player) {
// Check if the player matches this player.
if (player.getUid() != this.player.getUid()) {
return;
}
// Check if the player is invulnerable.
if(!this.abilityInvulnerable) {
return;
} }
// Set the player as not invulnerable.
this.abilityInvulnerable = false;
} }
private void handleOverrideParam(AbilityInvokeEntry invoke) throws Exception { private void handleOverrideParam(AbilityInvokeEntry invoke) throws Exception {
GameEntity entity = player.getScene().getEntityById(invoke.getEntityId()); GameEntity entity = this.player.getScene().getEntityById(invoke.getEntityId());
if (entity == null) { if (entity == null) {
return; return;
...@@ -65,7 +106,7 @@ public class AbilityManager extends BasePlayerManager { ...@@ -65,7 +106,7 @@ public class AbilityManager extends BasePlayerManager {
} }
private void handleReinitOverrideMap(AbilityInvokeEntry invoke) throws Exception { private void handleReinitOverrideMap(AbilityInvokeEntry invoke) throws Exception {
GameEntity entity = player.getScene().getEntityById(invoke.getEntityId()); GameEntity entity = this.player.getScene().getEntityById(invoke.getEntityId());
if (entity == null) { if (entity == null) {
return; return;
...@@ -80,7 +121,7 @@ public class AbilityManager extends BasePlayerManager { ...@@ -80,7 +121,7 @@ public class AbilityManager extends BasePlayerManager {
private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception { private void handleModifierChange(AbilityInvokeEntry invoke) throws Exception {
// Sanity checks // Sanity checks
GameEntity target = player.getScene().getEntityById(invoke.getEntityId()); GameEntity target = this.player.getScene().getEntityById(invoke.getEntityId());
if (target == null) { if (target == null) {
return; return;
} }
...@@ -104,7 +145,7 @@ public class AbilityManager extends BasePlayerManager { ...@@ -104,7 +145,7 @@ public class AbilityManager extends BasePlayerManager {
return; return;
} }
GameEntity sourceEntity = player.getScene().getEntityById(data.getApplyEntityId()); GameEntity sourceEntity = this.player.getScene().getEntityById(data.getApplyEntityId());
if (sourceEntity == null) { if (sourceEntity == null) {
return; return;
} }
...@@ -117,7 +158,7 @@ public class AbilityManager extends BasePlayerManager { ...@@ -117,7 +158,7 @@ public class AbilityManager extends BasePlayerManager {
if (modifier != null && modifier.getOnAdded().size() > 0) { if (modifier != null && modifier.getOnAdded().size() > 0) {
for (AbilityModifierAction action : modifier.getOnAdded()) { for (AbilityModifierAction action : modifier.getOnAdded()) {
invokeAction(action, target, sourceEntity); this.invokeAction(action, target, sourceEntity);
} }
} }
...@@ -133,7 +174,7 @@ public class AbilityManager extends BasePlayerManager { ...@@ -133,7 +174,7 @@ public class AbilityManager extends BasePlayerManager {
if (modifier != null && modifier.getOnRemoved().size() > 0) { if (modifier != null && modifier.getOnRemoved().size() > 0) {
for (AbilityModifierAction action : modifier.getOnRemoved()) { for (AbilityModifierAction action : modifier.getOnRemoved()) {
invokeAction(action, target, sourceEntity); this.invokeAction(action, target, sourceEntity);
} }
} }
...@@ -145,7 +186,7 @@ public class AbilityManager extends BasePlayerManager { ...@@ -145,7 +186,7 @@ public class AbilityManager extends BasePlayerManager {
private void handleMixinCostStamina(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { private void handleMixinCostStamina(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException {
AbilityMixinCostStamina costStamina = AbilityMixinCostStamina.parseFrom((invoke.getAbilityData())); AbilityMixinCostStamina costStamina = AbilityMixinCostStamina.parseFrom((invoke.getAbilityData()));
getPlayer().getStaminaManager().handleMixinCostStamina(costStamina.getIsSwim()); this.getPlayer().getStaminaManager().handleMixinCostStamina(costStamina.getIsSwim());
} }
private void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { private void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException {
......
...@@ -17,6 +17,10 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler { ...@@ -17,6 +17,10 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload); ClientAbilityInitFinishNotify notif = ClientAbilityInitFinishNotify.parseFrom(payload);
Player player = session.getPlayer(); Player player = session.getPlayer();
// Call skill end in the player's ability manager.
player.getAbilityManager().onSkillEnd(player);
for (AbilityInvokeEntry entry : notif.getInvokesList()) { for (AbilityInvokeEntry entry : notif.getInvokesList()) {
player.getAbilityManager().onAbilityInvoke(entry); player.getAbilityManager().onAbilityInvoke(entry);
player.getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry); player.getClientAbilityInitFinishHandler().addEntry(entry.getForwardType(), entry);
...@@ -26,5 +30,4 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler { ...@@ -26,5 +30,4 @@ public class HandlerClientAbilityInitFinishNotify extends PacketHandler {
session.getPlayer().getClientAbilityInitFinishHandler().update(session.getPlayer()); session.getPlayer().getClientAbilityInitFinishHandler().update(session.getPlayer());
} }
} }
} }
\ No newline at end of file
...@@ -6,7 +6,6 @@ import emu.grasscutter.game.player.Player; ...@@ -6,7 +6,6 @@ import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.AttackResultOuterClass;
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify;
import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry;
...@@ -18,7 +17,6 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo; ...@@ -18,7 +17,6 @@ import emu.grasscutter.net.proto.MotionInfoOuterClass.MotionInfo;
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass; import emu.grasscutter.net.proto.PlayerDieTypeOuterClass;
import emu.grasscutter.server.event.entity.EntityMoveEvent; import emu.grasscutter.server.event.entity.EntityMoveEvent;
import emu.grasscutter.server.event.game.ReceiveCommandFeedbackEvent;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.utils.Position; import emu.grasscutter.utils.Position;
...@@ -36,16 +34,22 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { ...@@ -36,16 +34,22 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
for (CombatInvokeEntry entry : notif.getInvokeListList()) { for (CombatInvokeEntry entry : notif.getInvokeListList()) {
// Handle combat invoke // Handle combat invoke
switch (entry.getArgumentType()) { switch (entry.getArgumentType()) {
case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT: case COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT -> {
EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData()); EvtBeingHitInfo hitInfo = EvtBeingHitInfo.parseFrom(entry.getCombatData());
AttackResult attackResult = hitInfo.getAttackResult(); AttackResult attackResult = hitInfo.getAttackResult();
Player player = session.getPlayer(); Player player = session.getPlayer();
// Check if the player is invulnerable.
if (
attackResult.getAttackerId() != player.getTeamManager().getCurrentAvatarEntity().getId() &&
player.getAbilityManager().isAbilityInvulnerable()
) break;
// Handle damage // Handle damage
player.getAttackResults().add(attackResult); player.getAttackResults().add(attackResult);
player.getEnergyManager().handleAttackHit(hitInfo); player.getEnergyManager().handleAttackHit(hitInfo);
break; }
case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE: case COMBAT_TYPE_ARGUMENT_ENTITY_MOVE -> {
// Handle movement // Handle movement
EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData());
GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId());
...@@ -90,17 +94,16 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { ...@@ -90,17 +94,16 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
continue; continue;
} }
} }
break; }
case COMBAT_TYPE_ARGUMENT_ANIMATOR_PARAMETER_CHANGED: case COMBAT_TYPE_ARGUMENT_ANIMATOR_PARAMETER_CHANGED -> {
EvtAnimatorParameterInfo paramInfo = EvtAnimatorParameterInfo.parseFrom(entry.getCombatData()); EvtAnimatorParameterInfo paramInfo = EvtAnimatorParameterInfo.parseFrom(entry.getCombatData());
if (paramInfo.getIsServerCache()) { if (paramInfo.getIsServerCache()) {
paramInfo = paramInfo.toBuilder().setIsServerCache(false).build(); paramInfo = paramInfo.toBuilder().setIsServerCache(false).build();
entry = entry.toBuilder().setCombatData(paramInfo.toByteString()).build(); entry = entry.toBuilder().setCombatData(paramInfo.toByteString()).build();
} }
break; }
default: default -> {
break; }
} }
session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry); session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry);
......
...@@ -12,10 +12,16 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler { ...@@ -12,10 +12,16 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler {
@Override @Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
EvtDoSkillSuccNotify notify = EvtDoSkillSuccNotify.parseFrom(payload); EvtDoSkillSuccNotify notify = EvtDoSkillSuccNotify.parseFrom(payload);
var player = session.getPlayer();
int skillId = notify.getSkillId(); int skillId = notify.getSkillId();
int casterId = notify.getCasterId(); int casterId = notify.getCasterId();
session.getPlayer().getStaminaManager().handleEvtDoSkillSuccNotify(session, skillId, casterId); // Call skill perform in the player's ability manager.
session.getPlayer().getEnergyManager().handleEvtDoSkillSuccNotify(session, skillId, casterId); player.getAbilityManager().onSkillStart(session.getPlayer(), skillId, casterId);
// Handle skill notify in other managers.
player.getStaminaManager().handleEvtDoSkillSuccNotify(session, skillId, casterId);
player.getEnergyManager().handleEvtDoSkillSuccNotify(session, skillId, casterId);
} }
} }
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment