From c67dc832715f8210ffd0ae52f829c7feffcc6ee5 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 6 May 2024 11:35:57 -0400 Subject: [PATCH] v2.4.0: implemented part of new mimic tooth trinket --- .../assets/messages/items/items.properties | 3 + core/src/main/assets/sprites/items.png | Bin 23382 -> 23420 bytes core/src/main/assets/sprites/mimic.png | Bin 3033 -> 3139 bytes .../shatteredpixeldungeon/Dungeon.java | 7 ++ .../actors/mobs/CrystalMimic.java | 6 +- .../actors/mobs/GoldenMimic.java | 7 +- .../actors/mobs/Mimic.java | 7 +- .../items/Generator.java | 4 +- .../items/trinkets/MimicTooth.java | 60 ++++++++++++++++++ .../shatteredpixeldungeon/levels/Level.java | 9 +++ .../levels/RegularLevel.java | 11 +++- .../rooms/special/CrystalVaultRoom.java | 2 + .../levels/rooms/special/TreasuryRoom.java | 4 +- .../rooms/standard/SuspiciousChestRoom.java | 4 +- .../scenes/GameScene.java | 12 +++- .../sprites/ItemSpriteSheet.java | 18 +++--- .../sprites/MimicSprite.java | 24 +++++-- 17 files changed, 155 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/trinkets/MimicTooth.java 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 284c90d46c771afcc8699a2f46ada5d44c5c2d8c..5c78a277fc50ef7350be065a083f3f45ee235a2a 100644 GIT binary patch delta 14976 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 diff --git a/core/src/main/assets/sprites/mimic.png b/core/src/main/assets/sprites/mimic.png index 85ba447566a226e86e69701e68ad46e0d675b215..7f13275b983591dcf80ad15af1c4543f46077a18 100644 GIT binary patch delta 2706 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 delta 2599 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 JPDHLkV1jS#(Ru&? 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();