diff --git a/core/src/main/assets/effects/text_icons.png b/core/src/main/assets/effects/text_icons.png index a03de99bc..faa354c4e 100644 Binary files a/core/src/main/assets/effects/text_icons.png and b/core/src/main/assets/effects/text_icons.png differ diff --git a/core/src/main/assets/messages/actors/actors.properties b/core/src/main/assets/messages/actors/actors.properties index 351a90ff1..3c726a5b9 100644 --- a/core/src/main/assets/messages/actors/actors.properties +++ b/core/src/main/assets/messages/actors/actors.properties @@ -1319,7 +1319,7 @@ actors.mobs.armoredbrute.desc=The most senior gnoll brutes often wear powerful a actors.mobs.skeleton.name=skeleton actors.mobs.skeleton.explo_kill=You were killed by the explosion of bones... actors.mobs.skeleton.def_verb=blocked -actors.mobs.skeleton.desc=Skeletons are composed of corpses bones from unlucky adventurers and inhabitants of the dungeon, animated by emanations of evil magic from the depths below. After they have been damaged enough, they disintegrate in an explosion of bones. +actors.mobs.skeleton.desc=Skeletons are composed of the bones of unlucky adventurers and inhabitants of the prison, animated by emanations of evil magic from the depths below. After they have been damaged enough, skeletons will disintegrate in an explosion of bones. The shrapnel from this explosion is harmful to anything nearby, but armor is very effective at mitigating it. actors.mobs.slime.name=slime actors.mobs.slime.def_verb=blocked diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java index 61e38a64e..34169c82d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/Char.java @@ -41,6 +41,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.ChampionEnemy; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Charm; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Chill; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corrosion; +import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Corruption; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Daze; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Doom; @@ -76,7 +77,11 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.duelist.Challenge; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.rogue.DeathMark; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.warrior.Endure; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.CrystalSpire; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DwarfKing; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Elemental; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GnollGeomancer; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Necromancer; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Tengu; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.MirrorImage; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.PrismaticImage; @@ -86,6 +91,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.AntiMagic; import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Potential; import com.shatteredpixel.shatteredpixeldungeon.items.armor.glyphs.Viscosity; +import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.DriedRose; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass; import com.shatteredpixel.shatteredpixeldungeon.items.potions.exotic.PotionOfCleansing; import com.shatteredpixel.shatteredpixeldungeon.items.quest.Pickaxe; @@ -94,6 +100,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetributio import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfChallenge; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast; +import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFrost; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfLightning; @@ -792,9 +799,15 @@ public abstract class Char extends Actor { if (sprite != null) { //defaults to normal damage icon if no other ones apply int icon = FloatingText.PHYS_DMG; + if (NO_ARMOR_PHYSICAL_SOURCES.contains(src.getClass())) icon = FloatingText.PHYS_DMG_NO_BLOCK; if (AntiMagic.RESISTS.contains(src.getClass())) icon = FloatingText.MAGIC_DMG; if (src instanceof Pickaxe) icon = FloatingText.PICK_DMG; + //special case for sniper when using ranged attacks + if (src == Dungeon.hero && Dungeon.hero.subClass == HeroSubClass.SNIPER && Dungeon.hero.belongings.attackingWeapon() instanceof MissileWeapon){ + icon = FloatingText.PHYS_DMG_NO_BLOCK; + } + if (src instanceof Hunger) icon = FloatingText.HUNGER; if (src instanceof Burning) icon = FloatingText.BURNING; if (src instanceof Chilling || src instanceof Frost) icon = FloatingText.FROST; @@ -807,6 +820,8 @@ public abstract class Char extends Actor { if (src instanceof Poison) icon = FloatingText.POISON; if (src instanceof Ooze) icon = FloatingText.OOZE; if (src instanceof Viscosity.DeferedDamage) icon = FloatingText.DEFERRED; + if (src instanceof Corruption) icon = FloatingText.CORRUPTION; + if (src instanceof AscensionChallenge) icon = FloatingText.AMULET; sprite.showStatusWithIcon(HP > HT / 2 ? CharSprite.WARNING : @@ -823,6 +838,20 @@ public abstract class Char extends Actor { DeathMark.processFearTheReaper(this); } } + + //these are misc. sources of physical damage which do not apply armor, they get a different icon + private static HashSet NO_ARMOR_PHYSICAL_SOURCES = new HashSet<>(); + { + NO_ARMOR_PHYSICAL_SOURCES.add(CrystalSpire.SpireSpike.class); + NO_ARMOR_PHYSICAL_SOURCES.add(GnollGeomancer.Boulder.class); + NO_ARMOR_PHYSICAL_SOURCES.add(DwarfKing.KingDamager.class); + NO_ARMOR_PHYSICAL_SOURCES.add(DwarfKing.Summoning.class); + NO_ARMOR_PHYSICAL_SOURCES.add(Chasm.class); + NO_ARMOR_PHYSICAL_SOURCES.add(WandOfBlastWave.Knockback.class); + NO_ARMOR_PHYSICAL_SOURCES.add(Heap.class); //damage from wraiths attempting to spawn from heaps + NO_ARMOR_PHYSICAL_SOURCES.add(Necromancer.SummoningBlockDamage.class); + NO_ARMOR_PHYSICAL_SOURCES.add(DriedRose.GhostHero.NoRoseDamage.class); + } public void destroy() { HP = 0; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java index 9c0dee7c0..72e4a0d90 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/DwarfKing.java @@ -686,7 +686,7 @@ public class DwarfKing extends Mob { } } else { Char ch = Actor.findChar(pos); - ch.damage(Random.NormalIntRange(20, 40), target); + ch.damage(Random.NormalIntRange(20, 40), this); if (((DwarfKing)target).phase == 2){ if (Dungeon.isChallenged(Challenges.STRONGER_BOSSES)){ target.damage(target.HT/18, new KingDamager()); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Necromancer.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Necromancer.java index bb22a30be..a49430e87 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Necromancer.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Necromancer.java @@ -218,7 +218,7 @@ public class Necromancer extends Mob { Char blocker = Actor.findChar(summoningPos); if (blocker.alignment != alignment){ - blocker.damage( Random.NormalIntRange(2, 10), this ); + blocker.damage( Random.NormalIntRange(2, 10), new SummoningBlockDamage() ); if (blocker == Dungeon.hero && !blocker.isAlive()){ Badges.validateDeathFromEnemyMagic(); Dungeon.fail(this); @@ -246,6 +246,8 @@ public class Necromancer extends Mob { Buff.affect( mySkeleton, b.getClass()); } } + + public static class SummoningBlockDamage{} private class Hunting extends Mob.Hunting{ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Skeleton.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Skeleton.java index 00319f304..6c5df8402 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Skeleton.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Skeleton.java @@ -71,6 +71,7 @@ public class Skeleton extends Mob { if (ch != null && ch.isAlive()) { int damage = Math.round(Random.NormalIntRange(6, 12)); damage = Math.round( damage * AscensionChallenge.statModifier(this)); + //armor is 2x effective against bone explosion damage = Math.max( 0, damage - (ch.drRoll() + ch.drRoll()) ); ch.damage( damage, this ); if (ch == Dungeon.hero && !ch.isAlive()) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/SpectralNecromancer.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/SpectralNecromancer.java index 0361d9d86..61ae8dcc4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/SpectralNecromancer.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/SpectralNecromancer.java @@ -136,7 +136,7 @@ public class SpectralNecromancer extends Necromancer { Char blocker = Actor.findChar(summoningPos); if (blocker.alignment != alignment){ - blocker.damage( Random.NormalIntRange(2, 10), this ); + blocker.damage( Random.NormalIntRange(2, 10), new SummoningBlockDamage() ); if (blocker == Dungeon.hero && !blocker.isAlive()){ Badges.validateDeathFromEnemyMagic(); Dungeon.fail(this); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/FloatingText.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/FloatingText.java index 37ed58ea0..38460dd08 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/FloatingText.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/effects/FloatingText.java @@ -47,31 +47,35 @@ public class FloatingText extends RenderedTextBlock { public static int NO_ICON = -1; //combat damage icons - public static int PHYS_DMG = 0; - public static int MAGIC_DMG = 1; - public static int PICK_DMG = 2; + public static int PHYS_DMG = 0; + public static int PHYS_DMG_NO_BLOCK = 1; + public static int MAGIC_DMG = 2; + public static int PICK_DMG = 3; //debuff/dot damage icons - public static int HUNGER = 4; - public static int BURNING = 5; - public static int SHOCKING = 6; - public static int FROST = 7; - public static int WATER = 8; - public static int BLEEDING = 9; - public static int TOXIC = 10; - public static int CORROSION = 11; - public static int POISON = 12; - public static int OOZE = 13; - public static int DEFERRED = 14; + public static int HUNGER = 5; + public static int BURNING = 6; + public static int SHOCKING = 7; + public static int FROST = 8; + public static int WATER = 9; + public static int BLEEDING = 10; + public static int TOXIC = 11; + public static int CORROSION = 12; + public static int POISON = 13; + public static int OOZE = 14; + public static int DEFERRED = 15; + public static int CORRUPTION= 16; + public static int AMULET = 17; //positive icons public static int HEALING = 18; public static int SHIELDING = 19; public static int EXPERIENCE= 20; + public static int STRENGTH = 21; //currency icons - public static int GOLD = 22; - public static int ENERGY = 23; + public static int GOLD = 23; + public static int ENERGY = 24; private Image icon; private boolean iconLeft; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/AntiMagic.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/AntiMagic.java index 5936c5afe..273629d07 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/AntiMagic.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/armor/glyphs/AntiMagic.java @@ -56,6 +56,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Blazing; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Shocking; +import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.HolyDart; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.DisintegrationTrap; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite; @@ -83,6 +84,7 @@ public class AntiMagic extends Armor.Glyph { RESISTS.add( ScrollOfRetribution.class ); RESISTS.add( ScrollOfPsionicBlast.class ); RESISTS.add( ScrollOfTeleportation.class ); + RESISTS.add( HolyDart.class ); RESISTS.add( ElementalBlast.class ); RESISTS.add( CursedWand.class ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java index 9e02c100d..aec7b6844 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/artifacts/DriedRose.java @@ -580,7 +580,7 @@ public class DriedRose extends Artifact { if (rose == null || !rose.isEquipped(Dungeon.hero) || Dungeon.hero.buff(MagicImmune.class) != null){ - damage(1, this); + damage(1, new NoRoseDamage()); } if (!isAlive()) { @@ -589,6 +589,8 @@ public class DriedRose extends Artifact { return super.act(); } + public static class NoRoseDamage{} + @Override public int attackSkill(Char target) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfStrength.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfStrength.java index 90de4cf8d..38e1a59d4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfStrength.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/PotionOfStrength.java @@ -23,7 +23,9 @@ package com.shatteredpixel.shatteredpixeldungeon.items.potions; import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.effects.FloatingText; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; @@ -42,6 +44,7 @@ public class PotionOfStrength extends Potion { identify(); hero.STR++; + hero.sprite.showStatusWithIcon(CharSprite.POSITIVE, "1", FloatingText.STRENGTH); GLog.p( Messages.get(this, "msg", hero.STR()) ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/elixirs/ElixirOfMight.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/elixirs/ElixirOfMight.java index 1587ec93d..18c6f1c2a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/elixirs/ElixirOfMight.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/potions/elixirs/ElixirOfMight.java @@ -25,9 +25,11 @@ import com.shatteredpixel.shatteredpixeldungeon.Badges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.effects.FloatingText; import com.shatteredpixel.shatteredpixeldungeon.items.potions.AlchemicalCatalyst; import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; import com.shatteredpixel.shatteredpixeldungeon.ui.BuffIndicator; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; @@ -47,6 +49,7 @@ public class ElixirOfMight extends Elixir { identify(); hero.STR++; + hero.sprite.showStatusWithIcon(CharSprite.POSITIVE, "1", FloatingText.STRENGTH); Buff.affect(hero, HTBoost.class).reset(); HTBoost boost = Buff.affect(hero, HTBoost.class); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java index 678ec7f70..6cc4aa8d5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java @@ -159,7 +159,7 @@ public class WandOfBlastWave extends DamageWand { int oldPos = ch.pos; ch.pos = newPos; if (finalCollided && ch.isActive()) { - ch.damage(Random.NormalIntRange(finalDist, 2*finalDist), this); + ch.damage(Random.NormalIntRange(finalDist, 2*finalDist), new Knockback()); if (ch.isActive()) { Paralysis.prolong(ch, Paralysis.class, 1 + finalDist/2f); } else if (ch == Dungeon.hero){ @@ -181,6 +181,8 @@ public class WandOfBlastWave extends DamageWand { })); } + public static class Knockback{} + @Override public void onHit(MagesStaff staff, Char attacker, Char defender, int damage) { //acts like elastic enchantment diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/ShockingDart.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/ShockingDart.java index e0050a65d..57cf5dca3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/ShockingDart.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/weapon/missiles/darts/ShockingDart.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Electricity; import com.shatteredpixel.shatteredpixeldungeon.effects.Lightning; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; @@ -44,7 +45,7 @@ public class ShockingDart extends TippedDart { //when processing charged shot, only shock enemies if (!processingChargedShot || attacker.alignment != defender.alignment) { - defender.damage(Random.NormalIntRange(5 + Dungeon.scalingDepth() / 4, 10 + Dungeon.scalingDepth() / 4), this); + defender.damage(Random.NormalIntRange(5 + Dungeon.scalingDepth() / 4, 10 + Dungeon.scalingDepth() / 4), new Electricity()); CharSprite s = defender.sprite; if (s != null && s.parent != null) {