Commit 2e685785 authored by gentlespoon's avatar gentlespoon Committed by Melledy
Browse files

The statues will now automatically regen their HP volume over time.

Max is currently set to 85000 for everyone. Will update after implementing statue levels.
parent b760fb1b
...@@ -18,6 +18,8 @@ import java.util.List; ...@@ -18,6 +18,8 @@ import java.util.List;
// Statue of the Seven Manager // Statue of the Seven Manager
public class SotSManager { public class SotSManager {
// NOTE: Spring volume balance *1 = fight prop HP *100
private final Player player; private final Player player;
public SotSManager(Player player) { public SotSManager(Player player) {
...@@ -46,7 +48,8 @@ public class SotSManager { ...@@ -46,7 +48,8 @@ public class SotSManager {
boolean isAlive = entity.isAlive(); boolean isAlive = entity.isAlive();
if (!isAlive) { if (!isAlive) {
float maxHP = entity.getAvatar().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP); float maxHP = entity.getAvatar().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, Math.min(150, maxHP)); float newHP = (float)(maxHP * 0.3);
entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP);
entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar())); entity.getWorld().broadcastPacket(new PacketAvatarLifeStateChangeNotify(entity.getAvatar()));
} }
}); });
...@@ -65,14 +68,31 @@ public class SotSManager { ...@@ -65,14 +68,31 @@ public class SotSManager {
}).start(); }).start();
} }
// autoRecover checks player setting to see if auto recover is enabled, and refill HP to the predefined level. public void refillSpringVolume() {
public void autoRecover(GameSession session) { // TODO: max spring volume depends on level of the statues in Mondstadt and Liyue.
// TODO: Implement SotS Spring volume refill over time. // https://genshin-impact.fandom.com/wiki/Statue_of_The_Seven#:~:text=region%20of%20Inazuma.-,Statue%20Levels,-Upon%20first%20unlocking
// Placeholder:
player.setProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME, 8500000); 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. long now = System.currentTimeMillis() / 1000;
long secondsSinceLastUsed = now - player.getSpringLastUsed();
float percentageRefilled = (float)secondsSinceLastUsed / 15 / 100; // 15s = 1% max volume
int maxVolume = player.getProperty(PlayerProperty.PROP_MAX_SPRING_VOLUME);
int currentVolume = player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME);
if (currentVolume < maxVolume) {
int volumeRefilled = (int)(percentageRefilled * maxVolume);
int newVolume = currentVolume + volumeRefilled;
if (currentVolume + volumeRefilled > maxVolume) {
newVolume = maxVolume;
}
player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, newVolume);
}
player.setSpringLastUsed(now);
player.save();
}
// autoRecover checks player setting to see if auto recover is enabled, and refill HP to the predefined level.
public void autoRecover(GameSession session) {
// TODO: In MP, respect SotS settings from the HOST.
boolean isAutoRecoveryEnabled = getIsAutoRecoveryEnabled(); boolean isAutoRecoveryEnabled = getIsAutoRecoveryEnabled();
int autoRecoverPercentage = getAutoRecoveryPercentage(); int autoRecoverPercentage = getAutoRecoveryPercentage();
Grasscutter.getLogger().debug("isAutoRecoveryEnabled: " + isAutoRecoveryEnabled + "\tautoRecoverPercentage: " + autoRecoverPercentage); Grasscutter.getLogger().debug("isAutoRecoveryEnabled: " + isAutoRecoveryEnabled + "\tautoRecoverPercentage: " + autoRecoverPercentage);
...@@ -88,27 +108,36 @@ public class SotSManager { ...@@ -88,27 +108,36 @@ public class SotSManager {
if (targetHP > currentHP) { if (targetHP > currentHP) {
float needHP = targetHP - currentHP; float needHP = targetHP - currentHP;
float needSV = needHP * 100; // convert HP needed to Spring Volume needed
int sotsSVBalance = player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME);
if (sotsSVBalance >= needSV) {
// sufficient
sotsSVBalance -= needSV;
} else {
// insufficient balance
needSV = sotsSVBalance;
sotsSVBalance = 0;
}
player.setProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME, sotsSVBalance);
player.setSpringLastUsed(System.currentTimeMillis() / 1000);
int sotsHPBalance = player.getProperty(PlayerProperty.PROP_CUR_SPRING_VOLUME); float newHP = currentHP + needSV / 100; // convert SV to HP
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(); // TODO: Figure out why client shows current HP instead of added HP.
session.send(new PacketAvatarFightPropUpdateNotify(avatar, FightProperty.FIGHT_PROP_CUR_HP)); // Say an avatar had 12000 and now has 14000, it should show "2000".
avatar.setCurrentHp(newHP); // The client always show "+14000" which is incorrect.
player.save(); entity.setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, newHP);
} session.send(new PacketEntityFightPropChangeReasonNotify(entity, FightProperty.FIGHT_PROP_CUR_HP,
newHP, List.of(3), PropChangeReasonOuterClass.PropChangeReason.PROP_CHANGE_STATUE_RECOVER,
ChangeHpReasonOuterClass.ChangeHpReason.ChangeHpAddStatue));
session.send(new PacketEntityFightPropUpdateNotify(entity, FightProperty.FIGHT_PROP_CUR_HP));
Avatar avatar = entity.getAvatar();
avatar.setCurrentHp(newHP);
session.send(new PacketAvatarFightPropUpdateNotify(avatar, FightProperty.FIGHT_PROP_CUR_HP));
player.save();
} }
}); });
} }
......
...@@ -130,6 +130,8 @@ public class Player { ...@@ -130,6 +130,8 @@ public class Player {
private MapMarksManager mapMarksManager; private MapMarksManager mapMarksManager;
@Transient private MovementManager movementManager; @Transient private MovementManager movementManager;
private long springLastUsed;
@Deprecated @Deprecated
@SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only! @SuppressWarnings({"rawtypes", "unchecked"}) // Morphia only!
...@@ -535,6 +537,14 @@ public class Player { ...@@ -535,6 +537,14 @@ public class Player {
} }
} }
public long getSpringLastUsed() {
return springLastUsed;
}
public void setSpringLastUsed(long val) {
springLastUsed = val;
}
public SceneLoadState getSceneLoadState() { public SceneLoadState getSceneLoadState() {
return sceneState; return sceneState;
} }
......
...@@ -22,6 +22,8 @@ public class HandlerEnterTransPointRegionNotify extends PacketHandler { ...@@ -22,6 +22,8 @@ public class HandlerEnterTransPointRegionNotify extends PacketHandler {
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{ public void handle(GameSession session, byte[] header, byte[] payload) throws Exception{
Player player = session.getPlayer(); Player player = session.getPlayer();
SotSManager sotsManager = player.getSotSManager(); SotSManager sotsManager = player.getSotSManager();
sotsManager.refillSpringVolume();
sotsManager.autoRevive(session); sotsManager.autoRevive(session);
sotsManager.scheduleAutoRecover(session); sotsManager.scheduleAutoRecover(session);
// TODO: allow interaction with the SotS? // TODO: allow interaction with the SotS?
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment