mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-25 20:56:28 +00:00
Implementes auto HP recovery at the statues.
- Respects player setting. - SP + MP. - Statue has unlimited HP volume (to be updated)
This commit is contained in:
parent
2ad6f5934b
commit
198214ec53
@ -0,0 +1,118 @@
|
||||
package emu.grasscutter.game.managers.SotSManager;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
import emu.grasscutter.net.proto.ChangeHpReasonOuterClass;
|
||||
import emu.grasscutter.net.proto.PropChangeReasonOuterClass;
|
||||
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;
|
||||
|
||||
// Statue of the Seven Manager
|
||||
public class SotSManager {
|
||||
|
||||
private final Player player;
|
||||
|
||||
public SotSManager(Player player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public boolean getIsAutoRecoveryEnabled() {
|
||||
return player.getProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE) == 1;
|
||||
}
|
||||
|
||||
public void setIsAutoRecoveryEnabled(boolean enabled) {
|
||||
player.setProperty(PlayerProperty.PROP_IS_SPRING_AUTO_USE, enabled ? 1 : 0);
|
||||
}
|
||||
|
||||
public int getAutoRecoveryPercentage() {
|
||||
return player.getProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT);
|
||||
}
|
||||
|
||||
public void setAutoRecoveryPercentage(int percentage) {
|
||||
player.setProperty(PlayerProperty.PROP_SPRING_AUTO_USE_PERCENT, percentage);
|
||||
}
|
||||
|
||||
// autoRevive automatically revives all team members.
|
||||
public void autoRevive(GameSession session) {
|
||||
player.getTeamManager().getActiveTeam().forEach(entity -> {
|
||||
boolean isAlive = entity.isAlive();
|
||||
if (!isAlive) {
|
||||
float maxHP = entity.getAvatar().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, Math.min(150, maxHP));
|
||||
entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void scheduleAutoRecover(GameSession session) {
|
||||
// TODO: play audio effects? possibly client side? - client automatically plays.
|
||||
// delay 2.5 seconds
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(2500);
|
||||
autoRecover(session);
|
||||
} catch (Exception e) {
|
||||
Grasscutter.getLogger().error(e.getMessage());
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
// autoRecover checks player setting to see if auto recover is enabled, and refill HP to the predefined level.
|
||||
public void autoRecover(GameSession session) {
|
||||
// TODO: Implement SotS Spring volume refill over time.
|
||||
// Placeholder:
|
||||
player.setProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME, 8500000);
|
||||
player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, 8500000);
|
||||
|
||||
// TODO: In MP, respect SotS settings from the host.
|
||||
boolean isAutoRecoveryEnabled = getIsAutoRecoveryEnabled();
|
||||
int autoRecoverPercentage = getAutoRecoveryPercentage();
|
||||
Grasscutter.getLogger().warn("isAutoRecoveryEnabled: " + isAutoRecoveryEnabled + "\tautoRecoverPercentage: " + autoRecoverPercentage);
|
||||
|
||||
if (isAutoRecoveryEnabled) {
|
||||
player.getTeamManager().getActiveTeam().forEach(entity -> {
|
||||
float maxHP = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
|
||||
float currentHP = entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
|
||||
if (currentHP == maxHP) {
|
||||
return;
|
||||
}
|
||||
float targetHP = maxHP * autoRecoverPercentage / 100;
|
||||
|
||||
if (targetHP > currentHP) {
|
||||
float needHP = targetHP - currentHP;
|
||||
|
||||
int sotsHPBalance = player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME);
|
||||
if (sotsHPBalance >= needHP) {
|
||||
sotsHPBalance -= needHP;
|
||||
player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, sotsHPBalance);
|
||||
|
||||
float newHP = currentHP + needHP;
|
||||
|
||||
session.send(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_MAX_HP));
|
||||
session.send(new PacketEntityFightPropChangeReasonNotify(entity, FightProperty.FIGHT_PROP_CUR_HP,
|
||||
newHP, List.of(3), PropChangeReasonOuterClass.PropChangeReason.PROP_CHANGE_STATUE_RECOVER,
|
||||
ChangeHpReasonOuterClass.ChangeHpReason.ChangeHpAddStatue));
|
||||
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP);
|
||||
|
||||
Avatar avatar = entity.getAvatar();
|
||||
session.send(new PacketAvatarFightPropUpdateNotify(avatar, FightProperty.FIGHT_PROP_CUR_HP));
|
||||
avatar.setCurrentHp(newHP);
|
||||
|
||||
player.save();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -22,6 +22,7 @@ import emu.grasscutter.game.inventory.Inventory;
|
||||
import emu.grasscutter.game.mail.Mail;
|
||||
import emu.grasscutter.game.mail.MailHandler;
|
||||
import emu.grasscutter.game.managers.MovementManager.MovementManager;
|
||||
import emu.grasscutter.game.managers.SotSManager.SotSManager;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.EntityType;
|
||||
import emu.grasscutter.game.props.PlayerProperty;
|
||||
@ -89,6 +90,8 @@ public class Player {
|
||||
@Transient private MailHandler mailHandler;
|
||||
@Transient private MessageHandler messageHandler;
|
||||
|
||||
@Transient private SotSManager sotsManager;
|
||||
|
||||
private TeamManager teamManager;
|
||||
|
||||
private TowerManager towerManager;
|
||||
@ -168,6 +171,7 @@ public class Player {
|
||||
this.messageHandler = null;
|
||||
this.mapMarksManager = new MapMarksManager();
|
||||
this.movementManager = new MovementManager(this);
|
||||
this.sotsManager = new SotSManager(this);
|
||||
}
|
||||
|
||||
// On player creation
|
||||
@ -196,6 +200,7 @@ public class Player {
|
||||
this.messageHandler = null;
|
||||
this.mapMarksManager = new MapMarksManager();
|
||||
this.movementManager = new MovementManager(this);
|
||||
this.sotsManager = new SotSManager(this);
|
||||
}
|
||||
|
||||
public int getUid() {
|
||||
@ -984,6 +989,8 @@ public class Player {
|
||||
|
||||
public MovementManager getMovementManager() { return movementManager; }
|
||||
|
||||
public SotSManager getSotSManager() { return sotsManager; }
|
||||
|
||||
public synchronized void onTick() {
|
||||
// Check ping
|
||||
if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
|
||||
|
@ -1,5 +1,7 @@
|
||||
package emu.grasscutter.server.packet.recv;
|
||||
|
||||
import emu.grasscutter.game.managers.SotSManager.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;
|
||||
@ -18,26 +20,10 @@ import java.util.List;
|
||||
public class HandlerEnterTransPointRegionNotify extends PacketHandler {
|
||||
@Override
|
||||
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{
|
||||
session.getPlayer().getTeamManager().getActiveTeam().forEach(entity -> {
|
||||
boolean isAlive = entity.isAlive();
|
||||
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()));
|
||||
}
|
||||
}
|
||||
});
|
||||
Player player = session.getPlayer();
|
||||
SotSManager sotsManager = player.getSotSManager();
|
||||
sotsManager.autoRevive(session);
|
||||
sotsManager.scheduleAutoRecover(session);
|
||||
// TODO: allow interaction with the SotS?
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user