mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-19 10:24:47 +01:00
Merge remote-tracking branch 'origin/development' into tower
This commit is contained in:
@@ -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.FightProperty;
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
import emu.grasscutter.net.proto.CombatInvocationsNotifyOuterClass.CombatInvocationsNotify;
|
||||
@@ -8,11 +10,19 @@ 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.MotionInfoOuterClass.MotionInfo;
|
||||
import emu.grasscutter.net.proto.MotionStateOuterClass.MotionState;
|
||||
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass;
|
||||
import emu.grasscutter.server.game.GameSession;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
|
||||
@Opcodes(PacketOpcodes.CombatInvocationsNotify)
|
||||
public class HandlerCombatInvocationsNotify extends PacketHandler {
|
||||
|
||||
private float cachedLandingSpeed = 0;
|
||||
private long cachedLandingTimeMillisecond = 0;
|
||||
private boolean monitorLandingEvent = false;
|
||||
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
|
||||
CombatInvocationsNotify notif = CombatInvocationsNotify.parseFrom(payload);
|
||||
@@ -28,7 +38,34 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
|
||||
EntityMoveInfo moveInfo = EntityMoveInfo.parseFrom(entry.getCombatData());
|
||||
GameEntity entity = session.getPlayer().getScene().getEntityById(moveInfo.getEntityId());
|
||||
if (entity != null) {
|
||||
session.getPlayer().getMovementManager().handle(session, moveInfo, entity);
|
||||
// Move player
|
||||
MotionInfo motionInfo = moveInfo.getMotionInfo();
|
||||
entity.getPosition().set(motionInfo.getPos());
|
||||
entity.getRotation().set(motionInfo.getRot());
|
||||
entity.setLastMoveSceneTimeMs(moveInfo.getSceneTime());
|
||||
entity.setLastMoveReliableSeq(moveInfo.getReliableSeq());
|
||||
MotionState motionState = motionInfo.getState();
|
||||
entity.setMotionState(motionState);
|
||||
|
||||
session.getPlayer().getStaminaManager().handleCombatInvocationsNotify(session, moveInfo, entity);
|
||||
|
||||
// TODO: handle MOTION_FIGHT landing which has a different damage factor
|
||||
// Also, for plunge attacks, LAND_SPEED is always -30 and is not useful.
|
||||
// May need the height when starting plunge attack.
|
||||
|
||||
// MOTION_LAND_SPEED and MOTION_FALL_ON_GROUND arrive in different packets.
|
||||
// Cache land speed for later use.
|
||||
if (motionState == MotionState.MOTION_LAND_SPEED) {
|
||||
cachedLandingSpeed = motionInfo.getSpeed().getY();
|
||||
cachedLandingTimeMillisecond = System.currentTimeMillis();
|
||||
monitorLandingEvent = true;
|
||||
}
|
||||
if (monitorLandingEvent) {
|
||||
if (motionState == MotionState.MOTION_FALL_ON_GROUND) {
|
||||
monitorLandingEvent = false;
|
||||
handleFallOnGround(session, entity, motionState);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -47,5 +84,48 @@ public class HandlerCombatInvocationsNotify extends PacketHandler {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void handleFallOnGround(GameSession session, GameEntity entity, MotionState motionState) {
|
||||
// People have reported that after plunge attack (client sends a FIGHT instead of FALL_ON_GROUND) they will die
|
||||
// if they talk to an NPC (this is when the client sends a FALL_ON_GROUND) without jumping again.
|
||||
// A dirty patch: if not received immediately after MOTION_LAND_SPEED, discard this packet.
|
||||
// 200ms seems to be a reasonable delay.
|
||||
int maxDelay = 200;
|
||||
long actualDelay = System.currentTimeMillis() - cachedLandingTimeMillisecond;
|
||||
Grasscutter.getLogger().trace("MOTION_FALL_ON_GROUND received after " + actualDelay + "/" + maxDelay + "ms." + (actualDelay > maxDelay ? " Discard" : ""));
|
||||
if (actualDelay > maxDelay) {
|
||||
return;
|
||||
}
|
||||
float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
|
||||
float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
|
||||
float damageFactor = 0;
|
||||
if (cachedLandingSpeed < -23.5) {
|
||||
damageFactor = 0.33f;
|
||||
}
|
||||
if (cachedLandingSpeed < -25) {
|
||||
damageFactor = 0.5f;
|
||||
}
|
||||
if (cachedLandingSpeed < -26.5) {
|
||||
damageFactor = 0.66f;
|
||||
}
|
||||
if (cachedLandingSpeed < -28) {
|
||||
damageFactor = 1f;
|
||||
}
|
||||
float damage = maxHP * damageFactor;
|
||||
float newHP = currentHP - damage;
|
||||
if (newHP < 0) {
|
||||
newHP = 0;
|
||||
}
|
||||
if (damageFactor > 0) {
|
||||
Grasscutter.getLogger().debug(currentHP + "/" + maxHP + "\tLandingSpeed: " + cachedLandingSpeed +
|
||||
"\tDamageFactor: " + damageFactor + "\tDamage: " + damage + "\tNewHP: " + newHP);
|
||||
} else {
|
||||
Grasscutter.getLogger().trace(currentHP + "/" + maxHP + "\tLandingSpeed: 0\tNo damage");
|
||||
}
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP);
|
||||
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
if (newHP == 0) {
|
||||
session.getPlayer().getStaminaManager().killAvatar(session, entity, PlayerDieTypeOuterClass.PlayerDieType.PLAYER_DIE_FALL);
|
||||
}
|
||||
cachedLandingSpeed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.game.managers.SotSManager.SotSManager;
|
||||
import emu.grasscutter.game.managers.SotSManager;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
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 {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
import emu.grasscutter.net.packet.PacketOpcodes;
|
||||
@@ -15,10 +14,7 @@ public class HandlerEvtDoSkillSuccNotify extends PacketHandler {
|
||||
EvtDoSkillSuccNotify notify = EvtDoSkillSuccNotify.parseFrom(payload);
|
||||
// TODO: Will be used for deducting stamina for charged skills.
|
||||
|
||||
int caster = notify.getCasterId();
|
||||
int skillId = notify.getSkillId();
|
||||
|
||||
session.getPlayer().getMovementManager().notifySkill(caster, skillId);
|
||||
session.getPlayer().getStaminaManager().handleEvtDoSkillSuccNotify(session, notify);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.game.managers.SotSManager.SotSManager;
|
||||
import emu.grasscutter.game.managers.SotSManager;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.net.packet.Opcodes;
|
||||
import emu.grasscutter.net.packet.PacketHandler;
|
||||
|
||||
Reference in New Issue
Block a user