diff --git a/assets/traps.png b/assets/traps.png new file mode 100644 index 000000000..8bef3d129 Binary files /dev/null and b/assets/traps.png differ diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/Assets.java b/src/com/shatteredpixel/shatteredpixeldungeon/Assets.java index 24469b926..35bcea4fc 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/Assets.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/Assets.java @@ -89,6 +89,7 @@ public class Assets { public static final String ITEMS = "items.png"; public static final String PLANTS = "plants.png"; + public static final String TRAPS = "traps.png"; public static final String TILES_SEWERS = "tiles0.png"; public static final String TILES_PRISON = "tiles1.png"; diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java b/src/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java index 810a8f1fe..7718c578c 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/items/wands/CursedWand.java @@ -247,7 +247,7 @@ public class CursedWand { //shock and recharge case 3: - LightningTrap.trigger(user.pos, user); + new LightningTrap().set( user.pos ).activate(); Buff.prolong(user, ScrollOfRecharging.Recharging.class, 20f); ScrollOfRecharging.charge(user); SpellSprite.show(user, SpellSprite.CHARGE); @@ -322,7 +322,7 @@ public class CursedWand { //summon monsters case 3: - SummoningTrap.trigger( user.pos, user ); + new SummoningTrap().set( user.pos ).activate(); wand.wandUsed(); break; } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index c6dd3dd11..f35f20d3b 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -731,56 +731,56 @@ public abstract class Level implements Bundlable { GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.TOXIC_TRAP: trap = true; - if (!frozen) ToxicTrap.trigger( cell, ch ); + if (!frozen) new ToxicTrap().set(cell).activate(); break; case Terrain.SECRET_FIRE_TRAP: GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.FIRE_TRAP: trap = true; - if (!frozen) FireTrap.trigger( cell, ch ); + if (!frozen) new FireTrap().set( cell ).activate(); break; case Terrain.SECRET_PARALYTIC_TRAP: GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.PARALYTIC_TRAP: trap = true; - if (!frozen) ParalyticTrap.trigger( cell, ch ); + if (!frozen) new ParalyticTrap().set( cell ).activate(); break; case Terrain.SECRET_POISON_TRAP: GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.POISON_TRAP: trap = true; - if (!frozen) PoisonTrap.trigger( cell, ch ); + if (!frozen) new PoisonTrap().set( cell ).activate(); break; case Terrain.SECRET_ALARM_TRAP: GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.ALARM_TRAP: trap = true; - if (!frozen) AlarmTrap.trigger( cell, ch ); + if (!frozen) new AlarmTrap().set( cell ).activate(); break; case Terrain.SECRET_LIGHTNING_TRAP: GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.LIGHTNING_TRAP: trap = true; - if (!frozen) LightningTrap.trigger( cell, ch ); + if (!frozen) new LightningTrap().set( cell ).activate(); break; case Terrain.SECRET_GRIPPING_TRAP: GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.GRIPPING_TRAP: trap = true; - if (!frozen) GrippingTrap.trigger( cell, ch ); + if (!frozen) new GrippingTrap().set( cell ).activate(); break; case Terrain.SECRET_SUMMONING_TRAP: GLog.i( TXT_HIDDEN_PLATE_CLICKS ); case Terrain.SUMMONING_TRAP: trap = true; - if (!frozen) SummoningTrap.trigger( cell, ch ); + if (!frozen) new SummoningTrap().set( cell ).activate(); break; case Terrain.HIGH_GRASS: @@ -843,35 +843,35 @@ public abstract class Level implements Bundlable { switch (map[cell]) { case Terrain.TOXIC_TRAP: - ToxicTrap.trigger( cell, mob ); + new ToxicTrap().set( cell ).activate(); break; case Terrain.FIRE_TRAP: - FireTrap.trigger( cell, mob ); + new FireTrap().set( cell ).activate(); break; case Terrain.PARALYTIC_TRAP: - ParalyticTrap.trigger( cell, mob ); + new ParalyticTrap().set( cell ).activate(); break; case Terrain.POISON_TRAP: - PoisonTrap.trigger( cell, mob ); + new PoisonTrap().set( cell ).activate(); break; case Terrain.ALARM_TRAP: - AlarmTrap.trigger( cell, mob ); + new AlarmTrap().set( cell ).activate(); break; case Terrain.LIGHTNING_TRAP: - LightningTrap.trigger( cell, mob ); + new LightningTrap().set( cell ).activate(); break; case Terrain.GRIPPING_TRAP: - GrippingTrap.trigger( cell, mob ); + new GrippingTrap().set( cell ).activate(); break; case Terrain.SUMMONING_TRAP: - SummoningTrap.trigger( cell, mob ); + new SummoningTrap().set( cell ).activate(); break; case Terrain.DOOR: diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/AlarmTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/AlarmTrap.java index e5401caa7..7d21cb774 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/AlarmTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/AlarmTrap.java @@ -26,23 +26,26 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.Speck; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; -public class AlarmTrap { +public class AlarmTrap extends Trap { // 0xDD3333 - - public static void trigger( int pos, Char ch ) { - + { + name = "alarm trap"; + image = 4; + } + + @Override + public void activate() { + for (Mob mob : Dungeon.level.mobs) { - if (mob != ch) { mob.beckon( pos ); - } } - + if (Dungeon.visible[pos]) { GLog.w( "The trap emits a piercing sound that echoes throughout the dungeon!" ); CellEmitter.center( pos ).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 ); } - + Sample.INSTANCE.play( Assets.SND_ALERT ); } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/FireTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/FireTrap.java index 153ecd16a..dbedd7ccb 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/FireTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/FireTrap.java @@ -24,14 +24,19 @@ import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; -public class FireTrap { +public class FireTrap extends Trap { // 0xFF7708 - - public static void trigger( int pos, Char ch ) { - + { + name = "fire trap"; + image = 1; + } + + @Override + public void activate() { + GameScene.add( Blob.seed( pos, 2, Fire.class ) ); CellEmitter.get( pos ).burst( FlameParticle.FACTORY, 5 ); - + } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GrippingTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GrippingTrap.java index f71d5c749..aa71a0646 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GrippingTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/GrippingTrap.java @@ -18,6 +18,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.buffs.Bleeding; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff; @@ -25,10 +26,18 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple; import com.shatteredpixel.shatteredpixeldungeon.effects.Wound; import com.watabou.utils.Random; -public class GrippingTrap { - - public static void trigger( int pos, Char c ) { - +public class GrippingTrap extends Trap { + + { + name = "gripping trap"; + image = 6; + } + + @Override + public void activate() { + + Char c = Actor.findChar( pos ); + if (c != null) { int damage = Math.max( 0, (Dungeon.depth + 3) - Random.IntRange( 0, c.dr() / 2 ) ); Buff.affect( c, Bleeding.class ).set( damage ); @@ -37,6 +46,6 @@ public class GrippingTrap { } else { Wound.hit( pos ); } - + } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/LightningTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/LightningTrap.java index f35b44540..8c6c3dbd7 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/LightningTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/LightningTrap.java @@ -17,6 +17,7 @@ */ package com.shatteredpixel.shatteredpixeldungeon.levels.traps; +import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.watabou.noosa.Camera; import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions; @@ -31,20 +32,24 @@ import com.watabou.utils.Random; import java.util.ArrayList; -public class LightningTrap { +public class LightningTrap extends Trap { + + { + name = "lightning trap"; + image = 5; + } + + @Override + public void activate() { + + Char ch = Actor.findChar( pos ); - private static final String name = "lightning trap"; - - // 00x66CCEE - - public static void trigger( int pos, Char ch ) { - if (ch != null) { ch.damage( Math.max( 1, Random.Int( ch.HP / 3, 2 * ch.HP / 3 ) ), LIGHTNING ); if (ch == Dungeon.hero) { - + Camera.main.shake( 2, 0.3f ); - + if (!ch.isAlive()) { Dungeon.fail( Utils.format( ResultDescriptions.TRAP, name ) ); GLog.n( "You were killed by a discharge of a lightning trap..." ); @@ -57,12 +62,12 @@ public class LightningTrap { ch.sprite.parent.add( new Lightning( arcs, null ) ); } - + CellEmitter.center( pos ).burst( SparkParticle.FACTORY, Random.IntRange( 3, 4 ) ); - } - + + //FIXME: this is bad, handle when you rework resistances, make into a category public static final Electricity LIGHTNING = new Electricity(); - public static class Electricity { + public static class Electricity { } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ParalyticTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ParalyticTrap.java index e0d1c19fc..c7032a423 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ParalyticTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ParalyticTrap.java @@ -23,13 +23,18 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ParalyticGas; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; -public class ParalyticTrap { +public class ParalyticTrap extends Trap{ // 0xCCCC55 - - public static void trigger( int pos, Char ch ) { - + { + name = "paralytic gas trap"; + image = 2; + } + + @Override + public void activate() { + GameScene.add( Blob.seed( pos, 80 + 5 * Dungeon.depth, ParalyticGas.class ) ); - + } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/PoisonTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/PoisonTrap.java index 36a2ec365..72cac092a 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/PoisonTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/PoisonTrap.java @@ -18,23 +18,31 @@ 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.buffs.Buff; import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison; import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PoisonParticle; -public class PoisonTrap { +public class PoisonTrap extends Trap{ // 0xBB66EE - - public static void trigger( int pos, Char ch ) { - + { + name = "poison trap"; + image = 3; + } + + @Override + public void activate() { + + Char ch = Actor.findChar( pos ); + if (ch != null) { Buff.affect( ch, Poison.class ).set( Poison.durationFactor( ch ) * (4 + Dungeon.depth / 2) ); } - + CellEmitter.center( pos ).burst( PoisonParticle.SPLASH, 3 ); - + } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java index 95b970992..cce32964d 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/SummoningTrap.java @@ -29,24 +29,31 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.watabou.utils.Random; -public class SummoningTrap { +public class SummoningTrap extends Trap { private static final float DELAY = 2f; private static final Mob DUMMY = new Mob() {}; // 0x770088 - - public static void trigger( int pos, Char c ) { - + { + name = "summoning trap"; + image = 7; + } + + @Override + public void activate() { + if (Dungeon.bossLevel()) { return; } - + + Char c = Actor.findChar( pos ); + if (c != null) { Actor.occupyCell( c ); } - + int nMobs = 1; if (Random.Int( 2 ) == 0) { nMobs++; @@ -54,35 +61,36 @@ public class SummoningTrap { nMobs++; } } - + // It's complicated here, because these traps can be activated in chain - - ArrayList candidates = new ArrayList(); - + + ArrayList candidates = new ArrayList<>(); + for (int i=0; i < Level.NEIGHBOURS8.length; i++) { int p = pos + Level.NEIGHBOURS8[i]; if (Actor.findChar( p ) == null && (Level.passable[p] || Level.avoid[p])) { candidates.add( p ); } } - - ArrayList respawnPoints = new ArrayList(); - + + ArrayList respawnPoints = new ArrayList<>(); + while (nMobs > 0 && candidates.size() > 0) { int index = Random.index( candidates ); - + DUMMY.pos = candidates.get( index ); Actor.occupyCell( DUMMY ); - + respawnPoints.add( candidates.remove( index ) ); nMobs--; } - + for (Integer point : respawnPoints) { Mob mob = Bestiary.mob( Dungeon.depth ); mob.state = mob.WANDERING; GameScene.add( mob, DELAY ); ScrollOfTeleportation.appear( mob, point ); } + } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ToxicTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ToxicTrap.java index cd3aa6100..ba5502413 100644 --- a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ToxicTrap.java +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/ToxicTrap.java @@ -23,13 +23,18 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; -public class ToxicTrap { +public class ToxicTrap extends Trap{ // 0x40CC55 - - public static void trigger( int pos, Char ch ) { - + { + name = "toxic gas trap"; + image = 0; + } + + @Override + public void activate() { + GameScene.add( Blob.seed( pos, 300 + 20 * Dungeon.depth, ToxicGas.class ) ); - + } } diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/Trap.java b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/Trap.java new file mode 100644 index 000000000..466017f7b --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/levels/traps/Trap.java @@ -0,0 +1,70 @@ +package com.shatteredpixel.shatteredpixeldungeon.levels.traps; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite; +import com.watabou.noosa.audio.Sample; +import com.watabou.utils.Bundlable; +import com.watabou.utils.Bundle; + +public abstract class Trap implements Bundlable { + + public String name; + + public int image; + public int pos; + + public TrapSprite sprite; + public boolean visible; + + private static final String POS = "pos"; + + public Trap set(int pos){ + this.pos = pos; + return this; + } + + public void reveal() { + visible = true; + if (sprite != null) + sprite.visible = true; + } + + public void hide() { + visible = false; + if (sprite != null) + sprite.visible = false; + } + + public void trigger() { + if (Dungeon.visible[pos]){ + Sample.INSTANCE.play(Assets.SND_TRAP); + } + activate(); + disarm(); + } + + public abstract void activate(); + + protected void disarm(){ + //Dungeon.level.traps.delete( pos ); + Level.set(pos, Terrain.INACTIVE_TRAP); + sprite.kill(); + } + + @Override + public void restoreFromBundle( Bundle bundle ) { + pos = bundle.getInt( POS ); + } + + @Override + public void storeInBundle( Bundle bundle ) { + bundle.put( POS, pos ); + } + + public String desc() { + return ""; + } +} diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/sprites/TrapSprite.java b/src/com/shatteredpixel/shatteredpixeldungeon/sprites/TrapSprite.java new file mode 100644 index 000000000..5ed8170cb --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/sprites/TrapSprite.java @@ -0,0 +1,49 @@ +package com.shatteredpixel.shatteredpixeldungeon.sprites; + +import com.shatteredpixel.shatteredpixeldungeon.Assets; +import com.shatteredpixel.shatteredpixeldungeon.Dungeon; +import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap; +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; +import com.watabou.noosa.Image; +import com.watabou.noosa.TextureFilm; + +public class TrapSprite extends Image { + + private static TextureFilm frames; + + private int pos = -1; + + public TrapSprite() { + super( Assets.TRAPS ); + + if (frames == null) { + frames = new TextureFilm( texture, 16, 16 ); + } + + origin.set( 8, 12 ); + } + + public TrapSprite( int image ) { + this(); + reset( image ); + } + + public void reset( Trap trap ) { + + revive(); + + reset( trap.image + (((Dungeon.depth-1) / 5) * 8) ); + alpha( 1f ); + + pos = trap.pos; + x = (pos % Level.WIDTH) * DungeonTilemap.SIZE; + y = (pos / Level.WIDTH) * DungeonTilemap.SIZE; + + } + + public void reset( int image ) { + frame( frames.get( image ) ); + } + +} diff --git a/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTrap.java b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTrap.java new file mode 100644 index 000000000..75fd8f064 --- /dev/null +++ b/src/com/shatteredpixel/shatteredpixeldungeon/windows/WndInfoTrap.java @@ -0,0 +1,14 @@ +package com.shatteredpixel.shatteredpixeldungeon.windows; + +import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap; +import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite; + +public class WndInfoTrap extends WndTitledMessage { + + public WndInfoTrap(Trap trap) { + + super(new TrapSprite( trap.image ), trap.name, trap.desc()); + + } + +}