From 7ae14f9142962e8c295ee30d1068175a508d7f6f Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 27 Oct 2019 02:36:03 -0400 Subject: [PATCH] v0.8.0: adjustments and balance changes to bats and brutes --- .../ShatteredPixelDungeon.java | 6 ++ .../actors/mobs/ArmoredBrute.java | 91 ++++++++++++++++++ .../actors/mobs/Bat.java | 4 +- .../actors/mobs/Bestiary.java | 2 +- .../actors/mobs/Brute.java | 94 +++++++++++++++---- .../actors/mobs/Shielded.java | 40 -------- .../messages/actors/actors.properties | 9 +- 7 files changed, 184 insertions(+), 62 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/ArmoredBrute.java delete mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Shielded.java diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java index 6b563ed66..b1f562ef9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/ShatteredPixelDungeon.java @@ -109,6 +109,12 @@ public class ShatteredPixelDungeon extends Game { com.watabou.utils.Bundle.addAlias( com.shatteredpixel.shatteredpixeldungeon.actors.mobs.OldTengu.class, "com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Tengu" ); + + //v0.7.6 + com.watabou.utils.Bundle.addAlias( + com.shatteredpixel.shatteredpixeldungeon.actors.mobs.ArmoredBrute.class, + "com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Shielded"); + } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/ArmoredBrute.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/ArmoredBrute.java new file mode 100644 index 000000000..1fc70174f --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/ArmoredBrute.java @@ -0,0 +1,91 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; + +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.items.Generator; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.PlateArmor; +import com.shatteredpixel.shatteredpixeldungeon.items.armor.ScaleArmor; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ShieldedSprite; +import com.watabou.utils.Random; + +public class ArmoredBrute extends Brute { + + { + spriteClass = ShieldedSprite.class; + + //see rollToDropLoot + loot = Generator.Category.ARMOR; + lootChance = 1f; + } + + @Override + public int drRoll() { + return Random.NormalIntRange(6, 10); + } + + @Override + protected void triggerEnrage () { + Buff.affect(this, ArmoredRage.class).setShield(HT/2 + 1); + if (Dungeon.level.heroFOV[pos]) { + sprite.showStatus( CharSprite.NEGATIVE, Messages.get(this, "enraged") ); + } + spend( TICK ); + hasRaged = true; + } + + @Override + protected Item createLoot () { + if (Random.Int( 4 ) == 0) { + return new PlateArmor().random(); + } + return new ScaleArmor().random(); + } + + //similar to regular brute rate, but deteriorates much slower. 60 turns to death total. + public static class ArmoredRage extends Brute.BruteRage { + + @Override + public boolean act() { + + if (target.HP > 0){ + detach(); + return true; + } + + absorbDamage( 1 ); + + if (shielding() <= 0){ + target.die(null); + } + + spend( 3*TICK ); + + return true; + } + + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bat.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bat.java index 7db143a58..1778f2f67 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bat.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bat.java @@ -49,7 +49,7 @@ public class Bat extends Mob { @Override public int damageRoll() { - return Random.NormalIntRange( 5, 18 ); + return Random.NormalIntRange( 6, 16 ); } @Override @@ -65,7 +65,7 @@ public class Bat extends Mob { @Override public int attackProc( Char enemy, int damage ) { damage = super.attackProc( enemy, damage ); - int reg = Math.min( damage, HT - HP ); + int reg = Math.min( damage - 4, HT - HP ); if (reg > 0) { HP += reg; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java index ef483e625..098828a71 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Bestiary.java @@ -218,7 +218,7 @@ public class Bestiary { } else if (cl == Thief.class) { cl = Bandit.class; } else if (cl == Brute.class) { - cl = Shielded.class; + cl = ArmoredBrute.class; } else if (cl == Monk.class) { cl = Senior.class; } else if (cl == Scorpio.class) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Brute.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Brute.java index 1bfeb1a67..9bb3e651f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Brute.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Brute.java @@ -23,11 +23,14 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ShieldBuff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.BruteSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; +import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.watabou.utils.Bundle; import com.watabou.utils.Random; @@ -46,17 +49,12 @@ public class Brute extends Mob { lootChance = 0.5f; } - private boolean enraged = false; - - @Override - public void restoreFromBundle( Bundle bundle ) { - super.restoreFromBundle( bundle ); - enraged = HP < HT / 4; - } + protected boolean hasRaged = false; @Override public int damageRoll() { - return enraged ? + //TODO final balance decisions on these numbers + return buff(BruteRage.class) != null ? Random.NormalIntRange( 15, 45 ) : Random.NormalIntRange( 6, 26 ); } @@ -72,19 +70,83 @@ public class Brute extends Mob { } @Override - public void damage( int dmg, Object src ) { - super.damage( dmg, src ); - - if (isAlive() && !enraged && HP < HT / 4) { - enraged = true; - spend( TICK ); - if (Dungeon.level.heroFOV[pos]) { - sprite.showStatus( CharSprite.NEGATIVE, Messages.get(this, "enraged") ); + public boolean isAlive() { + if (HP > 0){ + return true; + } else { + if (!hasRaged){ + triggerEnrage(); } + return buff(BruteRage.class) != null; } } + protected void triggerEnrage(){ + Buff.affect(this, BruteRage.class).setShield(HT/2 + 4); + if (Dungeon.level.heroFOV[pos]) { + sprite.showStatus( CharSprite.NEGATIVE, Messages.get(this, "enraged") ); + } + spend( TICK ); + hasRaged = true; + } + + private static final String HAS_RAGED = "has_raged"; + + @Override + public void storeInBundle(Bundle bundle) { + super.storeInBundle(bundle); + bundle.put(HAS_RAGED, hasRaged); + } + + @Override + public void restoreFromBundle(Bundle bundle) { + super.restoreFromBundle(bundle); + hasRaged = bundle.getBoolean(HAS_RAGED); + } + { immunities.add( Terror.class ); } + + public static class BruteRage extends ShieldBuff { + + { + type = buffType.POSITIVE; + } + + @Override + public boolean act() { + + if (target.HP > 0){ + detach(); + return true; + } + + absorbDamage( 4 ); + + if (shielding() <= 0){ + target.die(null); + } + + spend( TICK ); + + return true; + } + + @Override + public int icon () { + return BuffIndicator.FURY; + } + + @Override + public String toString () { + return Messages.get(this, "name"); + } + + @Override + public String desc () { + return Messages.get(this, "desc", shielding()); + } + + } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Shielded.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Shielded.java deleted file mode 100644 index c28b67db9..000000000 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Shielded.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Pixel Dungeon - * Copyright (C) 2012-2015 Oleg Dolya - * - * Shattered Pixel Dungeon - * Copyright (C) 2014-2019 Evan Debenham - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - */ - -package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; - -import com.shatteredpixel.shatteredpixeldungeon.sprites.ShieldedSprite; -import com.watabou.utils.Random; - -public class Shielded extends Brute { - - { - spriteClass = ShieldedSprite.class; - - defenseSkill = 20; - } - - @Override - public int drRoll() { - return Random.NormalIntRange(0, 10); - } - -} diff --git a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties index b52dbf9d8..e6c9fa32c 100644 --- a/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties +++ b/core/src/main/resources/com/shatteredpixel/shatteredpixeldungeon/messages/actors/actors.properties @@ -437,7 +437,7 @@ actors.mobs.albino.desc=This is a rare breed of marsupial rat, with pure white f actors.mobs.bandit.name=crazy bandit actors.mobs.bat.name=vampire bat -actors.mobs.bat.desc=These brisk and tenacious inhabitants of cave domes may defeat much larger opponents by replenishing their health with each successful attack. +actors.mobs.bat.desc=These brisk and tenacious inhabitants of the caves are much more dangerous than they seem. They replenish their health with each successful attack, which allows them to defeat much larger opponents. actors.mobs.bee.name=golden bee actors.mobs.bee.desc_honey=Despite their small size, golden bees tend to protect their home fiercely. This one has been placated, and seems to want to follow you. @@ -446,7 +446,9 @@ actors.mobs.bee.desc=Despite their small size, golden bees tend to protect their actors.mobs.brute.name=gnoll brute actors.mobs.brute.enraged=enraged actors.mobs.brute.def_verb=blocked -actors.mobs.brute.desc=Brutes are the largest, strongest and toughest of all gnolls. When severely wounded, they go berserk, inflicting even more damage to their enemies. +actors.mobs.brute.desc=Brutes are the largest, strongest, and toughest of all gnolls. When mortally wounded, they go berserk, gaining temporary shielding and a large boost to damage. +actors.mobs.brute$bruterage.name=Brute Rage +actors.mobs.brute$bruterage.desc=This gnoll brute is dieing, but wants to take you with it!\n\nThe brute will die when its shielding wears off, either due to time or if it is damaged. In the meantime, it will deal hugely increased damage, so watch out!\n\nShield remaining: %d. actors.mobs.causticslime.name=caustic slime actors.mobs.causticslime.desc=This slime seems to have been tainted by the dark magic emanating from below. It has lost its usual green color, and drips with caustic ooze. @@ -558,7 +560,8 @@ actors.mobs.shaman.name=gnoll shaman actors.mobs.shaman.zap_kill=The lightning bolt killed you... actors.mobs.shaman.desc=The most intelligent gnolls can master shamanistic magic. Gnoll shamans prefer battle spells to compensate for lack of might, not hesitating to use them on those who question their status in a tribe. -actors.mobs.shielded.name=shielded brute +actors.mobs.armoredbrute.name=armored brute +actors.mobs.armoredbrute.desc=The most senior gnoll brutes often wear powerful armor to show their status. The armor makes these brutes much more resilient to physical damage, and their greater discipline means they can rage for much longer before succumbing to their wounds. actors.mobs.skeleton.name=skeleton actors.mobs.skeleton.explo_kill=You were killed by the explosion of bones...