From 2074933e969580ef9e5c9512f8dab1a1189c522d Mon Sep 17 00:00:00 2001 From: BaiSugar <97774724+BaiSugar@users.noreply.github.com> Date: Thu, 5 May 2022 02:45:20 +0800 Subject: [PATCH] Add the god statue's blood return display and stamina system (#520) * Fix announcement display * Approaching StatuesOfTheSeven will restore all health of the current team * Added god statue's blood return display and stamina system * fix error fix error * fix file --- src/main/java/emu/grasscutter/Config.java | 1 + .../recv/HandlerCombatInvocationsNotify.java | 85 +++++++++++++++++-- .../HandlerEnterTransPointRegionNotify.java | 30 +++++-- .../PacketAvatarLifeStateChangeNotify.java | 14 +++ ...cketEntityFightPropChangeReasonNotify.java | 38 +++++++++ 5 files changed, 154 insertions(+), 14 deletions(-) create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java diff --git a/src/main/java/emu/grasscutter/Config.java b/src/main/java/emu/grasscutter/Config.java index 4504df2aa..467d0f04e 100644 --- a/src/main/java/emu/grasscutter/Config.java +++ b/src/main/java/emu/grasscutter/Config.java @@ -24,6 +24,7 @@ public final class Config { public DispatchServerOptions DispatchServer = new DispatchServerOptions(); public String Language = "en_us"; + public Boolean OpenStamina = true; public GameServerOptions getGameServerOptions() { return GameServer; } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java index d62d9fc6f..2d0ceac8b 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombatInvocationsNotify.java @@ -1,6 +1,8 @@ package emu.grasscutter.server.packet.recv; +import emu.grasscutter.Grasscutter; import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify; @@ -8,15 +10,20 @@ import emu.grasscutter.net.proto.CombatInvokeEntryOuterClass.CombatInvokeEntry; import emu.grasscutter.net.proto.EntityMoveInfoOuterClass.EntityMoveInfo; import emu.grasscutter.net.proto.EvtBeingHitInfoOuterClass.EvtBeingHitInfo; import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState; +import emu.grasscutter.net.proto.VectorOuterClass.Vector; import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.*; + +import java.util.Arrays; +import java.util.Collection; @Opcodes(PacketOpcodes.CombatInvocationsNotify) public class HandlerCombatInvocationsNotify extends PacketHandler { - + @Override public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload); - for (CombatInvokeEntry entry : notif.getInvokeListList()) { switch (entry.getArgumentType()) { case COMBAT_EVT_BEING_HIT: @@ -28,29 +35,93 @@ public class HandlerCombatInvocationsNotify extends PacketHandler { // Handle movement EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData()); GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId()); + MotionState state = moveInfo.getMotionInfo().getState(); if (entity != null) { + //move entity.getPosition().set(moveInfo.getMotionInfo().getPos()); entity.getRotation().set(moveInfo.getMotionInfo().getRot()); entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime()); entity.setLastMoveReliableSeq(moveInfo.getReliableSeq()); entity.setMotionState(moveInfo.getMotionInfo().getState()); + + if(Grasscutter.getConfig().OpenStamina){ + //consume stamina + int curStamina = session.getPlayer().getProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA); + int maxStamina = session.getPlayer().getProperty(PlayerProperty.PROP_MAX_STAMINA); + if (CONSUME_STAMINA_LIST.contains(state)) { + + //In the water exhausted stamina + + //Climbing the wall stays in place + + //Sprint in the water + if (state == MotionState.MOTION_SWIM_DASH) { + curStamina -= 700; + } + //wall jump + else if (state == MotionState.MOTION_CLIMB_JUMP) { + curStamina -= 2000; + } + //climb the wall slowly + else if (state == MotionState.MOTION_CLIMB) { + curStamina -= 800; + } + else if (state == MotionState.MOTION_DASH_BEFORE_SHAKE) { + curStamina -= 2500; + } + else { + curStamina -= 500; + } + + session.getPlayer().setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA, curStamina); + session.send(new PacketPlayerPropNotify(session.getPlayer(), PlayerProperty.PROP_CUR_PERSIST_STAMINA)); + break; + } + //restore stamina + if (RESTORE_STAMINA_LIST.contains(state)) { + if(state == MotionState.MOTION_STANDBY) { + Vector speed = moveInfo.getMotionInfo().getSpeed(); + if(speed.getX() != 0 && speed.getZ() != 0 && speed.getY() != 0) { + break; + } + } + curStamina += 1000; + if (curStamina >= maxStamina) { + curStamina = maxStamina; + } + session.getPlayer().setProperty(PlayerProperty.PROP_CUR_PERSIST_STAMINA, curStamina); + session.send(new PacketPlayerPropNotify(session.getPlayer(), PlayerProperty.PROP_CUR_PERSIST_STAMINA)); + } + } } break; default: break; } - + session.getPlayer().getCombatInvokeHandler().addEntry(entry.getForwardType(), entry); } - - // Handles sending combat invokes to other players/server + if (notif.getInvokeListList().size() > 0) { session.getPlayer().getCombatInvokeHandler().update(session.getPlayer()); } - - // Handle attack results last + // Handle attack results last while (!session.getPlayer().getAttackResults().isEmpty()) { session.getPlayer().getScene().handleAttack(session.getPlayer().getAttackResults().poll()); } } + + private static MotionState[] consumeStaminaTypes = new MotionState[]{ + MotionState.MOTION_CLIMB, MotionState.MOTION_CLIMB_JUMP, MotionState.MOTION_SWIM_DASH, + MotionState.MOTION_SWIM_MOVE, MotionState.MOTION_FLY, MotionState.MOTION_DASH, + MotionState.MOTION_DASH_BEFORE_SHAKE, MotionState.MOTION_FIGHT, MotionState.MOTION_JUMP_UP_WALL_FOR_STANDBY, + MotionState.MOTION_FLY_SLOW + }; + private static MotionState[] restoreStaminaTypes = new MotionState[]{ + MotionState.MOTION_STANDBY, MotionState.MOTION_RUN, MotionState.MOTION_WALK, + MotionState.MOTION_STANDBY_MOVE + }; + + private static final Collection CONSUME_STAMINA_LIST = Arrays.asList(consumeStaminaTypes); + private static final Collection RESTORE_STAMINA_LIST = Arrays.asList(restoreStaminaTypes); } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java index de874cd7e..2c946e1fa 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerEnterTransPointRegionNotify.java @@ -4,9 +4,15 @@ import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.net.packet.Opcodes; import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify; +import emu.grasscutter.server.packet.send.PacketEntityFightPropChangeReasonNotify; +import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; + +import java.util.List; @Opcodes(PacketOpcodes.EnterTransPointRegionNotify) public class HandlerEnterTransPointRegionNotify extends PacketHandler { @@ -14,13 +20,23 @@ public class HandlerEnterTransPointRegionNotify extends PacketHandler { public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{ session.getPlayer().getTeamManager().getActiveTeam().forEach(entity -> { boolean isAlive = entity.isAlive(); - entity.setFightProperty( - FightProperty.FIGHT_PROP_CUR_HP, - entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) - ); - entity.getWorld().broadcastPacket(new PacketAvatarFightPropUpdateNotify(entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); - if (!isAlive) { - entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); + if(entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) != entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP)){ + Float hp = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP)-entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP); + + session.send(new PacketEntityFightPropUpdateNotify(entity,FightProperty.FIGHT_PROP_MAX_HP)); + + session.send(new PacketEntityFightPropChangeReasonNotify( + entity, FightProperty.FIGHT_PROP_CUR_HP, hp, List.of(3), + PropChangeReason.PROP_CHANGE_STATUE_RECOVER, ChangeHpReason.ChangeHpAddStatue)); + + entity.setFightProperty( + FightProperty.FIGHT_PROP_CUR_HP, + entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP) + ); + session.send(new PacketAvatarFightPropUpdateNotify(entity.getAvatar(), FightProperty.FIGHT_PROP_CUR_HP)); + if (!isAlive) { + entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); + } } }); } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java index fcdce2b9a..3032bf355 100644 --- a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarLifeStateChangeNotify.java @@ -1,11 +1,14 @@ package emu.grasscutter.server.packet.send; import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.LifeState; import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.proto.AvatarLifeStateChangeNotifyOuterClass.AvatarLifeStateChangeNotify; +import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType; public class PacketAvatarLifeStateChangeNotify extends BasePacket { @@ -19,4 +22,15 @@ public class PacketAvatarLifeStateChangeNotify extends BasePacket { this.setData(proto); } + public PacketAvatarLifeStateChangeNotify(Avatar avatar,int attackerId,LifeState lifeState) { + super(PacketOpcodes.AvatarLifeStateChangeNotify); + + AvatarLifeStateChangeNotify proto = AvatarLifeStateChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setLifeState(lifeState.getValue()) + .setMoveReliableSeq(attackerId) + .build(); + + this.setData(proto); + } } diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java new file mode 100644 index 000000000..5778f711a --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketEntityFightPropChangeReasonNotify.java @@ -0,0 +1,38 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.entity.GameEntity; +import emu.grasscutter.game.props.FightProperty; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.ChangeHpReasonOuterClass.ChangeHpReason; +import emu.grasscutter.net.proto.EntityFightPropChangeReasonNotifyOuterClass.EntityFightPropChangeReasonNotify; +import emu.grasscutter.net.proto.PropChangeReasonOuterClass.PropChangeReason; + +import java.util.List; + +public class PacketEntityFightPropChangeReasonNotify extends BasePacket { + public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, List param, PropChangeReason reason, ChangeHpReason changeHpReason) { + super(PacketOpcodes.EntityFightPropChangeReasonNotify); + EntityFightPropChangeReasonNotify.Builder proto = EntityFightPropChangeReasonNotify.newBuilder() + .setEntityId(entity.getId()) + .setPropType(prop.getId()) + .setPropDelta(value) + .setReason(reason) + .setChangeHpReason(changeHpReason); + for(int p: param){ + proto.addParamList(p); + } + this.setData(proto); + } + public PacketEntityFightPropChangeReasonNotify(GameEntity entity, FightProperty prop, Float value, PropChangeReason reason, ChangeHpReason changeHpReason) { + super(PacketOpcodes.EntityFightPropChangeReasonNotify); + EntityFightPropChangeReasonNotify proto = EntityFightPropChangeReasonNotify.newBuilder() + .setEntityId(entity.getId()) + .setPropType(prop.getId()) + .setPropDelta(value) + .setReason(reason) + .setChangeHpReason(changeHpReason) + .build(); + this.setData(proto); + } +}