From 28323fed668fb5b7b319cce9b3ad5a096f40b04a Mon Sep 17 00:00:00 2001 From: ImmuState Date: Sat, 21 May 2022 10:08:21 -0700 Subject: [PATCH] Move energy-related logic to a new EnergyManager. --- .../game/ability/AbilityManager.java | 86 +------- .../emu/grasscutter/game/avatar/Avatar.java | 3 +- .../grasscutter/game/entity/EntityAvatar.java | 30 ++- .../grasscutter/game/inventory/Inventory.java | 2 +- .../game/managers/EnergyManager.java | 199 ++++++++++++++++++ .../emu/grasscutter/game/player/Player.java | 8 + .../grasscutter/game/player/TeamManager.java | 60 ------ .../recv/HandlerEvtDoSkillSuccNotify.java | 7 +- 8 files changed, 233 insertions(+), 162 deletions(-) create mode 100644 src/main/java/emu/grasscutter/game/managers/EnergyManager.java diff --git a/src/main/java/emu/grasscutter/game/ability/AbilityManager.java b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java index c0d5e9f06..ae67deb19 100644 --- a/src/main/java/emu/grasscutter/game/ability/AbilityManager.java +++ b/src/main/java/emu/grasscutter/game/ability/AbilityManager.java @@ -147,93 +147,9 @@ public class AbilityManager { AbilityMixinCostStamina costStamina = AbilityMixinCostStamina.parseFrom((invoke.getAbilityData())); getPlayer().getStaminaManager().handleMixinCostStamina(costStamina.getIsSwim()); } - - private int getCastingAvatarIdForElemBall(int invokeEntityId) { - // To determine the avatar that has cast the skill that caused the energy particle to be generated, - // we have to look at the entity that has invoked the ability. This can either be that avatar directly, - // or it can be an `EntityClientGadget`, owned (some way up the owner hierarchy) by the avatar - // that cast the skill. - int res = 0; - - // Try to get the invoking entity from the scene. - GameEntity entity = player.getScene().getEntityById(invokeEntityId); - - // If this entity is null, or not an `EntityClientGadget`, we assume that we are directly - // looking at the casting avatar. - if (!(entity instanceof EntityClientGadget)) { - res = invokeEntityId; - } - // If the entity is a `EntityClientGadget`, we need to "walk up" the owner hierarchy, - // until the owner is no longer a gadget. This should then be the ID of the casting avatar. - else { - while (entity instanceof EntityClientGadget gadget) { - res = gadget.getOwnerEntityId(); - entity = player.getScene().getEntityById(gadget.getOwnerEntityId()); - } - } - - return res; - } private void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { - // Get action info. - AbilityActionGenerateElemBall action = AbilityActionGenerateElemBall.parseFrom(invoke.getAbilityData()); - if (action == null) { - return; - } - - // Determine the element of the energy particle that we have to generate. - // In case we can't, we default to an elementless particle. - // The element is the element of the avatar that has cast the ability. - // We can get that from the avatar's skill depot. - int itemId = 2024; - - // Try to fetch the avatar from the player's party and determine their element. - // ToDo: Does this work in co-op? - int avatarId = getCastingAvatarIdForElemBall(invoke.getEntityId()); - Optional avatarEntity = player.getTeamManager().getActiveTeam() - .stream() - .filter(character -> character.getId() == avatarId) - .findFirst(); - - if (avatarEntity.isPresent()) { - Avatar avatar = avatarEntity.get().getAvatar(); - - if (avatar != null) { - AvatarSkillDepotData skillDepotData = avatar.getSkillDepot(); - - if (skillDepotData != null) { - ElementType element = skillDepotData.getElementType(); - - // If we found the element, we use it to deterine the ID of the - // energy particle that we have to generate. - if (element != null) { - itemId = switch (element) { - case Fire -> 2017; - case Water -> 2018; - case Grass -> 2019; - case Electric -> 2020; - case Wind -> 2021; - case Ice -> 2022; - case Rock -> 2023; - default -> 2024; - }; - } - } - } - } - - // Get the item data for an energy particle of the correct element. - ItemData itemData = GameData.getItemDataMap().get(itemId); - if (itemData == null) { - return; // Should never happen - } - - // Generate entity. - EntityItem energyBall = new EntityItem(getPlayer().getScene(), getPlayer(), itemData, new Position(action.getPos()), 1); - energyBall.getRotation().set(action.getRot()); - - getPlayer().getScene().addEntity(energyBall); + this.player.getEnergyManager().handleGenerateElemBall(invoke); } private void invokeAction(AbilityModifierAction action, GameEntity target, GameEntity sourceEntity) { diff --git a/src/main/java/emu/grasscutter/game/avatar/Avatar.java b/src/main/java/emu/grasscutter/game/avatar/Avatar.java index ed6dd006f..f8f4e2358 100644 --- a/src/main/java/emu/grasscutter/game/avatar/Avatar.java +++ b/src/main/java/emu/grasscutter/game/avatar/Avatar.java @@ -16,6 +16,7 @@ import dev.morphia.annotations.Indexed; import dev.morphia.annotations.PostLoad; import dev.morphia.annotations.PrePersist; import dev.morphia.annotations.Transient; +import emu.grasscutter.Grasscutter; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.FightPropData; import emu.grasscutter.data.custom.OpenConfigEntry; @@ -519,7 +520,7 @@ public class Avatar { if (data.getSkillDepot() != null && data.getSkillDepot().getEnergySkillData() != null) { ElementType element = data.getSkillDepot().getElementType(); this.setFightProperty(element.getMaxEnergyProp(), data.getSkillDepot().getEnergySkillData().getCostElemVal()); - + if (GAME_OPTIONS.energyUsage) { this.setFightProperty(element.getCurEnergyProp(), currentEnergy); } diff --git a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java index e190bb929..6f5822e89 100644 --- a/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java +++ b/src/main/java/emu/grasscutter/game/entity/EntityAvatar.java @@ -129,13 +129,24 @@ public class EntityAvatar extends GameEntity { return healed; } - public void addEnergy(float amount) { - this.addEnergy(amount, false); + public void clearEnergy(PropChangeReason reason) { + FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp(); + this.setFightProperty(curEnergyProp, 0); + + this.getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp)); + this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, 0f, reason)); } - public void addEnergy(float amount, boolean isFlat) { + + public void addEnergy(float amount, PropChangeReason reason) { + this.addEnergy(amount, reason, false); + } + public void addEnergy(float amount, PropChangeReason reason, boolean isFlat) { // Get current and maximum energy for this avatar. - FightProperty curEnergyProp = getAvatar().getSkillDepot().getElementType().getCurEnergyProp(); - FightProperty maxEnergyProp = getAvatar().getSkillDepot().getElementType().getMaxEnergyProp(); + FightProperty curEnergyProp = this.getAvatar().getSkillDepot().getElementType().getCurEnergyProp(); + FightProperty maxEnergyProp = this.getAvatar().getSkillDepot().getElementType().getMaxEnergyProp(); + + float curEnergy = this.getFightProperty(curEnergyProp); + float maxEnergy = this.getFightProperty(maxEnergyProp); // Get energy recharge. float energyRecharge = this.getFightProperty(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY); @@ -146,16 +157,15 @@ public class EntityAvatar extends GameEntity { } // Determine the new energy value. - float curEnergy = this.getFightProperty(curEnergyProp); - float maxEnergy = this.getFightProperty(maxEnergyProp); float newEnergy = Math.min(curEnergy + amount, maxEnergy); // Set energy and notify. + Grasscutter.getLogger().info("Giving {} energy to {} with {} maximum energy, resulting in {} total enery. Energy fight prop: {}", amount, this.getAvatar(), maxEnergy, newEnergy, maxEnergyProp); if (newEnergy != curEnergy) { - setFightProperty(curEnergyProp, newEnergy); + this.setFightProperty(curEnergyProp, newEnergy); - getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(getAvatar(), curEnergyProp)); - getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, PropChangeReason.PROP_CHANGE_ENERGY_BALL)); + this.getScene().broadcastPacket(new PacketAvatarFightPropUpdateNotify(this.getAvatar(), curEnergyProp)); + this.getScene().broadcastPacket(new PacketEntityFightPropChangeReasonNotify(this, curEnergyProp, newEnergy, reason)); } } diff --git a/src/main/java/emu/grasscutter/game/inventory/Inventory.java b/src/main/java/emu/grasscutter/game/inventory/Inventory.java index fb26d5c8d..a2e57cea6 100644 --- a/src/main/java/emu/grasscutter/game/inventory/Inventory.java +++ b/src/main/java/emu/grasscutter/game/inventory/Inventory.java @@ -182,7 +182,7 @@ public class Inventory implements Iterable { this.addVirtualItem(item.getItemId(), item.getCount()); return item; } else if (item.getItemData().getMaterialType() == MaterialType.MATERIAL_ADSORBATE) { - player.getTeamManager().addEnergyToTeam(item); + this.player.getEnergyManager().handlePickupElemBall(item); return null; } else if (item.getItemData().getMaterialType() == MaterialType.MATERIAL_AVATAR) { // Get avatar id diff --git a/src/main/java/emu/grasscutter/game/managers/EnergyManager.java b/src/main/java/emu/grasscutter/game/managers/EnergyManager.java new file mode 100644 index 000000000..dc5544184 --- /dev/null +++ b/src/main/java/emu/grasscutter/game/managers/EnergyManager.java @@ -0,0 +1,199 @@ +package emu.grasscutter.game.managers; + +import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.def.AvatarSkillDepotData; +import emu.grasscutter.data.def.ItemData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.game.entity.EntityClientGadget; +import emu.grasscutter.game.entity.EntityItem; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.inventory.GameItem; +import emu.grasscutter.game.player.Player; +import emu.grasscutter.game.props.ElementType; +import emu.grasscutter.net.proto.AbilityActionGenerateElemBallOuterClass.AbilityActionGenerateElemBall; +import emu.grasscutter.net.proto.AbilityInvokeEntryOuterClass.AbilityInvokeEntry; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.utils.Position; + +import static emu.grasscutter.Configuration.GAME_OPTIONS; + +import java.util.Optional; + +import com.google.protobuf.InvalidProtocolBufferException; + +public class EnergyManager { + private final Player player; + + public EnergyManager(Player player) { + this.player = player; + } + + public Player getPlayer() { + return this.player; + } + + /********** + Particle creation for elemental skills. + **********/ + private int getCastingAvatarIdForElemBall(int invokeEntityId) { + // To determine the avatar that has cast the skill that caused the energy particle to be generated, + // we have to look at the entity that has invoked the ability. This can either be that avatar directly, + // or it can be an `EntityClientGadget`, owned (some way up the owner hierarchy) by the avatar + // that cast the skill. + int res = 0; + + // Try to get the invoking entity from the scene. + GameEntity entity = player.getScene().getEntityById(invokeEntityId); + + // If this entity is null, or not an `EntityClientGadget`, we assume that we are directly + // looking at the casting avatar. + if (!(entity instanceof EntityClientGadget)) { + res = invokeEntityId; + } + // If the entity is a `EntityClientGadget`, we need to "walk up" the owner hierarchy, + // until the owner is no longer a gadget. This should then be the ID of the casting avatar. + else { + while (entity instanceof EntityClientGadget gadget) { + res = gadget.getOwnerEntityId(); + entity = player.getScene().getEntityById(gadget.getOwnerEntityId()); + } + } + + return res; + } + + public void handleGenerateElemBall(AbilityInvokeEntry invoke) throws InvalidProtocolBufferException { + // Get action info. + AbilityActionGenerateElemBall action = AbilityActionGenerateElemBall.parseFrom(invoke.getAbilityData()); + if (action == null) { + return; + } + + // Determine the element of the energy particle that we have to generate. + // In case we can't, we default to an elementless particle. + // The element is the element of the avatar that has cast the ability. + // We can get that from the avatar's skill depot. + int itemId = 2024; + + // Try to fetch the avatar from the player's party and determine their element. + // ToDo: Does this work in co-op? + int avatarId = getCastingAvatarIdForElemBall(invoke.getEntityId()); + Optional avatarEntity = player.getTeamManager().getActiveTeam() + .stream() + .filter(character -> character.getId() == avatarId) + .findFirst(); + + if (avatarEntity.isPresent()) { + Avatar avatar = avatarEntity.get().getAvatar(); + + if (avatar != null) { + AvatarSkillDepotData skillDepotData = avatar.getSkillDepot(); + + if (skillDepotData != null) { + ElementType element = skillDepotData.getElementType(); + + // If we found the element, we use it to deterine the ID of the + // energy particle that we have to generate. + if (element != null) { + itemId = switch (element) { + case Fire -> 2017; + case Water -> 2018; + case Grass -> 2019; + case Electric -> 2020; + case Wind -> 2021; + case Ice -> 2022; + case Rock -> 2023; + default -> 2024; + }; + } + } + } + } + + // Get the item data for an energy particle of the correct element. + ItemData itemData = GameData.getItemDataMap().get(itemId); + if (itemData == null) { + return; // Should never happen + } + + // Generate entity. + EntityItem energyBall = new EntityItem(getPlayer().getScene(), getPlayer(), itemData, new Position(action.getPos()), 1); + energyBall.getRotation().set(action.getRot()); + + this.getPlayer().getScene().addEntity(energyBall); + } + + /********** + Pickup of elemental particles and orbs. + **********/ + public void handlePickupElemBall(GameItem elemBall) { + // Check if the item is indeed an energy particle/orb. + if (elemBall.getItemId() < 2001 ||elemBall.getItemId() > 2024) { + return; + } + + // Determine the base amount of energy given by the particle/orb. + // Particles have a base amount of 1.0, and orbs a base amount of 3.0. + float baseEnergy = (elemBall.getItemId() <= 2008) ? 3.0f : 1.0f; + + // Add energy to every team member. + for (int i = 0; i < this.player.getTeamManager().getActiveTeam().size(); i++) { + EntityAvatar entity = this.player.getTeamManager().getActiveTeam().get(i); + + // On-field vs off-field multiplier. + float offFieldPenalty = (this.player.getTeamManager().getCurrentCharacterIndex() == i) ? 1.0f : 1.0f - this.player.getTeamManager().getActiveTeam().size() * 0.1f; + + // Same element/neutral bonus. + ElementType avatarElement = entity.getAvatar().getSkillDepot().getElementType(); + ElementType ballElement = switch (elemBall.getItemId()) { + case 2001, 2017 -> ElementType.Fire; + case 2002, 2018 -> ElementType.Water; + case 2003, 2019 -> ElementType.Grass; + case 2004, 2020 -> ElementType.Electric; + case 2005, 2021 -> ElementType.Wind; + case 2006, 2022 -> ElementType.Ice; + case 2007, 2023 -> ElementType.Rock; + default -> null; + }; + float elementBonus = (ballElement == null) ? 2.0f : (avatarElement == ballElement) ? 3.0f : 1.0f; + + // Add the energy. + entity.addEnergy(baseEnergy * elementBonus * offFieldPenalty, PropChangeReason.PROP_CHANGE_ENERGY_BALL); + } + } + + + /********** + Energy logic related to using skills. + **********/ + private void handleBurstCast(Avatar avatar, int skillId) { + // Don't do anything if energy usage is disabled. + if (!GAME_OPTIONS.energyUsage) { + return; + } + + // If the cast skill was a burst, consume energy. + if (skillId == avatar.getSkillDepot().getEnergySkill()) { + avatar.getAsEntity().clearEnergy(PropChangeReason.PROP_CHANGE_ABILITY); + } + } + + public void handleEvtDoSkillSuccNotify(GameSession session, int skillId, int casterId) { + // Determine the entity that has cast the skill. Cancel if we can't find that avatar. + Optional caster = this.player.getTeamManager().getActiveTeam().stream() + .filter(character -> character.getId() == casterId) + .findFirst(); + + if (caster.isEmpty()) { + return; + } + + Avatar avatar = caster.get().getAvatar(); + + // Handle elemental burst. + this.handleBurstCast(avatar, skillId); + } +} diff --git a/src/main/java/emu/grasscutter/game/player/Player.java b/src/main/java/emu/grasscutter/game/player/Player.java index 23b32c70f..775d3a9a4 100644 --- a/src/main/java/emu/grasscutter/game/player/Player.java +++ b/src/main/java/emu/grasscutter/game/player/Player.java @@ -24,6 +24,7 @@ import emu.grasscutter.game.inventory.Inventory; import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.mail.MailHandler; import emu.grasscutter.game.managers.StaminaManager.StaminaManager; +import emu.grasscutter.game.managers.EnergyManager; import emu.grasscutter.game.managers.SotSManager; import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.EntityType; @@ -144,6 +145,7 @@ public class Player { @Transient private MapMarksManager mapMarksManager; @Transient private StaminaManager staminaManager; + @Transient private EnergyManager energyManager; private long springLastUsed; private HashMap mapMarks; @@ -194,6 +196,7 @@ public class Player { this.mapMarksManager = new MapMarksManager(this); this.staminaManager = new StaminaManager(this); this.sotsManager = new SotSManager(this); + this.energyManager = new EnergyManager(this); } // On player creation @@ -222,6 +225,7 @@ public class Player { this.mapMarksManager = new MapMarksManager(this); this.staminaManager = new StaminaManager(this); this.sotsManager = new SotSManager(this); + this.energyManager = new EnergyManager(this); } public int getUid() { @@ -1088,6 +1092,10 @@ public class Player { public SotSManager getSotSManager() { return sotsManager; } + public EnergyManager getEnergyManager() { + return this.energyManager; + } + public AbilityManager getAbilityManager() { return abilityManager; } diff --git a/src/main/java/emu/grasscutter/game/player/TeamManager.java b/src/main/java/emu/grasscutter/game/player/TeamManager.java index 3d9806080..be1f2507d 100644 --- a/src/main/java/emu/grasscutter/game/player/TeamManager.java +++ b/src/main/java/emu/grasscutter/game/player/TeamManager.java @@ -4,13 +4,11 @@ import java.util.*; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Transient; -import emu.grasscutter.Grasscutter; import emu.grasscutter.GameConstants; import emu.grasscutter.data.def.AvatarSkillDepotData; import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.entity.EntityAvatar; import emu.grasscutter.game.entity.EntityBaseGadget; -import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.props.ElementType; import emu.grasscutter.game.props.EnterReason; import emu.grasscutter.game.props.FightProperty; @@ -20,7 +18,6 @@ import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; -import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketAvatarDieAnimationEndRsp; import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; @@ -583,63 +580,6 @@ public class TeamManager { // Packets getPlayer().sendPacket(new BasePacket(PacketOpcodes.WorldPlayerReviveRsp)); } - - public synchronized void addEnergyToTeam(GameItem energyBall) { - // Check if the item is indeed an energy particle/orb. - if (energyBall.getItemId() < 2001 ||energyBall.getItemId() > 2024) { - return; - } - - // Determine the base amount of energy given by the particle/orb. - // Particles have a base amount of 1.0, and orbs a base amount of 3.0. - float baseEnergy = (energyBall.getItemId() <= 2008) ? 3.0f : 1.0f; - - // Add energy to every team member. - for (int i = 0; i < this.getActiveTeam().size(); i++) { - EntityAvatar entity = this.getActiveTeam().get(i); - - // On-field vs off-field multiplier. - float offFieldPenalty = (this.getCurrentCharacterIndex() == i) ? 1.0f : 1.0f - this.getActiveTeam().size() * 0.1f; - - // Same element/neutral bonus. - ElementType avatarElement = entity.getAvatar().getSkillDepot().getElementType(); - ElementType ballElement = switch (energyBall.getItemId()) { - case 2001, 2017 -> ElementType.Fire; - case 2002, 2018 -> ElementType.Water; - case 2003, 2019 -> ElementType.Grass; - case 2004, 2020 -> ElementType.Electric; - case 2005, 2021 -> ElementType.Wind; - case 2006, 2022 -> ElementType.Ice; - case 2007, 2023 -> ElementType.Rock; - default -> null; - }; - float elementBonus = (ballElement == null) ? 2.0f : (avatarElement == ballElement) ? 3.0f : 1.0f; - - // Add the energy. - entity.addEnergy(baseEnergy * elementBonus * offFieldPenalty); - } - } - - public void handleEvtDoSkillSuccNotify(GameSession session, int skillId, int casterId) { - if (!GAME_OPTIONS.energyUsage) { - return; - } - - // Determine the entity that has cast the skill. - Optional caster = this.getActiveTeam().stream() - .filter(character -> character.getId() == casterId) - .findFirst(); - if (caster.isEmpty()) { - return; - } - Avatar avatar = caster.get().getAvatar(); - - // If the cast skill was a burst, consume energy. - if (skillId == avatar.getSkillDepot().getEnergySkill()) { - float consumedEnergy = avatar.getFightProperty(avatar.getSkillDepot().getElementType().getCurEnergyProp()); - avatar.getAsEntity().addEnergy(-consumedEnergy, true); - } - } public void saveAvatars() { // Save all avatars from active team diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java index 30f32a8bf..a714d936b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEvtDoSkillSuccNotify.java @@ -4,9 +4,7 @@ import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.EvtDoSkillSuccNotifyOuterClass.EvtDoSkillSuccNotify; -import emu.grasscutter.net.proto.VectorOuterClass.Vector; import emu.grasscutter.server.game.GameSession; -import emu.grasscutter.utils.Position; @Opcodes(PacketOpcodes.EvtDoSkillSuccNotify) public class HandlerEvtDoSkillSuccNotify extends PacketHandler { @@ -16,9 +14,8 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler { EvtDoSkillSuccNotify notify = EvtDoSkillSuccNotify.parseFrom(payload); int skillId = notify.getSkillId(); int casterId = notify.getCasterId(); - Vector forwardVector = notify.getForward(); - Position forward = new Position(forwardVector.getX(), forwardVector.getY(), forwardVector.getZ()); + session.getPlayer().getStaminaManager().handleEvtDoSkillSuccNotify(session, skillId, casterId); - session.getPlayer().getTeamManager().handleEvtDoSkillSuccNotify(session, skillId, casterId); + session.getPlayer().getEnergyManager().handleEvtDoSkillSuccNotify(session, skillId, casterId); } }