diff --git a/core/src/main/assets/messages/items/items.properties b/core/src/main/assets/messages/items/items.properties index 70f0b3fb3..dbbd6d240 100644 --- a/core/src/main/assets/messages/items/items.properties +++ b/core/src/main/assets/messages/items/items.properties @@ -1303,6 +1303,9 @@ items.trinkets.dimensionalsundial.desc=This small handheld sundial is somehow ab items.trinkets.exoticcrystals.name=exotic crystals items.trinkets.exoticcrystals.desc=These small pink crystals have the same shape as crystals of alchemical energy. While they can't be used for energy directly, they seem to be somehow influencing the potions and scrolls you find.\n\nAt its current level this trinket will replace _%d%%_ of potion or scroll drops with their exotic equivalents. This does not affect potions of strength, scrolls of upgrade, or items that are generated to help solve hazard rooms. +items.trinkets.mimictooth.name=mimic tooth +items.trinkets.mimictooth.desc=TODO\n\nAt its current level this trinket will make all kinds of mimics _%sx_ more common, and will make mimics more difficult to detect. + items.trinkets.mossyclump.name=mossy clump items.trinkets.mossyclump.desc=This clump of wet moss seems to hold onto its moisture no matter how hard you squeeze it. It seems to be magically tied to the dungeon itself, making grass and water more likely to appear.\n\nAt its current level this trinket will make _%d%%_ of regular floors become filled with either water or grass instead.\n\nThis trinket costs a relatively large amount of energy to upgrade. diff --git a/core/src/main/assets/sprites/items.png b/core/src/main/assets/sprites/items.png index 284c90d46..5c78a277f 100644 Binary files a/core/src/main/assets/sprites/items.png and b/core/src/main/assets/sprites/items.png differ diff --git a/core/src/main/assets/sprites/mimic.png b/core/src/main/assets/sprites/mimic.png index 85ba44756..7f13275b9 100644 Binary files a/core/src/main/assets/sprites/mimic.png and b/core/src/main/assets/sprites/mimic.png differ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java index d437f5f7f..152cdddad 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/Dungeon.java @@ -35,6 +35,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Terror; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost; @@ -48,6 +49,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesi import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfRegrowth; import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfWarding; import com.shatteredpixel.shatteredpixeldungeon.journal.Notes; @@ -943,8 +945,13 @@ public class Dungeon { GameScene.updateFog(l, t, width, height); + boolean stealthyMimics = MimicTooth.stealthyMimics(); if (hero.buff(MindVision.class) != null){ for (Mob m : level.mobs.toArray(new Mob[0])){ + if (stealthyMimics && m instanceof Mimic && m.alignment == Char.Alignment.NEUTRAL){ + continue; + } + BArray.or( level.visited, level.heroFOV, m.pos - 1 - level.width(), 3, level.visited ); BArray.or( level.visited, level.heroFOV, m.pos - 1, 3, level.visited ); BArray.or( level.visited, level.heroFOV, m.pos - 1 + level.width(), 3, level.visited ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/CrystalMimic.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/CrystalMimic.java index 36f372ec0..3028a682b 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/CrystalMimic.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/CrystalMimic.java @@ -36,6 +36,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact; import com.shatteredpixel.shatteredpixeldungeon.items.rings.Ring; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.sprites.MimicSprite; @@ -82,7 +83,10 @@ public class CrystalMimic extends Mimic { if (desc == null) { desc = Messages.get(Heap.class, "locked_chest_desc"); } - return desc + "\n\n" + Messages.get(this, "hidden_hint"); + if (!MimicTooth.stealthyMimics()){ + desc += "\n\n" + Messages.get(this, "hidden_hint"); + } + return desc; } else { return super.description(); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GoldenMimic.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GoldenMimic.java index 2b7f9a0d0..3cde1a1a6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GoldenMimic.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GoldenMimic.java @@ -31,6 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.armor.Armor; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.Artifact; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.wands.Wand; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon; @@ -58,7 +59,11 @@ public class GoldenMimic extends Mimic { @Override public String description() { if (alignment == Alignment.NEUTRAL){ - return Messages.get(Heap.class, "locked_chest_desc") + "\n\n" + Messages.get(this, "hidden_hint"); + if (MimicTooth.stealthyMimics()){ + return Messages.get(Heap.class, "locked_chest_desc"); + } else { + return Messages.get(Heap.class, "locked_chest_desc") + "\n\n" + Messages.get(this, "hidden_hint"); + } } else { return super.description(); } 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 f805be5b7..e0ba09ade 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 @@ -34,6 +34,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TimekeepersHourglass; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.plants.Swiftthistle; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; @@ -114,7 +115,11 @@ public class Mimic extends Mob { @Override public String description() { if (alignment == Alignment.NEUTRAL){ - return Messages.get(Heap.class, "chest_desc") + "\n\n" + Messages.get(this, "hidden_hint"); + if (MimicTooth.stealthyMimics()){ + return Messages.get(Heap.class, "chest_desc"); + } else { + return Messages.get(Heap.class, "chest_desc") + "\n\n" + Messages.get(this, "hidden_hint"); + } } else { return super.description(); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java index f95bc0649..e592d3d97 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/Generator.java @@ -108,6 +108,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfShock; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.DimensionalSundial; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ExoticCrystals; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MossyClump; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.ParchmentScrap; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.PetrifiedSeed; @@ -561,12 +562,13 @@ public class Generator { ParchmentScrap.class, PetrifiedSeed.class, ExoticCrystals.class, + MimicTooth.class, MossyClump.class, DimensionalSundial.class, ThirteenLeafClover.class, TrapMechanism.class }; - TRINKET.defaultProbs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 1 }; + TRINKET.defaultProbs = new float[]{ 1, 1, 1, 1, 1, 1, 1, 1, 1 }; TRINKET.probs = TRINKET.defaultProbs.clone(); for (Category cat : Category.values()){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MimicTooth.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MimicTooth.java new file mode 100644 index 000000000..ede02c843 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MimicTooth.java @@ -0,0 +1,60 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2024 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.items.trinkets; + +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSpriteSheet; + +public class MimicTooth extends Trinket { + + { + image = ItemSpriteSheet.MIMIC_TOOTH; + } + + @Override + protected int upgradeEnergyCost() { + //5 -> 8(13) -> 10(23) -> 12(35) + return 6+2*level(); + } + + @Override + public String desc() { + return Messages.get(this, "desc", Float.toString(mimicChanceMultiplier(buffedLvl()))); + } + + public static float mimicChanceMultiplier(){ + return mimicChanceMultiplier(trinketLevel(MimicTooth.class)); + } + + public static float mimicChanceMultiplier( int level ){ + if (level == -1){ + return 1f; + } else { + return 1.5f + 0.5f*level; + } + } + + public static boolean stealthyMimics(){ + return trinketLevel(MimicTooth.class) >= 0; + } + +} 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 bd9f1b3c6..44da2fd4f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -49,6 +49,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.abilities.huntress.SpiritHawk; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GnollGeomancer; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Piranha; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.YogFist; @@ -67,6 +68,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfEnchantment; import com.shatteredpixel.shatteredpixeldungeon.items.stones.StoneOfIntuition; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MossyClump; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.DimensionalSundial; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrapMechanism; @@ -1352,8 +1354,12 @@ public abstract class Level implements Bundlable { } Dungeon.hero.mindVisionEnemies.clear(); + boolean stealthyMimics = MimicTooth.stealthyMimics(); if (c.buff( MindVision.class ) != null) { for (Mob mob : mobs) { + if (stealthyMimics && mob instanceof Mimic && mob.alignment == Char.Alignment.NEUTRAL){ + continue; + } for (int i : PathFinder.NEIGHBOURS9) { heroMindFov[mob.pos + i] = true; } @@ -1362,6 +1368,9 @@ public abstract class Level implements Bundlable { Hero h = (Hero) c; int range = 1+h.pointsInTalent(Talent.HEIGHTENED_SENSES); for (Mob mob : mobs) { + if (stealthyMimics && mob instanceof Mimic && mob.alignment == Char.Alignment.NEUTRAL){ + continue; + } int p = mob.pos; if (!fieldOfView[p] && distance(c.pos, p) <= range) { for (int i : PathFinder.NEIGHBOURS9) { 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 50e48ded9..a2673413f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java @@ -48,6 +48,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.journal.GuidePage; import com.shatteredpixel.shatteredpixeldungeon.items.journal.RegionLorePage; import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey; import com.shatteredpixel.shatteredpixeldungeon.items.keys.Key; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrinketCatalyst; import com.shatteredpixel.shatteredpixeldungeon.journal.Document; import com.shatteredpixel.shatteredpixeldungeon.journal.Notes; @@ -384,6 +385,13 @@ public abstract class RegularLevel extends Level { case 2: case 3: case 4: + //base mimic chance is 1/20, regular chest is 4/20 + // so each +1x mimic spawn rate converts to a 25% chance here + if (Random.Float() < (MimicTooth.mimicChanceMultiplier() - 1f)/4f && findMob(cell) == null){ + mobs.add(Mimic.spawnAt(cell, toDrop)); + continue; + } + type = Heap.Type.CHEST; break; case 5: @@ -401,7 +409,8 @@ public abstract class RegularLevel extends Level { if ((toDrop instanceof Artifact && Random.Int(2) == 0) || (toDrop.isUpgradable() && Random.Int(4 - toDrop.level()) == 0)){ - if (Dungeon.depth > 1 && Random.Int(10) == 0 && findMob(cell) == null){ + float mimicChance = 1/10f * MimicTooth.mimicChanceMultiplier(); + if (Dungeon.depth > 1 && Random.Float() < mimicChance && findMob(cell) == null){ mobs.add(Mimic.spawnAt(cell, GoldenMimic.class, toDrop)); } else { Heap dropped = drop(toDrop, cell); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalVaultRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalVaultRoom.java index d4af2d1ac..810762d8c 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalVaultRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/CrystalVaultRoom.java @@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.keys.CrystalKey; import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.RatSkull; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; @@ -73,6 +74,7 @@ public class CrystalVaultRoom extends SpecialRoom { level.drop( i1, i1Pos ).type = Heap.Type.CRYSTAL_CHEST; float altChance = 1/10f * RatSkull.exoticChanceMultiplier(); if (altChance > 0.1f) altChance = (altChance+0.1f)/2f; //rat skull is 1/2 as effective here + altChance *= MimicTooth.mimicChanceMultiplier(); //mimic tooth has full effectiveness if (Random.Float() < altChance){ level.mobs.add(Mimic.spawnAt(i2Pos, CrystalMimic.class, i2)); } else { 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 31a6ca9ad..4b5104e92 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 @@ -27,6 +27,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Gold; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.TrinketCatalyst; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; @@ -45,6 +46,7 @@ public class TreasuryRoom extends SpecialRoom { Heap.Type heapType = Random.Int( 2 ) == 0 ? Heap.Type.CHEST : Heap.Type.HEAP; int n = Random.IntRange( 2, 3 ); + float mimicChance = 1/5f * MimicTooth.mimicChanceMultiplier(); for (int i=0; i < n; i++) { Item item = level.findPrizeItem(TrinketCatalyst.class); if (item == null) item = new Gold().random(); @@ -53,7 +55,7 @@ public class TreasuryRoom extends SpecialRoom { do { pos = level.pointToCell(random()); } while (level.map[pos] != Terrain.EMPTY || level.heaps.get( pos ) != null || level.findMob(pos) != null); - if (heapType == Heap.Type.CHEST && Dungeon.depth > 1 && Random.Int( 5 ) == 0){ + if (heapType == Heap.Type.CHEST && Dungeon.depth > 1 && Random.Float() < mimicChance){ level.mobs.add(Mimic.spawnAt(pos, item)); } else { level.drop( item, pos ).type = heapType; 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 c318622e8..2d8d4d655 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 @@ -25,6 +25,7 @@ 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; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; @@ -61,7 +62,8 @@ public class SuspiciousChestRoom extends StandardRoom { Painter.set(level, center, Terrain.PEDESTAL); - if (Random.Int(3) == 0) { + float mimicChance = 1/3f * MimicTooth.mimicChanceMultiplier(); + if (Random.Float() < mimicChance) { 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/scenes/GameScene.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java index 15dfd52df..b4b6cc57a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/scenes/GameScene.java @@ -41,6 +41,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Talent; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.DemonSpawner; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Ghoul; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Snake; import com.shatteredpixel.shatteredpixeldungeon.effects.BannerSprites; @@ -59,6 +60,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.journal.Guidebook; import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation; import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.DimensionalSundial; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.shatteredpixel.shatteredpixeldungeon.journal.Document; import com.shatteredpixel.shatteredpixeldungeon.journal.Journal; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; @@ -1285,8 +1287,16 @@ public class GameScene extends PixelScene { public static void afterObserve() { if (scene != null) { + boolean stealthyMimics = MimicTooth.stealthyMimics(); for (Mob mob : Dungeon.level.mobs.toArray(new Mob[0])) { - if (mob.sprite != null) mob.sprite.visible = Dungeon.level.heroFOV[mob.pos]; + if (mob.sprite != null) { + if (stealthyMimics && mob instanceof Mimic && mob.state == mob.PASSIVE && mob.sprite.visible){ + //mimics stay visible in fog of war after being first seen + mob.sprite.visible = true; + } else { + mob.sprite.visible = Dungeon.level.heroFOV[mob.pos]; + } + } if (mob instanceof Ghoul){ for (Ghoul.GhoulLifeLink link : mob.buffs(Ghoul.GhoulLifeLink.class)){ link.updateVisibility(); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java index d4964ac1a..e5a50b7a6 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/ItemSpriteSheet.java @@ -480,15 +480,17 @@ public class ItemSpriteSheet { public static final int SUNDIAL = TRINKETS+5; public static final int CLOVER = TRINKETS+6; public static final int TRAP_MECHANISM = TRINKETS+7; + public static final int MIMIC_TOOTH = TRINKETS+8; static{ - assignItemRect(RAT_SKULL, 16, 11); - assignItemRect(PARCHMENT_SCRAP, 10, 14); - assignItemRect(PETRIFIED_SEED, 10, 10); - assignItemRect(EXOTIC_CRYSTALS, 14, 13); - assignItemRect(MOSSY_CLUMP, 12, 11); - assignItemRect(SUNDIAL, 16, 12); - assignItemRect(CLOVER, 11, 15); - assignItemRect(TRAP_MECHANISM, 13, 15); + assignItemRect(RAT_SKULL, 16, 11); + assignItemRect(PARCHMENT_SCRAP, 10, 14); + assignItemRect(PETRIFIED_SEED, 10, 10); + assignItemRect(EXOTIC_CRYSTALS, 14, 13); + assignItemRect(MOSSY_CLUMP, 12, 11); + assignItemRect(SUNDIAL, 16, 12); + assignItemRect(CLOVER, 11, 15); + assignItemRect(TRAP_MECHANISM, 13, 15); + assignItemRect(MIMIC_TOOTH, 7, 13); } private static final int SCROLLS = xy(1, 19); //16 slots 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 527847db0..341b9a6b0 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java @@ -23,10 +23,13 @@ package com.shatteredpixel.shatteredpixeldungeon.sprites; import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.actors.Char; +import com.shatteredpixel.shatteredpixeldungeon.items.trinkets.MimicTooth; import com.watabou.noosa.TextureFilm; public class MimicSprite extends MobSprite { + private Animation advancedHiding; + private Animation hiding; { @@ -49,20 +52,23 @@ public class MimicSprite extends MobSprite { TextureFilm frames = new TextureFilm( texture, 16, 16 ); + advancedHiding = new Animation( 1, true ); + advancedHiding.frames( frames, 0+c); + hiding = new Animation( 1, true ); - hiding.frames( frames, 0+c, 0+c, 0+c, 0+c, 0+c, 1+c); + hiding.frames( frames, 1+c, 1+c, 1+c, 1+c, 1+c, 2+c); idle = new Animation( 5, true ); - idle.frames( frames, 2+c, 2+c, 2+c, 3+c, 3+c ); + idle.frames( frames, 3+c, 3+c, 3+c, 4+c, 4+c ); run = new Animation( 10, true ); - run.frames( frames, 2+c, 3+c, 4+c, 5+c, 5+c, 4+c, 3+c ); + run.frames( frames, 3+c, 4+c, 5+c, 6+c, 6+c, 5+c, 4+c ); attack = new Animation( 10, false ); - attack.frames( frames, 2+c, 6+c, 7+c, 8+c ); + attack.frames( frames, 3+c, 7+c, 8+c, 9+c ); die = new Animation( 5, false ); - die.frames( frames, 9+c, 10+c, 11+c ); + die.frames( frames, 10+c, 111+c, 12+c ); play( idle ); } @@ -76,13 +82,17 @@ public class MimicSprite extends MobSprite { } public void hideMimic(){ - play(hiding); + if (MimicTooth.stealthyMimics()){ + play(advancedHiding); + } else { + play(hiding); + } hideSleep(); } @Override public void showSleep() { - if (curAnim == hiding){ + if (curAnim == hiding || curAnim == advancedHiding){ return; } super.showSleep();