mirror of
https://github.com/Melledy/Grasscutter.git
synced 2024-11-27 20:08:09 +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
39a49ae964
commit
39c932b041
@ -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.Mail;
|
||||||
import emu.grasscutter.game.mail.MailHandler;
|
import emu.grasscutter.game.mail.MailHandler;
|
||||||
import emu.grasscutter.game.managers.MovementManager.MovementManager;
|
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.ActionReason;
|
||||||
import emu.grasscutter.game.props.EntityType;
|
import emu.grasscutter.game.props.EntityType;
|
||||||
import emu.grasscutter.game.props.PlayerProperty;
|
import emu.grasscutter.game.props.PlayerProperty;
|
||||||
@ -89,6 +90,8 @@ public class Player {
|
|||||||
@Transient private MailHandler mailHandler;
|
@Transient private MailHandler mailHandler;
|
||||||
@Transient private MessageHandler messageHandler;
|
@Transient private MessageHandler messageHandler;
|
||||||
|
|
||||||
|
@Transient private SotSManager sotsManager;
|
||||||
|
|
||||||
private TeamManager teamManager;
|
private TeamManager teamManager;
|
||||||
|
|
||||||
private TowerManager towerManager;
|
private TowerManager towerManager;
|
||||||
@ -168,6 +171,7 @@ public class Player {
|
|||||||
this.messageHandler = null;
|
this.messageHandler = null;
|
||||||
this.mapMarksManager = new MapMarksManager();
|
this.mapMarksManager = new MapMarksManager();
|
||||||
this.movementManager = new MovementManager(this);
|
this.movementManager = new MovementManager(this);
|
||||||
|
this.sotsManager = new SotSManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// On player creation
|
// On player creation
|
||||||
@ -196,6 +200,7 @@ public class Player {
|
|||||||
this.messageHandler = null;
|
this.messageHandler = null;
|
||||||
this.mapMarksManager = new MapMarksManager();
|
this.mapMarksManager = new MapMarksManager();
|
||||||
this.movementManager = new MovementManager(this);
|
this.movementManager = new MovementManager(this);
|
||||||
|
this.sotsManager = new SotSManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getUid() {
|
public int getUid() {
|
||||||
@ -984,6 +989,8 @@ public class Player {
|
|||||||
|
|
||||||
public MovementManager getMovementManager() { return movementManager; }
|
public MovementManager getMovementManager() { return movementManager; }
|
||||||
|
|
||||||
|
public SotSManager getSotSManager() { return sotsManager; }
|
||||||
|
|
||||||
public synchronized void onTick() {
|
public synchronized void onTick() {
|
||||||
// Check ping
|
// Check ping
|
||||||
if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
|
if (this.getLastPingTime() > System.currentTimeMillis() + 60000) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package emu.grasscutter.server.packet.recv;
|
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.game.props.FightProperty;
|
||||||
import emu.grasscutter.net.packet.Opcodes;
|
import emu.grasscutter.net.packet.Opcodes;
|
||||||
import emu.grasscutter.net.packet.PacketHandler;
|
import emu.grasscutter.net.packet.PacketHandler;
|
||||||
@ -18,26 +20,10 @@ import java.util.List;
|
|||||||
public class HandlerEnterTransPointRegionNotify extends PacketHandler {
|
public class HandlerEnterTransPointRegionNotify 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{
|
||||||
session.getPlayer().getTeamManager().getActiveTeam().forEach(entity -> {
|
Player player = session.getPlayer();
|
||||||
boolean isAlive = entity.isAlive();
|
SotSManager sotsManager = player.getSotSManager();
|
||||||
if(entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP) != entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP)){
|
sotsManager.autoRevive(session);
|
||||||
Float hp = entity.getFightProperty(FightProperty.FIGHT_PROP_MAX_HP)-entity.getFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
|
sotsManager.scheduleAutoRecover(session);
|
||||||
|
// TODO: allow interaction with the SotS?
|
||||||
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()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user