From e72c4886e87122fec5496d075b60e12ff87a7ab6 Mon Sep 17 00:00:00 2001 From: FatBoy-DOTC Date: Sun, 12 Jan 2025 16:18:47 -0600 Subject: [PATCH] updated regen system --- src/engine/objects/PlayerCharacter.java | 361 ++++++++++------------- src/engine/workthreads/UpdateThread.java | 2 +- 2 files changed, 157 insertions(+), 206 deletions(-) diff --git a/src/engine/objects/PlayerCharacter.java b/src/engine/objects/PlayerCharacter.java index c00c040c..875b7d1b 100644 --- a/src/engine/objects/PlayerCharacter.java +++ b/src/engine/objects/PlayerCharacter.java @@ -5599,6 +5599,10 @@ public class PlayerCharacter extends AbstractCharacter { public void resetRegenUpdateTime() { this.lastUpdateTime = System.currentTimeMillis(); this.lastStamUpdateTime = System.currentTimeMillis(); + this.timestamps.put("LastRegenHealth", System.currentTimeMillis()); + this.timestamps.put("LastRegenMana", System.currentTimeMillis()); + this.timestamps.put("LastRegenStamina", System.currentTimeMillis()); + this.timestamps.put("LastConsumeStamina", System.currentTimeMillis()); } public float getCharacterHeight() { @@ -5690,211 +5694,6 @@ public class PlayerCharacter extends AbstractCharacter { dirtyLock.writeLock().unlock(); } - public void RunRegen(){ - - float healthRegen = 0f; - float manaRegen = 0f; - float stamRegen = 0f; - - boolean updateClient = false; - - // Early exit if char is dead or disconnected - if ((this.isAlive() == false) - || (this.isActive() == false) || this.getLoc().x == 0 && this.getLoc().z == 0) - return; - - // Calculate Regen amount from last simulation tick - switch (this.movementState) { - - case IDLE: - - healthRegen = ((this.healthMax * MBServerStatics.HEALTH_REGEN_IDLE) + MBServerStatics.HEALTH_REGEN_IDLE_STATIC) * (getRegenModifier(ModType.HealthRecoverRate)); - - if (this.isCasting() || this.isItemCasting()) - healthRegen *= .75f; - // Characters regen mana when in only walk mode and idle - if (this.walkMode) - manaRegen = (this.manaMax * 0.01f) * getRegenModifier(ModType.ManaRecoverRate) * MBServerStatics.MANA_REGEN_WALK; - else { - manaRegen = (this.manaMax * 0.01f) * getRegenModifier(ModType.ManaRecoverRate) * MBServerStatics.MANA_REGEN_IDLE; - } - - if (!PlayerCharacter.CanBreathe(this)) - stamRegen = MBServerStatics.STAMINA_REGEN_SWIM; - else if ((!this.isCasting() && !this.isItemCasting()) || this.lastMovementState.equals(MovementState.FLYING)) - stamRegen = MBServerStatics.STAMINA_REGEN_IDLE * getRegenModifier(ModType.StaminaRecoverRate); - else - stamRegen = 0; - break; - case SITTING: - healthRegen = ((this.healthMax * MBServerStatics.HEALTH_REGEN_SIT) + MBServerStatics.HEALTH_REGEN_SIT_STATIC) * getRegenModifier(ModType.HealthRecoverRate); - manaRegen = (this.manaMax * MBServerStatics.MANA_REGEN_SIT) * (getRegenModifier(ModType.ManaRecoverRate)); - stamRegen = MBServerStatics.STAMINA_REGEN_SIT * getRegenModifier(ModType.StaminaRecoverRate); - break; - case RUNNING: - if (this.walkMode == true) { - healthRegen = ((this.healthMax * MBServerStatics.HEALTH_REGEN_WALK) + MBServerStatics.HEALTH_REGEN_IDLE_STATIC) * getRegenModifier(ModType.HealthRecoverRate); - manaRegen = this.manaMax * MBServerStatics.MANA_REGEN_WALK * getRegenModifier(ModType.ManaRecoverRate); - stamRegen = MBServerStatics.STAMINA_REGEN_WALK; - } else { - healthRegen = 0; - manaRegen = 0; - - if (this.combat == true) - stamRegen = MBServerStatics.STAMINA_REGEN_RUN_COMBAT; - else - stamRegen = MBServerStatics.STAMINA_REGEN_RUN_NONCOMBAT; - } - break; - case FLYING: - - float seventyFive = this.staminaMax * .75f; - float fifty = this.staminaMax * .5f; - float twentyFive = this.staminaMax * .25f; - - if (this.getDesiredAltitude() == 0 && this.getAltitude() <= 10) { - if (this.isCombat()) - stamRegen = 0; - else - stamRegen = MBServerStatics.STAMINA_REGEN_IDLE * getRegenModifier(ModType.StaminaRecoverRate); - } else if (!this.useFlyMoveRegen()) { - - healthRegen = ((this.healthMax * MBServerStatics.HEALTH_REGEN_IDLE) + MBServerStatics.HEALTH_REGEN_IDLE_STATIC) * (getRegenModifier(ModType.HealthRecoverRate)); - - if (this.isCasting() || this.isItemCasting()) - healthRegen *= .75f; - // Characters regen mana when in only walk mode and idle - if (this.walkMode) - manaRegen = (this.manaMax * MBServerStatics.MANA_REGEN_IDLE + (this.getSpiMod() * .015f)) * (getRegenModifier(ModType.ManaRecoverRate)); - else if (!this.isCasting() && !this.isItemCasting()) - manaRegen = (this.manaMax * MBServerStatics.MANA_REGEN_IDLE + (this.getSpiMod() * .015f)) * (getRegenModifier(ModType.ManaRecoverRate)); - else - manaRegen = 0; - - if (!this.isItemCasting() && !this.isCasting() || this.getTakeOffTime() != 0) - stamRegen = MBServerStatics.STAMINA_REGEN_FLY_IDLE; - else - stamRegen = -1f; - } else if (this.walkMode == true) { - healthRegen = ((this.healthMax * MBServerStatics.HEALTH_REGEN_WALK) + MBServerStatics.HEALTH_REGEN_IDLE_STATIC) * getRegenModifier(ModType.HealthRecoverRate); - manaRegen = ((this.manaMax * MBServerStatics.MANA_REGEN_WALK) + (this.getSpiMod() * .015f)) * (getRegenModifier(ModType.ManaRecoverRate)); - stamRegen = MBServerStatics.STAMINA_REGEN_FLY_WALK; - } else { - healthRegen = 0; - manaRegen = 0; - if (this.isCombat()) - stamRegen = MBServerStatics.STAMINA_REGEN_FLY_RUN_COMBAT; - else - stamRegen = MBServerStatics.STAMINA_REGEN_FLY_RUN; - } - - float oldStamina = this.stamina.get(); - - if (FastMath.between(oldStamina, 0, twentyFive) && !this.wasTripped25) { - updateClient = true; - this.wasTripped25 = true; - this.wasTripped50 = false; - this.wasTripped75 = false; - } else if (FastMath.between(oldStamina, twentyFive, fifty) && !this.wasTripped50) { - updateClient = true; - this.wasTripped25 = false; - this.wasTripped50 = true; - this.wasTripped75 = false; - } else if (FastMath.between(oldStamina, fifty, seventyFive) && !this.wasTripped75) { - updateClient = true; - this.wasTripped25 = false; - this.wasTripped50 = false; - this.wasTripped75 = true; - } - break; - case SWIMMING: - if (this.walkMode == true) { - healthRegen = ((this.healthMax * MBServerStatics.HEALTH_REGEN_WALK) + MBServerStatics.HEALTH_REGEN_IDLE_STATIC) * getRegenModifier(ModType.HealthRecoverRate); - manaRegen = ((this.manaMax * MBServerStatics.MANA_REGEN_WALK) + (this.getSpiMod() * .015f)) * (getRegenModifier(ModType.ManaRecoverRate)); - stamRegen = MBServerStatics.STAMINA_REGEN_SWIM; - } else { - healthRegen = 0; - manaRegen = 0; - stamRegen = MBServerStatics.STAMINA_REGEN_SWIM; - - if (this.combat == true) - stamRegen += MBServerStatics.STAMINA_REGEN_RUN_COMBAT; - else - stamRegen += MBServerStatics.STAMINA_REGEN_RUN_NONCOMBAT; - } - break; - } - - // Are we drowning? - if ((this.getStamina() <= 0) - && (PlayerCharacter.CanBreathe(this) == false)) - healthRegen = (this.healthMax * -.03f); - - // Multiple regen values by current deltaTime - // Logger.info("", healthRegen + ""); - long currentTime = System.currentTimeMillis(); - Long regenTime; - if(this.timestamps.containsKey("LastRegen")) - regenTime = this.timestamps.get("LastRegen"); - else - regenTime = currentTime; - float secondsPassed = (currentTime - regenTime) / 1000f; - healthRegen *= secondsPassed; - manaRegen *= secondsPassed; - stamRegen *= secondsPassed; - - this.timestamps.put("LastRegen",currentTime); - - //ChatManager.chatSystemInfo(this,"Mana: " + this.mana.get()); - - boolean workedHealth = false; - boolean workedMana = false; - boolean workedStamina = false; - - float old, mod; - while (!workedHealth || !workedMana || !workedStamina) { - if (!this.isAlive() || !this.isActive()) - return; - if (!workedHealth) { - old = this.health.get(); - mod = old + healthRegen; - if (mod > this.healthMax) - mod = healthMax; - else if (mod <= 0) { - if (this.isAlive.compareAndSet(true, false)) - killCharacter("Water"); - return; - } - workedHealth = this.health.compareAndSet(old, mod); - } - if (!workedStamina) { - old = this.stamina.get(); - mod = old + stamRegen; - if (mod > this.staminaMax) - mod = staminaMax; - else if (mod < 0) - mod = 0; - workedStamina = this.stamina.compareAndSet(old, mod); - } - if (!workedMana) { - old = this.mana.get(); - mod = old + manaRegen; - if (mod > this.manaMax) - mod = manaMax; - else if (mod < 0) - mod = 0; - workedMana = this.mana.compareAndSet(old, mod); - } - } - - if (updateClient) - this.syncClient(); - - // Reset this char's frame time. - this.lastUpdateTime = System.currentTimeMillis(); - this.lastStamUpdateTime = System.currentTimeMillis(); - } - public static float getRegenRate(PlayerCharacter player, ModType type){ float regenRate = player.getRegenModifier(type); @@ -6064,4 +5863,156 @@ public class PlayerCharacter extends AbstractCharacter { } } } + + public void doRegen(){ + if (this.updateLock.writeLock().tryLock()) { + try { + regenerateHealth(); + regenerateMana(); + regenerateStamina(); + consumeStamina(); + } catch (Exception e) { + Logger.error(e); + } finally { + this.updateLock.writeLock().unlock(); + } + } + } + + public void regenerateHealth(){ + Long regenTime; + Long currentTime = System.currentTimeMillis(); + regenTime = this.timestamps.getOrDefault("LastRegenHealth", currentTime); + float secondsPassed = (currentTime - regenTime) / 1000f; + float onePercent = this.healthMax * 0.01f; + float rate = RecoveryType.getRecoveryType(this).healthRate; + rate *= this.getRegenModifier(ModType.HealthRecoverRate); + + float healthRegenerated = onePercent * secondsPassed * rate; + + boolean workedHealth = false; + float old,mod; + while(!workedHealth) { + old = this.health.get(); + mod = old + healthRegenerated; + if (mod > this.healthMax) + mod = healthMax; + else if (mod <= 0) { + if (this.isAlive.compareAndSet(true, false)) + killCharacter("Water"); + return; + } + workedHealth = this.health.compareAndSet(old, mod); + } + + this.timestamps.put("LastRegenHealth",currentTime); + } + public void regenerateMana(){ + Long regenTime; + Long currentTime = System.currentTimeMillis(); + regenTime = this.timestamps.getOrDefault("LastRegenMana", currentTime); + float secondsPassed = (currentTime - regenTime) / 1000f; + float onePercent = this.manaMax * 0.01f; + float rate = RecoveryType.getRecoveryType(this).manaRate; + rate *= this.getRegenModifier(ModType.ManaRecoverRate); + + float manaRegenerated = onePercent * secondsPassed * rate; + + boolean workedMana = false; + float old,mod; + while(!workedMana) { + old = this.mana.get(); + mod = old + manaRegenerated; + if (mod > this.manaMax) + mod = manaMax; + else if (mod < 0) + mod = 0; + workedMana = this.mana.compareAndSet(old, mod); + } + + this.timestamps.put("LastRegenMana",currentTime); + } + public void regenerateStamina(){ + Long regenTime; + Long currentTime = System.currentTimeMillis(); + regenTime = this.timestamps.getOrDefault("LastRegenStamina", currentTime); + float secondsPassed = (currentTime - regenTime) / 1000f; + + float rate = RecoveryType.getRecoveryType(this).staminaRate; + rate *= this.getRegenModifier(ModType.StaminaRecoverRate); // Adjust rate with modifiers + + float staminaRegenerated = secondsPassed / rate; // Stamina regenerates 1 point per `rate` seconds + + boolean workedStamina = false; + float old, mod; + while (!workedStamina) { + old = this.stamina.get(); + mod = old + staminaRegenerated; + if (mod > this.staminaMax) + mod = staminaMax; + else if (mod < 0) + mod = 0; + workedStamina = this.stamina.compareAndSet(old, mod); + } + + this.timestamps.put("LastRegenStamina", currentTime); + } + public void consumeStamina(){ + Long regenTime; + Long currentTime = System.currentTimeMillis(); + regenTime = this.timestamps.getOrDefault("LastConsumeStamina", currentTime); + float secondsPassed = (currentTime - regenTime) / 1000f; + + float consumption; + if(!this.isMoving() && !this.isFlying()) + return; + + if(!this.combat){ + consumption = 0.4f * secondsPassed; + }else{ + consumption = 0.65f * secondsPassed; + } + if(!this.canBreathe || this.isFlying()) + consumption *= 2; + + boolean workedStamina = false; + float old,mod; + while (!workedStamina) { + old = this.stamina.get(); + mod = old - consumption; + if (mod <= 0) + mod = 0; + workedStamina = this.stamina.compareAndSet(old, mod); + } + } + + enum RecoveryType{ + //Values for health and mana are in terms of the number of seconds it takes to recover 1% of max pool + //Values for stamina are in terms of the number of seconds it takes to recover 1 point + RESTING(3.0f,1.2f,0.5f), //sitting + IDLING(15.0f,6.0f,5.0f), //standing not moving + WALKING(20.0f,8.0f,0.0f), // moving in walk mode + RUNNING(0.0f,0.0f,0.0f); // moving in run mode + public float healthRate; + public float manaRate; + public float staminaRate; + RecoveryType(float health, float mana, float stamina) { + this.healthRate = health; + this.manaRate = mana; + this.staminaRate = stamina; + } + public static RecoveryType getRecoveryType(PlayerCharacter pc){ + if (pc.isMoving()) { + if(pc.walkMode){ + return RecoveryType.WALKING; + }else{ + return RecoveryType.RUNNING; + } + }else if(pc.isSit()){ + return RecoveryType.RESTING; + }else{ + return RecoveryType.IDLING; + } + } + } } diff --git a/src/engine/workthreads/UpdateThread.java b/src/engine/workthreads/UpdateThread.java index 52f27e90..12ce8faa 100644 --- a/src/engine/workthreads/UpdateThread.java +++ b/src/engine/workthreads/UpdateThread.java @@ -30,7 +30,7 @@ public class UpdateThread implements Runnable { try { for(PlayerCharacter player : SessionManager.getAllActivePlayerCharacters()){ //player.update(true); - player.regenerate(); + player.doRegen(); } } catch (Exception e) { Logger.error("UPDATE ERROR");