From 0351ad64750a4c26266f641829df8185f224fd98 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 8 Dec 2019 18:02:47 -0500 Subject: [PATCH] v0.8.0: reworked mimics: - evasion reduced slightly - now have armor equal to depth/2 - damage increased by ~50% - no longer give exp (same as other floor-independent mobs) - now are visually different from chests, can be preemptively attacked - will inflict bonus damage to the hero if they try to open them. --- core/src/main/assets/mimic.png | Bin 751 -> 2962 bytes .../actors/mobs/Mimic.java | 144 +++++++++++++----- .../shatteredpixeldungeon/items/Heap.java | 27 +--- .../items/bombs/Noisemaker.java | 10 -- .../items/scrolls/ScrollOfRage.java | 10 -- .../items/wands/CursedWand.java | 4 + .../shatteredpixeldungeon/levels/Level.java | 9 ++ .../levels/RegularLevel.java | 27 ++-- .../levels/rooms/special/TreasuryRoom.java | 7 +- .../rooms/standard/SuspiciousChestRoom.java | 3 +- .../levels/traps/DistortionTrap.java | 7 +- .../sprites/MimicSprite.java | 51 +++++-- .../messages/actors/actors.properties | 3 +- 13 files changed, 193 insertions(+), 109 deletions(-) diff --git a/core/src/main/assets/mimic.png b/core/src/main/assets/mimic.png index f8f43aa85adcc4f90dcc7cb5231973e3480a2a8a..1d8e5f201208ee0ccb8917ca224102cb24dbb911 100644 GIT binary patch literal 2962 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 U+nOxTqyPW_07*qoM6N<$f_zL!3IG5A diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mimic.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mimic.java index d7e226c23..01e522254 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mimic.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/Mimic.java @@ -31,17 +31,22 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.Pushing; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; +import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetribution; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; +import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.MimicSprite; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.watabou.noosa.audio.Sample; import com.watabou.utils.Bundle; import com.watabou.utils.PathFinder; import com.watabou.utils.Random; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -53,6 +58,12 @@ public class Mimic extends Mob { spriteClass = MimicSprite.class; properties.add(Property.DEMONIC); + + EXP = 0; + + //mimics are neutral when hidden + alignment = Alignment.NEUTRAL; + state = PASSIVE; } public ArrayList items; @@ -75,24 +86,111 @@ public class Mimic extends Mob { } adjustStats( bundle.getInt( LEVEL ) ); super.restoreFromBundle(bundle); + if (state != PASSIVE && alignment == Alignment.NEUTRAL){ + alignment = Alignment.ENEMY; + } } - + + @Override + public String name() { + if (alignment == Alignment.NEUTRAL){ + return Messages.get(Heap.class, "chest"); + } else { + return super.name(); + } + } + + @Override + public String description() { + if (alignment == Alignment.NEUTRAL){ + return Messages.get(Heap.class, "chest_desc"); + } else { + return super.description(); + } + } + + @Override + public CharSprite sprite() { + MimicSprite sprite = (MimicSprite) super.sprite(); + if (alignment == Alignment.NEUTRAL) sprite.hideMimic(); + return sprite; + } + + @Override + public boolean interact() { + if (alignment != Alignment.NEUTRAL){ + return super.interact(); + } + stopHiding(); + doAttack(Dungeon.hero); + Dungeon.hero.busy(); + Dungeon.hero.sprite.operate(pos); + return false; + } + + @Override + public void onAttackComplete() { + super.onAttackComplete(); + if (alignment == Alignment.NEUTRAL){ + alignment = Alignment.ENEMY; + Dungeon.hero.spendAndNext(1f); + } + } + + @Override + public void damage(int dmg, Object src) { + if (state == PASSIVE){ + alignment = Alignment.ENEMY; + stopHiding(); + } + super.damage(dmg, src); + } + + public void stopHiding(){ + state = HUNTING; + if (Dungeon.level.heroFOV[pos] && Actor.chars().contains(this)) { + enemy = Dungeon.hero; + target = Dungeon.hero.pos; + enemySeen = true; + GLog.w(Messages.get(this, "reveal") ); + CellEmitter.get(pos).burst(Speck.factory(Speck.STAR), 10); + Sample.INSTANCE.play(Assets.SND_MIMIC); + } + } + @Override public int damageRoll() { - return Random.NormalIntRange( HT / 10, HT / 4 ); + if (alignment == Alignment.NEUTRAL){ + return Random.NormalIntRange( 2*level, 2 + 3*level); + } else { + return Random.NormalIntRange( 1 + level, 2 + 2*level); + } } - + + @Override + public int drRoll() { + return Random.NormalIntRange(0, 1 + level/2); + } + + @Override + public void beckon( int cell ) { + // Do nothing + } + @Override public int attackSkill( Char target ) { - return 9 + level; + if (target != null && alignment == Alignment.NEUTRAL){ + return INFINITE_ACCURACY; + } else { + return 9 + level; + } } public void adjustStats( int level ) { this.level = level; HP = HT = (1 + level) * 6; - EXP = 2 + 2 * (level - 1) / 5; - defenseSkill = attackSkill( null ) / 2; + defenseSkill = 2 + level/2; enemySeen = true; } @@ -120,42 +218,16 @@ public class Mimic extends Mob { return true; } + public static Mimic spawnAt( int pos, Item item ){ + return spawnAt( pos, Arrays.asList(item)); + } + public static Mimic spawnAt( int pos, List items ) { - if (Dungeon.level.pit[pos]) return null; - Char ch = Actor.findChar( pos ); - if (ch != null) { - ArrayList candidates = new ArrayList<>(); - for (int n : PathFinder.NEIGHBOURS8) { - int cell = pos + n; - if ((Dungeon.level.passable[cell] || Dungeon.level.avoid[cell]) && Actor.findChar( cell ) == null) { - candidates.add( cell ); - } - } - if (candidates.size() > 0) { - int newPos = Random.element( candidates ); - Actor.addDelayed( new Pushing( ch, ch.pos, newPos ), -1 ); - - ch.pos = newPos; - Dungeon.level.occupyCell(ch ); - - } else { - return null; - } - } Mimic m = new Mimic(); m.items = new ArrayList<>( items ); m.adjustStats( Dungeon.depth ); m.pos = pos; - m.state = m.HUNTING; - GameScene.add( m, 1 ); - - m.sprite.turnTo( pos, Dungeon.hero.pos ); - - if (Dungeon.level.heroFOV[m.pos]) { - CellEmitter.get( pos ).burst( Speck.factory( Speck.STAR ), 10 ); - Sample.INSTANCE.play( Assets.SND_MIMIC ); - } //generate an extra reward for killing the mimic Item reward = null; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java index e9ce9a843..9dcf06441 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Heap.java @@ -72,7 +72,7 @@ public class Heap implements Bundlable { TOMB, SKELETON, REMAINS, - MIMIC + MIMIC //remains for pre-0.8.0 compatibility. There are converted to mimics on level load } public Type type = Type.HEAP; @@ -87,11 +87,7 @@ public class Heap implements Bundlable { public void open( Hero hero ) { switch (type) { case MIMIC: - if (Mimic.spawnAt(pos, items) != null) { - destroy(); - } else { - type = Type.CHEST; - } + type = Type.CHEST; break; case TOMB: Wraith.spawnAround( hero.pos ); @@ -207,15 +203,6 @@ public class Heap implements Bundlable { public void burn() { - if (type == Type.MIMIC) { - Mimic m = Mimic.spawnAt( pos, items ); - if (m != null) { - Buff.affect( m, Burning.class ).reignite( m ); - m.sprite.emitter().burst( FlameParticle.FACTORY, 5 ); - destroy(); - } - } - if (type != Type.HEAP) { return; } @@ -285,7 +272,7 @@ public class Heap implements Bundlable { for (Item item : items.toArray( new Item[0] )) { if (item instanceof Potion) { - items.remove( item ); + items.remove(item); ((Potion) item).shatter(pos); } else if (item instanceof Bomb) { @@ -313,14 +300,6 @@ public class Heap implements Bundlable { public void freeze() { - if (type == Type.MIMIC) { - Mimic m = Mimic.spawnAt( pos, items ); - if (m != null) { - Buff.prolong( m, Frost.class, Frost.duration( m ) * Random.Float( 1.0f, 1.5f ) ); - destroy(); - } - } - if (type != Type.HEAP) { return; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bombs/Noisemaker.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bombs/Noisemaker.java index 09f35a7a4..e4038f498 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bombs/Noisemaker.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/bombs/Noisemaker.java @@ -52,16 +52,6 @@ public class Noisemaker extends Bomb { mob.beckon( cell ); } - for (Heap heap : Dungeon.level.heaps.valueList()) { - if (heap.type == Heap.Type.MIMIC) { - Mimic m = Mimic.spawnAt( heap.pos, heap.items ); - if (m != null) { - m.beckon( cell ); - heap.destroy(); - } - } - } - } public static class Trigger extends Buff { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfRage.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfRage.java index 9f972bd79..9a8794146 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfRage.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/scrolls/ScrollOfRage.java @@ -51,16 +51,6 @@ public class ScrollOfRage extends Scroll { } } - for (Heap heap : Dungeon.level.heaps.valueList()) { - if (heap.type == Heap.Type.MIMIC) { - Mimic m = Mimic.spawnAt( heap.pos, heap.items ); - if (m != null) { - m.beckon( curUser.pos ); - heap.destroy(); - } - } - } - GLog.w( Messages.get(this, "roar") ); setKnown(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java index 23bcd8ec3..f55f67869 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java @@ -370,8 +370,11 @@ public class CursedWand { case 1: cursedFX(user, bolt, new Callback() { public void call() { + //TODO make this a gold mimic instead of boosting stats artificially Mimic mimic = Mimic.spawnAt(bolt.collisionPos, new ArrayList()); if (mimic != null) { + mimic.stopHiding(); + mimic.alignment = Char.Alignment.ENEMY; mimic.adjustStats(Dungeon.depth + 10); mimic.HP = mimic.HT; Item reward; @@ -382,6 +385,7 @@ public class CursedWand { Sample.INSTANCE.play(Assets.SND_MIMIC, 1, 1, 0.5f); mimic.items.clear(); mimic.items.add(reward); + GameScene.add(mimic); } else { GLog.i(Messages.get(CursedWand.class, "nothing")); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index 509d93d2b..89316b91b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -44,6 +44,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Sheep; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlowParticle; @@ -375,6 +376,14 @@ public abstract class Level implements Bundlable { buildFlagMaps(); cleanWalls(); + + //compat with pre-0.8.0 saves + for (Heap h : heaps.valueList()){ + if (h.type == Heap.Type.MIMIC){ + heaps.remove(h.pos); + mobs.add(Mimic.spawnAt(h.pos, h.items)); + } + } } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java index 57cb675d6..0ea060f97 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java @@ -24,6 +24,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels; import com.shatteredpixel.shatteredpixeldungeon.Bones; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; @@ -277,6 +278,16 @@ public abstract class RegularLevel extends Level { int nItems = 3 + Random.chances(new float[]{6, 3, 1}); for (int i=0; i < nItems; i++) { + + Item toDrop = Generator.random(); + if (toDrop == null) continue; + + int cell = randomDropCell(); + if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) { + map[cell] = Terrain.GRASS; + losBlocking[cell] = false; + } + Heap.Type type = null; switch (Random.Int( 20 )) { case 0: @@ -289,21 +300,17 @@ public abstract class RegularLevel extends Level { type = Heap.Type.CHEST; break; case 5: - type = Dungeon.depth > 1 ? Heap.Type.MIMIC : Heap.Type.CHEST; + if (Dungeon.depth > 1 && findMob(cell) == null){ + mobs.add(Mimic.spawnAt(cell, toDrop)); + continue; + } + type = Heap.Type.CHEST; break; default: type = Heap.Type.HEAP; } - int cell = randomDropCell(); - if (map[cell] == Terrain.HIGH_GRASS || map[cell] == Terrain.FURROWED_GRASS) { - map[cell] = Terrain.GRASS; - losBlocking[cell] = false; - } - - Item toDrop = Generator.random(); - - if (toDrop == null) continue; + //TODO gold mimics if ((toDrop instanceof Artifact && Random.Int(2) == 0) || (toDrop.isUpgradable() && Random.Int(4 - toDrop.level()) == 0)){ Heap dropped = drop( toDrop, cell ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/TreasuryRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/TreasuryRoom.java index 5a223ce63..f435840aa 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/TreasuryRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/TreasuryRoom.java @@ -22,6 +22,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey; @@ -47,7 +48,11 @@ public class TreasuryRoom extends SpecialRoom { do { pos = level.pointToCell(random()); } while (level.map[pos] != Terrain.EMPTY || level.heaps.get( pos ) != null); - level.drop( new Gold().random(), pos ).type = (Random.Int(20) == 0 && heapType == Heap.Type.CHEST ? Heap.Type.MIMIC : heapType); + if (heapType == Heap.Type.CHEST && Random.Int(5 ) == 0){ + level.mobs.add(Mimic.spawnAt(pos, new Gold().random())); + } else { + level.drop( new Gold().random(), pos ).type = heapType; + } } if (heapType == Heap.Type.HEAP) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/SuspiciousChestRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/SuspiciousChestRoom.java index 9ae33b91a..8ea7367e9 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/SuspiciousChestRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/standard/SuspiciousChestRoom.java @@ -21,6 +21,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; @@ -56,7 +57,7 @@ public class SuspiciousChestRoom extends EmptyRoom { Painter.set(level, center, Terrain.PEDESTAL); if (Random.Int(3) == 0) { - level.drop(i, center).type = Heap.Type.MIMIC; + level.mobs.add(Mimic.spawnAt(center, i)); } else { level.drop(i, center).type = Heap.Type.CHEST; } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java index c63ce67d4..4094488a7 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/traps/DistortionTrap.java @@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.traps; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Acidic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Albino; @@ -121,8 +122,10 @@ public class DistortionTrap extends Trap{ mob = new Piranha(); break; case 2: - Mimic.spawnAt(point, new ArrayList<>()); - continue; //mimics spawn themselves, no need to do more + mob = Mimic.spawnAt(point, new ArrayList<>()); + ((Mimic)mob).stopHiding(); + mob.alignment = Char.Alignment.ENEMY; + break; case 3: mob = Statue.random(); break; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java index 866aa529e..507fd0912 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java @@ -22,34 +22,57 @@ package com.shatteredpixel.shatteredpixeldungeon.sprites; import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.watabou.noosa.TextureFilm; public class MimicSprite extends MobSprite { - + + private Animation hiding; + public MimicSprite() { super(); - + texture( Assets.MIMIC ); - + TextureFilm frames = new TextureFilm( texture, 16, 16 ); - + + hiding = new Animation( 1, true ); + hiding.frames( frames, 0, 0, 0, 0, 0, 0, 1); + idle = new Animation( 5, true ); - idle.frames( frames, 0, 0, 0, 1, 1 ); - + idle.frames( frames, 2, 2, 2, 3, 3 ); + run = new Animation( 10, true ); - run.frames( frames, 0, 1, 2, 3, 3, 2, 1 ); - + run.frames( frames, 2, 3, 4, 5, 5, 4, 3 ); + attack = new Animation( 10, false ); - attack.frames( frames, 0, 4, 5, 6 ); - + attack.frames( frames, 2, 6, 7, 8 ); + die = new Animation( 5, false ); - die.frames( frames, 7, 8, 9 ); - + die.frames( frames, 9, 10, 11 ); + play( idle ); } @Override - public int blood() { - return 0xFFcb9700; + public void linkVisuals(Char ch) { + super.linkVisuals(ch); + if (ch.alignment == Char.Alignment.NEUTRAL) { + hideMimic(); + } } + + public void hideMimic(){ + play(hiding); + hideSleep(); + } + + @Override + public synchronized void showSleep() { + if (curAnim == hiding){ + return; + } + super.showSleep(); + } + } 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 cbe9f1e83..2d5e75c4a 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 @@ -553,7 +553,8 @@ actors.mobs.king$undead.rankings_desc=Fell Before the King of Dwarves actors.mobs.king$undead.desc=These undead dwarves, risen by the will of the King of Dwarves, were members of his court. They appear as skeletons with a stunning amount of facial hair. actors.mobs.mimic.name=mimic -actors.mobs.mimic.desc=Mimics are magical creatures which can take any shape they wish. In dungeons they almost always choose a shape of a treasure chest, because they know how to beckon an adventurer. +actors.mobs.mimic.reveal=That chest is a mimic! +actors.mobs.mimic.desc=Mimics are magical creatures which can take any shape they wish. In dungeons they almost always choose a shape of a treasure chest, in order to lure in unsuspecting adventurers. Mimics have a nasty bite, but often hold more treasure than a regular chest. actors.mobs.necromancer.name=necromancer actors.mobs.necromancer.desc=These apprentice dark mages have flocked to the prison, as it is the perfect place to practise their evil craft.\n\nNecromancers will summon and empower skeletons to fight for them. Killing the necromancer will also kill the skeleton it summons.