From 816494c8dfe9a03fc9378821f48ae1ede2cf2b4e Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Thu, 6 Feb 2025 14:30:39 -0500 Subject: [PATCH] v3.0.0: Hunger and Regen now both tick for partial amounts once per turn previously they ticked for static amounts at a variable speed, defaulting to every 10 turns. The actual hunger/regen rate is unchanged, but this should make the buffs more responsive --- .../actors/buffs/Hunger.java | 23 +++-- .../actors/buffs/Regeneration.java | 99 +++++++++---------- .../items/trinkets/SaltCube.java | 17 ---- 3 files changed, 60 insertions(+), 79 deletions(-) diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Hunger.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Hunger.java index 28a82daef..324249ecd 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Hunger.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Hunger.java @@ -36,8 +36,6 @@ import com.watabou.utils.Bundle; public class Hunger extends Buff implements Hero.Doom { - private static final float STEP = 10f; - public static final float HUNGRY = 300f; public static final float STARVING = 450f; @@ -68,7 +66,7 @@ public class Hunger extends Buff implements Hero.Doom { || target.buff(WellFed.class) != null || SPDSettings.intro() || target.buff(ScrollOfChallenge.ChallengeArena.class) != null){ - spend(STEP); + spend(TICK); return true; } @@ -78,7 +76,7 @@ public class Hunger extends Buff implements Hero.Doom { if (isStarving()) { - partialDamage += STEP * target.HT/1000f; + partialDamage += target.HT/1000f; if (partialDamage > 1){ target.damage( (int)partialDamage, this); @@ -87,13 +85,20 @@ public class Hunger extends Buff implements Hero.Doom { } else { - float newLevel = level + STEP; + float hungerDelay = 1f; + if (target.buff(Shadows.class) != null){ + hungerDelay *= 1.5f; + } + hungerDelay /= SaltCube.hungerGainMultiplier(); + + float newLevel = level + (1f/hungerDelay); if (newLevel >= STARVING) { GLog.n( Messages.get(this, "onstarving") ); hero.damage( 1, this ); hero.interrupt(); + newLevel = STARVING; } else if (newLevel >= HUNGRY && level < HUNGRY) { @@ -107,14 +112,8 @@ public class Hunger extends Buff implements Hero.Doom { level = newLevel; } - - float hungerDelay = STEP; - if (target.buff(Shadows.class) != null){ - hungerDelay *= 1.5f; - } - hungerDelay /= SaltCube.hungerGainMultiplier(); - spend( hungerDelay ); + spend( TICK ); } else { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Regeneration.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Regeneration.java index 7dd258fbf..7f3da7458 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Regeneration.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Regeneration.java @@ -28,6 +28,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.ChaliceOfBlood; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfEnergy; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ChaoticCenser; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.SaltCube; +import com.watabou.utils.Bundle; public class Regeneration extends Buff { @@ -36,8 +37,10 @@ public class Regeneration extends Buff { //healing is much more useful if you get some of it off before taking damage actPriority = HERO_PRIO - 1; } - - private static final float REGENERATION_DELAY = 10; + + private float partialRegen = 0f; + + private static final float REGENERATION_DELAY = 10; //1HP every 10 turns @Override public boolean act() { @@ -49,45 +52,44 @@ public class Regeneration extends Buff { Buff.affect(Dungeon.hero, ChaoticCenser.CenserGasTracker.class); } - //cancel regenning entirely in thie case - if (SaltCube.healthRegenMultiplier() == 0){ - spend(REGENERATION_DELAY); - return true; - } + if (regenOn() && target.HP < regencap() && !((Hero)target).isStarving()) { + boolean chaliceCursed = false; + int chaliceLevel = -1; + if (target.buff(MagicImmune.class) == null) { + if (Dungeon.hero.buff(ChaliceOfBlood.chaliceRegen.class) != null) { + chaliceCursed = Dungeon.hero.buff(ChaliceOfBlood.chaliceRegen.class).isCursed(); + chaliceLevel = Dungeon.hero.buff(ChaliceOfBlood.chaliceRegen.class).itemLevel(); + } else if (Dungeon.hero.buff(SpiritForm.SpiritFormBuff.class) != null + && Dungeon.hero.buff(SpiritForm.SpiritFormBuff.class).artifact() instanceof ChaliceOfBlood) { + chaliceLevel = SpiritForm.artifactLevel(); + } + } - if (target.HP < regencap() && !((Hero)target).isStarving()) { - if (regenOn()) { + float delay = REGENERATION_DELAY; + if (chaliceLevel != -1 && target.buff(MagicImmune.class) == null) { + if (chaliceCursed) { + delay *= 1.5f; + } else { + //15% boost at +0, scaling to a 500% boost at +10 + delay -= 1.33f + chaliceLevel*0.667f; + delay /= RingOfEnergy.artifactChargeMultiplier(target); + } + } + delay /= SaltCube.healthRegenMultiplier(); + + partialRegen += 1f / delay; + + if (partialRegen >= 1) { target.HP += 1; + partialRegen--; if (target.HP == regencap()) { ((Hero) target).resting = false; } } + } - boolean chaliceCursed = false; - int chaliceLevel = -1; - if (target.buff(MagicImmune.class) == null) { - if (Dungeon.hero.buff(ChaliceOfBlood.chaliceRegen.class) != null) { - chaliceCursed = Dungeon.hero.buff(ChaliceOfBlood.chaliceRegen.class).isCursed(); - chaliceLevel = Dungeon.hero.buff(ChaliceOfBlood.chaliceRegen.class).itemLevel(); - } else if (Dungeon.hero.buff(SpiritForm.SpiritFormBuff.class) != null - && Dungeon.hero.buff(SpiritForm.SpiritFormBuff.class).artifact() instanceof ChaliceOfBlood) { - chaliceLevel = SpiritForm.artifactLevel(); //TODO this doesn't work well atm due to prior delay - } - } - - float delay = REGENERATION_DELAY; - if (chaliceLevel != -1 && target.buff(MagicImmune.class) == null) { - if (chaliceCursed) { - delay *= 1.5f; - } else { - //15% boost at +0, scaling to a 500% boost at +10 - delay -= 1.33f + chaliceLevel*0.667f; - delay /= RingOfEnergy.artifactChargeMultiplier(target); - } - } - delay /= SaltCube.healthRegenMultiplier(); - spend( delay ); + spend( TICK ); } else { @@ -97,23 +99,6 @@ public class Regeneration extends Buff { return true; } - - //helper method for resetting the delay when salt cube buff changes, to counter exploits - public void resetDelay( SaltCube cube ){ - ChaliceOfBlood.chaliceRegen regenBuff = Dungeon.hero.buff( ChaliceOfBlood.chaliceRegen.class); - float delay = REGENERATION_DELAY; - if (regenBuff != null && target.buff(MagicImmune.class) == null) { - if (regenBuff.isCursed()) { - delay *= 1.5f; - } else { - //15% boost at +0, scaling to a 500% boost at +10 - delay -= 1.33f + regenBuff.itemLevel()*0.667f; - delay /= RingOfEnergy.artifactChargeMultiplier(target); - } - } - delay /= SaltCube.healthRegenMultiplier(cube.level()); - postpone( delay ); - } public int regencap(){ return target.HT; @@ -126,4 +111,18 @@ public class Regeneration extends Buff { } return true; } + + public static final String PARTIAL_REGEN = "partial_regen"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(PARTIAL_REGEN, partialRegen); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + partialRegen = bundle.getFloat(PARTIAL_REGEN); + } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/SaltCube.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/SaltCube.java index 7fb197752..27e9618b2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/SaltCube.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/SaltCube.java @@ -21,10 +21,6 @@ package com.shatteredpixel.shatteredpixeldungeon.items.trinkets; -import com.shatteredpixel.shatteredpixeldungeon.Dungeon; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; -import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Regeneration; -import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; @@ -40,19 +36,6 @@ public class SaltCube extends Trinket { return 6+2*level(); } - @Override - protected void onDetach() { - //resets regen delay to counter exploits involving juggling the salt cube. - Buff.affect(Dungeon.hero, Regeneration.class).resetDelay(this); - } - - @Override - public boolean doPickUp(Hero hero, int pos) { - //resets regen delay to counter exploits involving juggling the salt cube. - Buff.affect(Dungeon.hero, Regeneration.class).resetDelay(this); - return super.doPickUp(hero, pos); - } - @Override public String statsDesc() { if (isIdentified()){