From d639069ed1dfa25123ae37b2cdc6ed889de2718a Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Wed, 23 Jul 2025 15:26:07 -0400 Subject: [PATCH] v3.2.0: hold fast buffed, now reduces shielding and combo decay --- .../assets/messages/actors/actors.properties | 4 +-- .../actors/buffs/Barrier.java | 2 +- .../actors/buffs/Berserk.java | 8 +++-- .../actors/buffs/Combo.java | 2 +- .../actors/buffs/HoldFast.java | 24 ++++++++++++- .../items/BrokenSeal.java | 7 ++-- .../items/weapon/enchantments/Blocking.java | 36 +++++++++++++++---- 7 files changed, 66 insertions(+), 17 deletions(-) diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index c87bf8b1b..7fb15c599 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -257,7 +257,7 @@ actors.buffs.hex.heromsg=You have been hexed! actors.buffs.hex.desc=Dark magic which saps focus, making the target slightly disoriented.\n\nHexing reduces accuracy and evasion by 20%%, making the target less effective in combat.\n\nTurns of hex remaining: %s. actors.buffs.holdfast.name=hold fast -actors.buffs.holdfast.desc=The Warrior is holding his position, increasing his armor by %1$d-%2$d. This will last until he moves. +actors.buffs.holdfast.desc=The Warrior is holding his position, increasing his armor by %1$d-%2$d and slowing the decay rate of some buffs by %3$d%%. This will last until he moves. actors.buffs.hunger.hungry=hungry actors.buffs.hunger.starving=starving @@ -922,7 +922,7 @@ actors.hero.talent.improvised_projectiles.title=improvised projectiles actors.hero.talent.improvised_projectiles.desc=_+1:_ The Warrior can blind an enemy for _2 turns_ by throwing any item that isn’t a thrown weapon at them. This has a 50 turn cooldown.\n\n_+2:_ The Warrior can blind an enemy for _3 turns_ by throwing any item that isn’t a thrown weapon at them. This has a 50 turn cooldown. actors.hero.talent.hold_fast.title=hold fast -actors.hero.talent.hold_fast.desc=_+1:_ When the Warrior waits he gains _1-2 armor_ until he moves.\n\n_+2:_ When the Warrior waits he gains _2-4 armor_ until he moves.\n\n_+3:_ When the Warrior waits he gains _3-6 armor_ until he moves. +actors.hero.talent.hold_fast.desc=_+1:_ When the Warrior waits he gains _1-2 armor_ and slows the decay of combo and shielding buffs by _50%_ until he moves.\n\n_+2:_ When the Warrior waits he gains _2-4 armor_ and slows the decay of combo and shielding buffs by _75%_ until he moves.\n\n_+3:_ When the Warrior waits he gains _3-6 armor_ and slows the decay of combo and shielding buffs by _100%_ until he moves. actors.hero.talent.strongman.title=strongman actors.hero.talent.strongman.desc=_+1:_ The Warrior's strength is _increased by 8%_, rounded down.\n\n_+2:_ The Warrior's strength is _increased by 13%_, rounded down.\n\n_+3:_ The Warrior's strength is _increased by 18%_, rounded down. diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barrier.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barrier.java index 116eed496..21f46f1c7 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barrier.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Barrier.java @@ -51,7 +51,7 @@ public class Barrier extends ShieldBuff { @Override public boolean act() { - partialLostShield += Math.min(1f, shielding()/20f); + partialLostShield += Math.min(1f, shielding()/20f) * HoldFast.buffDecayFactor(target); if (partialLostShield >= 1f) { absorbDamage(1); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Berserk.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Berserk.java index f5d21d2c5..7a2450a7e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Berserk.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Berserk.java @@ -42,6 +42,7 @@ import com.watabou.noosa.Visual; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundle; import com.watabou.utils.GameMath; +import com.watabou.utils.Random; public class Berserk extends ShieldBuff implements ActionIndicator.Action { @@ -102,9 +103,12 @@ public class Berserk extends ShieldBuff implements ActionIndicator.Action { if (state == State.BERSERK){ if (target.shielding() > 0) { //lose 2.5% of shielding per turn, but no less than 1 - int dmg = (int)Math.ceil(target.shielding() * 0.025f); + float dmg = (float)Math.ceil(target.shielding() * 0.025f) * HoldFast.buffDecayFactor(target); + if (Random.Float() < dmg % 1){ + dmg++; + } - dmg = ShieldBuff.processDamage(target, dmg, this); + ShieldBuff.processDamage(target, (int)dmg, this); if (target.shielding() <= 0){ state = State.RECOVERING; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java index 0d1480f2f..444fb9aae 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/Combo.java @@ -123,7 +123,7 @@ public class Combo extends Buff implements ActionIndicator.Action { @Override public boolean act() { - comboTime-=TICK; + comboTime -= TICK * HoldFast.buffDecayFactor(target); spend(TICK); if (comboTime <= 0) { detach(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/HoldFast.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/HoldFast.java index 8ae8c5328..e6d4a709c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/HoldFast.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/buffs/HoldFast.java @@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.buffs; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; @@ -57,6 +58,24 @@ public class HoldFast extends Buff { } } + public static float buffDecayFactor(Char target){ + HoldFast buff = target.buff(HoldFast.class); + if (buff != null && target.pos == buff.pos && target instanceof Hero){ + switch (((Hero) target).pointsInTalent(Talent.HOLD_FAST)){ + case 1: + return 0.5f; + case 2: + return 0.25f; + case 3: + return 0; + } + + } else if (buff != null) { + buff.detach(); + } + return 1; + } + @Override public int icon() { return BuffIndicator.ARMOR; @@ -69,7 +88,10 @@ public class HoldFast extends Buff { @Override public String desc() { - return Messages.get(this, "desc", Dungeon.hero.pointsInTalent(Talent.HOLD_FAST), 2*Dungeon.hero.pointsInTalent(Talent.HOLD_FAST)); + return Messages.get(this, "desc", + Dungeon.hero.pointsInTalent(Talent.HOLD_FAST), + 2*Dungeon.hero.pointsInTalent(Talent.HOLD_FAST), + 25 + 25*Dungeon.hero.pointsInTalent(Talent.HOLD_FAST)); } private static final String POS = "pos"; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java index b023685e9..b7513dc14 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/BrokenSeal.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Combo; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.HoldFast; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Regeneration; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ShieldBuff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Belongings; @@ -254,7 +255,7 @@ public class BrokenSeal extends Item { private Armor armor; private int cooldown = 0; - private int turnsSinceEnemies = 0; + private float turnsSinceEnemies = 0; private static int COOLDOWN_START = 150; @@ -315,7 +316,7 @@ public class BrokenSeal extends Item { if (shielding() > 0){ if (Dungeon.hero.visibleEnemies() == 0 && Dungeon.hero.buff(Combo.class) == null){ - turnsSinceEnemies++; + turnsSinceEnemies += HoldFast.buffDecayFactor(target); if (turnsSinceEnemies >= 5){ if (cooldown > 0) { float percentLeft = shielding() / (float)maxShield(); @@ -384,7 +385,7 @@ public class BrokenSeal extends Item { super.restoreFromBundle(bundle); if (bundle.contains(COOLDOWN)) { cooldown = bundle.getInt(COOLDOWN); - turnsSinceEnemies = bundle.getInt(TURNS_SINCE_ENEMIES); + turnsSinceEnemies = bundle.getFloat(TURNS_SINCE_ENEMIES); //if we have shield from pre-3.1, have it last a bit } else if (shielding() > 0) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/enchantments/Blocking.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/enchantments/Blocking.java index 492c90c1f..0d39e9f24 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/enchantments/Blocking.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/enchantments/Blocking.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barrier; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.HoldFast; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ShieldBuff; import com.shatteredpixel.shatteredpixeldungeon.effects.FloatingText; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; @@ -33,6 +34,7 @@ import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.watabou.noosa.Image; +import com.watabou.utils.Bundle; import com.watabou.utils.Random; public class Blocking extends Weapon.Enchantment { @@ -65,7 +67,7 @@ public class Blocking extends Weapon.Enchantment { public ItemSprite.Glowing glowing() { return BLUE; } - + public static class BlockBuff extends ShieldBuff { { @@ -74,16 +76,23 @@ public class Blocking extends Weapon.Enchantment { shieldUsePriority = 2; } + private float left = 5f; + @Override public boolean act() { - detach(); + left -= HoldFast.buffDecayFactor(target); + if (left <= 0) { + detach(); + } else { + spend(TICK); + } return true; } @Override public void setShield(int shield) { super.setShield(shield); - postpone(5f); + left = 5f; } @Override @@ -107,18 +116,31 @@ public class Blocking extends Weapon.Enchantment { @Override public float iconFadePercent() { - return Math.max(0, (5f - visualcooldown()) / 5f); + return Math.max(0, (5f - left) / 5f); } @Override public String iconTextDisplay() { - return Integer.toString((int)visualcooldown()); + return Integer.toString((int)left); } @Override public String desc() { - return Messages.get(this, "desc", shielding(), dispTurns(visualcooldown())); + return Messages.get(this, "desc", shielding(), dispTurns(left)); + } + + public static String LEFT = "left"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(LEFT, left); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + left = bundle.getFloat(LEFT); } - } }