From d96351c682cdce22d94302ca6e5b9a22212b96c2 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Mon, 9 Dec 2019 15:22:32 -0500 Subject: [PATCH] v0.8.0: added in a basic implementation for rare mimics --- .../actors/mobs/CrystalMimic.java | 87 +++++++++++++++++++ .../actors/mobs/GoldenMimic.java | 76 ++++++++++++++++ .../actors/mobs/Mimic.java | 22 ++++- .../items/wands/CursedWand.java | 13 ++- .../levels/RegularLevel.java | 17 ++-- .../levels/rooms/special/VaultRoom.java | 8 +- .../sprites/MimicSprite.java | 30 +++++-- 7 files changed, 230 insertions(+), 23 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/CrystalMimic.java create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GoldenMimic.java 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 new file mode 100644 index 000000000..2db1c7e15 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/CrystalMimic.java @@ -0,0 +1,87 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; +import com.shatteredpixel.shatteredpixeldungeon.items.Heap; +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.wands.Wand; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.MimicSprite; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.watabou.noosa.audio.Sample; + +public class CrystalMimic extends Mimic { + + { + spriteClass = MimicSprite.Crystal.class; + } + + @Override + public String name() { + if (alignment == Alignment.NEUTRAL){ + return Messages.get(Heap.class, "crystal_chest"); + } else { + return super.name(); + } + } + + @Override + public String description() { + if (alignment == Alignment.NEUTRAL){ + //TODO variable based on contents + for (Item i : items){ + if (i instanceof Artifact){ + return Messages.get(Heap.class, "crystal_chest_desc", Messages.get(Heap.class, "artifact")); + } else if (i instanceof Ring){ + return Messages.get(Heap.class, "crystal_chest_desc", Messages.get(Heap.class, "ring")); + } else if (i instanceof Wand){ + return Messages.get(Heap.class, "crystal_chest_desc", Messages.get(Heap.class, "wand")); + } + } + return Messages.get(Heap.class, "locked_chest_desc"); + } else { + return super.description(); + } + } + + 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, 1, 1.25f); + } + } + + //TODO different AI + +} 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 new file mode 100644 index 000000000..ff716251e --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/GoldenMimic.java @@ -0,0 +1,76 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2019 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.actors.mobs; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; +import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; +import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; +import com.shatteredpixel.shatteredpixeldungeon.items.Heap; +import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; +import com.shatteredpixel.shatteredpixeldungeon.sprites.MimicSprite; +import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; +import com.watabou.noosa.audio.Sample; + +//TODO should enhance the reward from these a bit, as they are much harder +public class GoldenMimic extends Mimic { + + { + spriteClass = MimicSprite.Golden.class; + } + + @Override + public String name() { + if (alignment == Alignment.NEUTRAL){ + return Messages.get(Heap.class, "locked_chest"); + } else { + return super.name(); + } + } + + @Override + public String description() { + if (alignment == Alignment.NEUTRAL){ + return Messages.get(Heap.class, "locked_chest_desc"); + } else { + return super.description(); + } + } + + 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, 1, 0.85f); + } + } + + @Override + public void adjustStats(int level) { + super.adjustStats((int)Math.ceil(level*1.5f)); + } +} 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 01e522254..c5aaa7d3d 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 @@ -219,12 +219,28 @@ public class Mimic extends Mob { } public static Mimic spawnAt( int pos, Item item ){ - return spawnAt( pos, Arrays.asList(item)); + return spawnAt( pos, Arrays.asList(item), Mimic.class); + } + + public static Mimic spawnAt( int pos, Item item, Class mimicType ){ + return spawnAt( pos, Arrays.asList(item), mimicType); } public static Mimic spawnAt( int pos, List items ) { - - Mimic m = new Mimic(); + return spawnAt( pos, items, Mimic.class); + } + + public static Mimic spawnAt( int pos, List items, Class mimicType ) { + + Mimic m; + if (mimicType == GoldenMimic.class){ + m = new GoldenMimic(); + } else if (mimicType == CrystalMimic.class) { + m = new CrystalMimic(); + } else { + m = new Mimic(); + } + m.items = new ArrayList<>( items ); m.adjustStats( Dungeon.depth ); m.pos = pos; 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 f55f67869..e24d189da 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 @@ -37,8 +37,8 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Burning; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Frost; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Recharging; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GoldenMimic; 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.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.Flare; @@ -366,23 +366,22 @@ public class CursedWand { afterZap.call(); break; - //superpowered mimic + //golden mimic 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()); + Mimic mimic = Mimic.spawnAt(bolt.collisionPos, new ArrayList(), GoldenMimic.class); if (mimic != null) { mimic.stopHiding(); mimic.alignment = Char.Alignment.ENEMY; - mimic.adjustStats(Dungeon.depth + 10); - mimic.HP = mimic.HT; Item reward; do { reward = Generator.random(Random.oneOf(Generator.Category.WEAPON, Generator.Category.ARMOR, Generator.Category.RING, Generator.Category.WAND)); } while (reward.level() < 1); - Sample.INSTANCE.play(Assets.SND_MIMIC, 1, 1, 0.5f); + //play vfx/sfx manually as mimic isn't in the scene yet + Sample.INSTANCE.play(Assets.SND_MIMIC, 1, 0.85f); + CellEmitter.get(mimic.pos).burst(Speck.factory(Speck.STAR), 10); mimic.items.clear(); mimic.items.add(reward); GameScene.add(mimic); 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 0ea060f97..d8259a55e 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.GoldenMimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.items.Generator; @@ -306,17 +307,19 @@ public abstract class RegularLevel extends Level { } type = Heap.Type.CHEST; break; - default: - type = Heap.Type.HEAP; } - //TODO gold mimics if ((toDrop instanceof Artifact && Random.Int(2) == 0) || (toDrop.isUpgradable() && Random.Int(4 - toDrop.level()) == 0)){ - Heap dropped = drop( toDrop, cell ); - if (heaps.get(cell) == dropped) { - dropped.type = Heap.Type.LOCKED_CHEST; - addItemToSpawn(new GoldenKey(Dungeon.depth)); + + if (Random.Int(5) == 0 && findMob(cell) == null){ + mobs.add(Mimic.spawnAt(cell, toDrop, GoldenMimic.class)); + } else { + Heap dropped = drop(toDrop, cell); + if (heaps.get(cell) == dropped) { + dropped.type = Heap.Type.LOCKED_CHEST; + addItemToSpawn(new GoldenKey(Dungeon.depth)); + } } } else { Heap dropped = drop( toDrop, cell ); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/VaultRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/VaultRoom.java index dde0a053e..71d872eb2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/VaultRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/VaultRoom.java @@ -23,6 +23,8 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special; import com.shatteredpixel.shatteredpixeldungeon.Challenges; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.CrystalMimic; +import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic; import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Item; @@ -55,7 +57,11 @@ public class VaultRoom extends SpecialRoom { i1 = prize( level ); i2 = prize( level ); level.drop( i1, c ).type = Heap.Type.CRYSTAL_CHEST; - level.drop( i2, c + PathFinder.NEIGHBOURS8[Random.Int( 8 )]).type = Heap.Type.CRYSTAL_CHEST; + if (Random.Int(10) == 0){ + level.mobs.add(Mimic.spawnAt(c + PathFinder.NEIGHBOURS8[Random.Int(8)], i2, CrystalMimic.class)); + } else { + level.drop(i2, c + PathFinder.NEIGHBOURS8[Random.Int(8)]).type = Heap.Type.CRYSTAL_CHEST; + } level.addItemToSpawn( new CrystalKey( Dungeon.depth ) ); entrance().set( Door.Type.LOCKED ); 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 507fd0912..c21ee41a2 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/sprites/MimicSprite.java @@ -29,27 +29,33 @@ public class MimicSprite extends MobSprite { private Animation hiding; + protected int texOffset(){ + return 0; + } + public MimicSprite() { super(); + int c = texOffset(); + 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); + hiding.frames( frames, 0+c, 0+c, 0+c, 0+c, 0+c, 0+c, 1+c); idle = new Animation( 5, true ); - idle.frames( frames, 2, 2, 2, 3, 3 ); + idle.frames( frames, 2+c, 2+c, 2+c, 3+c, 3+c ); run = new Animation( 10, true ); - run.frames( frames, 2, 3, 4, 5, 5, 4, 3 ); + run.frames( frames, 2+c, 3+c, 4+c, 5+c, 5+c, 4+c, 3+c ); attack = new Animation( 10, false ); - attack.frames( frames, 2, 6, 7, 8 ); + attack.frames( frames, 2+c, 6+c, 7+c, 8+c ); die = new Animation( 5, false ); - die.frames( frames, 9, 10, 11 ); + die.frames( frames, 9+c, 10+c, 11+c ); play( idle ); } @@ -75,4 +81,18 @@ public class MimicSprite extends MobSprite { super.showSleep(); } + public static class Golden extends MimicSprite{ + @Override + protected int texOffset() { + return 16; + } + } + + public static class Crystal extends MimicSprite{ + @Override + protected int texOffset() { + return 32; + } + } + }