v0.3.0c: trap refactor pt2, traps completely changed to work based on instantiable trap objects instead of terrain types

This makes the trap system far more extendable.
This commit is contained in:
Evan Debenham
2015-06-03 20:40:58 -04:00
parent 7e79a10501
commit 85a907d14e
25 changed files with 336 additions and 285 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -154,7 +154,7 @@ public class Dungeon {
quickslot.reset();
QuickSlotButton.reset();
depth = 0;
depth = 24;
gold = 0;
droppedItems = new SparseArray<ArrayList<Item>>();

View File

@@ -403,8 +403,11 @@ public abstract class Char extends Actor {
if (Dungeon.level.map[pos] == Terrain.OPEN_DOOR) {
Door.leave( pos );
}
Actor.freeCell(pos);
pos = step;
Actor.occupyCell( this );
if (flying && Dungeon.level.map[pos] == Terrain.DOOR) {
Door.enter( pos );

View File

@@ -56,8 +56,7 @@ public class WaterOfAwareness extends WellWater {
int terr = Dungeon.level.map[i];
if ((Terrain.flags[terr] & Terrain.SECRET) != 0) {
Level.set( i, Terrain.discover( terr ) );
GameScene.updateMap( i );
Dungeon.level.discover( i );
if (Dungeon.visible[i]) {
GameScene.discoverTile( i, terr );

View File

@@ -1283,8 +1283,7 @@ public class Hero extends Char {
visited[i] = true;
if ((Terrain.flags[terr] & Terrain.SECRET) != 0) {
Level.set( i, Terrain.discover( terr ) );
GameScene.updateMap( i );
Dungeon.level.discover( i );
}
}
}
@@ -1452,9 +1451,7 @@ public class Hero extends Char {
GameScene.discoverTile( p, oldValue );
Level.set( p, Terrain.discover( oldValue ) );
GameScene.updateMap( p );
Dungeon.level.discover( p );
ScrollOfMagicMapping.discover( p );

View File

@@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfMindVision
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfFireblast;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfMagicMissile;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.Dagger;
@@ -119,6 +120,9 @@ public enum HeroClass {
if (!Dungeon.isChallenged(Challenges.NO_FOOD))
new Food().identify().collect();
hero.HP = hero.HT = 10000;
new WandOfFireblast().identify().upgrade(50).collect();
}
public Badges.Badge masteryBadge() {

View File

@@ -20,6 +20,7 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import java.util.HashSet;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.LloydsBeacon;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.PoisonTrap;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
@@ -147,8 +148,8 @@ public class Tengu extends Mob {
} while (!Level.fieldOfView[trapPos] || !Level.passable[trapPos]);
if (Dungeon.level.map[trapPos] == Terrain.INACTIVE_TRAP) {
Level.set( trapPos, Terrain.POISON_TRAP );
GameScene.updateMap( trapPos );
Dungeon.level.setTrap( new PoisonTrap().reveal(), trapPos );
Level.set( trapPos, Terrain.TRAP );
ScrollOfMagicMapping.discover( trapPos );
}
}

View File

@@ -57,8 +57,7 @@ public class ScrollOfMagicMapping extends Scroll {
mapped[i] = true;
if ((Terrain.flags[terr] & Terrain.SECRET) != 0) {
Level.set( i, Terrain.discover( terr ) );
GameScene.updateMap( i );
Dungeon.level.discover( i );
if (Dungeon.visible[i]) {
GameScene.discoverTile( i, terr );

View File

@@ -109,8 +109,7 @@ public class WandOfPrismaticLight extends Wand {
int terr = Dungeon.level.map[cell];
if ((Terrain.flags[terr] & Terrain.SECRET) != 0) {
Level.set( cell, Terrain.discover( terr ) );
GameScene.updateMap(cell);
Dungeon.level.discover( cell );
GameScene.discoverTile( cell, terr );
ScrollOfMagicMapping.discover(cell);

View File

@@ -127,9 +127,10 @@ public class CavesBossLevel extends Level {
ROOM_RIGHT - ROOM_LEFT + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL );
Painter.fill( this, ROOM_LEFT, ROOM_TOP + 1,
ROOM_RIGHT - ROOM_LEFT + 1, ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY );
//TODO Trap refactor
Painter.fill( this, ROOM_LEFT, ROOM_TOP,
ROOM_RIGHT - ROOM_LEFT + 1, 1, Terrain.TOXIC_TRAP );
ROOM_RIGHT - ROOM_LEFT + 1, 1, Terrain.INACTIVE_TRAP );
arenaDoor = Random.Int( ROOM_LEFT, ROOM_RIGHT ) + (ROOM_BOTTOM + 1) * WIDTH;
map[arenaDoor] = Terrain.DOOR;

View File

@@ -70,6 +70,7 @@ import com.shatteredpixel.shatteredpixeldungeon.plants.Plant;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.ItemSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.Game;
import com.watabou.noosa.Scene;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.Bundlable;
@@ -120,7 +121,8 @@ public abstract class Level implements Bundlable {
public static boolean resizingNeeded;
public static int loadedMapSize;
public int version;
public int[] map;
public boolean[] visited;
public boolean[] mapped;
@@ -152,15 +154,17 @@ public abstract class Level implements Bundlable {
public SparseArray<Heap> heaps;
public HashMap<Class<? extends Blob>,Blob> blobs;
public SparseArray<Plant> plants;
public SparseArray<Trap> traps;
protected ArrayList<Item> itemsToSpawn = new ArrayList<Item>();
protected ArrayList<Item> itemsToSpawn = new ArrayList<>();
public int color1 = 0x004400;
public int color2 = 0x88CC44;
protected static boolean pitRoomNeeded = false;
protected static boolean weakFloorCreated = false;
private static final String VERSION = "version";
private static final String MAP = "map";
private static final String VISITED = "visited";
private static final String MAPPED = "mapped";
@@ -169,6 +173,7 @@ public abstract class Level implements Bundlable {
private static final String LOCKED = "locked";
private static final String HEAPS = "heaps";
private static final String PLANTS = "plants";
private static final String TRAPS = "traps";
private static final String MOBS = "mobs";
private static final String BLOBS = "blobs";
private static final String FEELING = "feeling";
@@ -253,10 +258,11 @@ public abstract class Level implements Bundlable {
pitRoomNeeded = pitNeeded;
weakFloorCreated = false;
mobs = new HashSet<Mob>();
heaps = new SparseArray<Heap>();
blobs = new HashMap<Class<? extends Blob>,Blob>();
plants = new SparseArray<Plant>();
mobs = new HashSet<>();
heaps = new SparseArray<>();
blobs = new HashMap<>();
plants = new SparseArray<>();
traps = new SparseArray<>();
} while (!build());
decorate();
@@ -280,13 +286,17 @@ public abstract class Level implements Bundlable {
@Override
public void restoreFromBundle( Bundle bundle ) {
version = bundle.getInt( VERSION );
mobs = new HashSet<Mob>();
heaps = new SparseArray<Heap>();
blobs = new HashMap<Class<? extends Blob>, Blob>();
plants = new SparseArray<Plant>();
mobs = new HashSet<>();
heaps = new SparseArray<>();
blobs = new HashMap<>();
plants = new SparseArray<>();
traps = new SparseArray<>();
map = bundle.getIntArray( MAP );
visited = bundle.getBooleanArray( VISITED );
mapped = bundle.getBooleanArray( MAPPED );
@@ -298,6 +308,12 @@ public abstract class Level implements Bundlable {
weakFloorCreated = false;
adjustMapSize();
//for pre-0.3.0c saves
//TODO: update to final value of 44 after testing
if (version < 43){
map = Terrain.convertTrapsFrom43( map, traps );
}
Collection<Bundlable> collection = bundle.getCollection( HEAPS );
for (Bundlable h : collection) {
@@ -317,6 +333,15 @@ public abstract class Level implements Bundlable {
}
plants.put( plant.pos, plant );
}
collection = bundle.getCollection( TRAPS );
for (Bundlable p : collection) {
Trap trap = (Trap)p;
if (resizingNeeded) {
trap.pos = adjustPos( trap.pos );
}
traps.put( trap.pos, trap );
}
collection = bundle.getCollection( MOBS );
for (Bundlable m : collection) {
@@ -345,6 +370,7 @@ public abstract class Level implements Bundlable {
@Override
public void storeInBundle( Bundle bundle ) {
bundle.put( VERSION, Game.versionCode );
bundle.put( MAP, map );
bundle.put( VISITED, visited );
bundle.put( MAPPED, mapped );
@@ -353,6 +379,7 @@ public abstract class Level implements Bundlable {
bundle.put( LOCKED, locked );
bundle.put( HEAPS, heaps.values() );
bundle.put( PLANTS, plants.values() );
bundle.put( TRAPS, traps.values() );
bundle.put( MOBS, mobs );
bundle.put( BLOBS, blobs.values() );
bundle.put( FEELING, feeling );
@@ -700,6 +727,27 @@ public abstract class Level implements Bundlable {
public void uproot( int pos ) {
plants.delete( pos );
}
public Trap setTrap( Trap trap, int pos ){
trap.set( pos );
traps.put( pos, trap );
GameScene.add(trap);
return trap;
}
public void disarmTrap( int pos ) {
traps.delete(pos);
set(pos, Terrain.INACTIVE_TRAP);
GameScene.updateMap(pos);
}
public void discover( int cell ) {
set( cell, Terrain.discover( map[cell] ) );
Trap trap = traps.get( cell );
if (trap != null)
trap.reveal();
GameScene.updateMap( cell );
}
public int pitCell() {
return randomRespawnCell();
@@ -723,64 +771,14 @@ public abstract class Level implements Bundlable {
boolean frozen = timeFreeze != null;
boolean trap = false;
Trap trap = null;
switch (map[cell]) {
case Terrain.SECRET_TOXIC_TRAP:
case Terrain.SECRET_TRAP:
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
case Terrain.TOXIC_TRAP:
trap = true;
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) 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) 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) 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) 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) 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) 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) new SummoningTrap().set( cell ).activate();
case Terrain.TRAP:
trap = traps.get( cell );
break;
case Terrain.HIGH_GRASS:
@@ -802,23 +800,18 @@ public abstract class Level implements Bundlable {
break;
}
if (trap && !frozen) {
if (Dungeon.visible[cell])
Sample.INSTANCE.play( Assets.SND_TRAP );
if (trap != null && !frozen) {
if (ch == Dungeon.hero)
Dungeon.hero.interrupt();
set( cell, Terrain.INACTIVE_TRAP );
GameScene.updateMap( cell );
trap.trigger();
} else if (trap && frozen){
} else if (trap != null && frozen){
Sample.INSTANCE.play( Assets.SND_TRAP );
Sample.INSTANCE.play(Assets.SND_TRAP);
Level.set( cell, Terrain.discover( map[cell] ) );
GameScene.updateMap( cell );
discover(cell);
timeFreeze.setDelayedPress( cell );
@@ -839,54 +832,20 @@ public abstract class Level implements Bundlable {
return;
}
boolean trap = true;
Trap trap = null;
switch (map[cell]) {
case Terrain.TOXIC_TRAP:
new ToxicTrap().set( cell ).activate();
break;
case Terrain.FIRE_TRAP:
new FireTrap().set( cell ).activate();
break;
case Terrain.PARALYTIC_TRAP:
new ParalyticTrap().set( cell ).activate();
break;
case Terrain.POISON_TRAP:
new PoisonTrap().set( cell ).activate();
break;
case Terrain.ALARM_TRAP:
new AlarmTrap().set( cell ).activate();
break;
case Terrain.LIGHTNING_TRAP:
new LightningTrap().set( cell ).activate();
break;
case Terrain.GRIPPING_TRAP:
new GrippingTrap().set( cell ).activate();
break;
case Terrain.SUMMONING_TRAP:
new SummoningTrap().set( cell ).activate();
case Terrain.TRAP:
trap = traps.get( cell );
break;
case Terrain.DOOR:
Door.enter( cell );
default:
trap = false;
break;
}
if (trap) {
if (Dungeon.visible[cell]) {
Sample.INSTANCE.play( Assets.SND_TRAP );
}
set( cell, Terrain.INACTIVE_TRAP );
GameScene.updateMap( cell );
if (trap != null) {
trap.trigger();
}
Plant plant = plants.get( cell );
@@ -1021,12 +980,7 @@ public abstract class Level implements Bundlable {
case Terrain.EMPTY:
case Terrain.EMPTY_SP:
case Terrain.EMPTY_DECO:
case Terrain.SECRET_TOXIC_TRAP:
case Terrain.SECRET_FIRE_TRAP:
case Terrain.SECRET_PARALYTIC_TRAP:
case Terrain.SECRET_POISON_TRAP:
case Terrain.SECRET_ALARM_TRAP:
case Terrain.SECRET_LIGHTNING_TRAP:
case Terrain.SECRET_TRAP:
return "Floor";
case Terrain.GRASS:
return "Grass";
@@ -1067,22 +1021,6 @@ public abstract class Level implements Bundlable {
case Terrain.STATUE:
case Terrain.STATUE_SP:
return "Statue";
case Terrain.TOXIC_TRAP:
return "Toxic gas trap";
case Terrain.FIRE_TRAP:
return "Fire trap";
case Terrain.PARALYTIC_TRAP:
return "Paralytic gas trap";
case Terrain.POISON_TRAP:
return "Poison dart trap";
case Terrain.ALARM_TRAP:
return "Alarm trap";
case Terrain.LIGHTNING_TRAP:
return "Lightning trap";
case Terrain.GRIPPING_TRAP:
return "Gripping trap";
case Terrain.SUMMONING_TRAP:
return "Summoning trap";
case Terrain.INACTIVE_TRAP:
return "Triggered trap";
case Terrain.BOOKSHELF:
@@ -1118,15 +1056,6 @@ public abstract class Level implements Bundlable {
return "The wooden barricade is firmly set but has dried over the years. Might it burn?";
case Terrain.SIGN:
return "You can't read the text from here.";
case Terrain.TOXIC_TRAP:
case Terrain.FIRE_TRAP:
case Terrain.PARALYTIC_TRAP:
case Terrain.POISON_TRAP:
case Terrain.ALARM_TRAP:
case Terrain.LIGHTNING_TRAP:
case Terrain.GRIPPING_TRAP:
case Terrain.SUMMONING_TRAP:
return "Stepping onto a hidden pressure plate will activate the trap.";
case Terrain.INACTIVE_TRAP:
return "The trap has been triggered before and it's not dangerous anymore.";
case Terrain.STATUE:

View File

@@ -30,6 +30,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.PoisonTrap;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.noosa.Scene;
import com.watabou.utils.Bundle;
@@ -204,13 +205,14 @@ public class PrisonBossLevel extends RegularLevel {
int trapPos = Random.Int( LENGTH );
if (map[trapPos] == Terrain.EMPTY) {
map[trapPos] = Terrain.POISON_TRAP;
map[trapPos] = Terrain.TRAP;
setTrap( new PoisonTrap().reveal(), trapPos );
}
}
}
@Override
protected void decorate() {
protected void decorate() {
for (int i=WIDTH + 1; i < LENGTH - WIDTH - 1; i++) {
if (map[i] == Terrain.EMPTY) {

View File

@@ -32,6 +32,13 @@ import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.ShopPainter;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.AlarmTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FireTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrippingTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.LightningTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ParalyticTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.PoisonTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ToxicTrap;
import com.watabou.utils.Bundle;
import com.watabou.utils.Graph;
import com.watabou.utils.Random;
@@ -317,36 +324,37 @@ public abstract class RegularLevel extends Level {
int nTraps = nTraps();
float[] trapChances = trapChances();
for (int i=0; i < nTraps; i++) {
int trapPos = Random.Int( LENGTH );
if (map[trapPos] == Terrain.EMPTY) {
map[trapPos] = Terrain.SECRET_TRAP;
switch (Random.chances( trapChances )) {
case 0:
map[trapPos] = Terrain.SECRET_TOXIC_TRAP;
setTrap( new ToxicTrap().hide(), trapPos);
break;
case 1:
map[trapPos] = Terrain.SECRET_FIRE_TRAP;
setTrap( new FireTrap().hide(), trapPos);
break;
case 2:
map[trapPos] = Terrain.SECRET_PARALYTIC_TRAP;
setTrap( new ParalyticTrap().hide(), trapPos);
break;
case 3:
map[trapPos] = Terrain.SECRET_POISON_TRAP;
setTrap( new PoisonTrap().hide(), trapPos);
break;
case 4:
map[trapPos] = Terrain.SECRET_ALARM_TRAP;
setTrap( new AlarmTrap().hide(), trapPos);
break;
case 5:
map[trapPos] = Terrain.SECRET_LIGHTNING_TRAP;
setTrap( new LightningTrap().hide(), trapPos);
break;
case 6:
map[trapPos] = Terrain.SECRET_GRIPPING_TRAP;
setTrap( new GrippingTrap().hide(), trapPos);
break;
case 7:
map[trapPos] = Terrain.SECRET_SUMMONING_TRAP;
setTrap( new LightningTrap().hide(), trapPos);
break;
}
}
@@ -672,7 +680,8 @@ public abstract class RegularLevel extends Level {
for (Item item : itemsToSpawn) {
int cell = randomDropCell();
if (item instanceof Scroll) {
while (map[cell] == Terrain.FIRE_TRAP || map[cell] == Terrain.SECRET_FIRE_TRAP) {
while ((map[cell] == Terrain.TRAP || map[cell] == Terrain.SECRET_TRAP)
&& traps.get( cell ) instanceof FireTrap) {
cell = randomDropCell();
}
}

View File

@@ -17,6 +17,9 @@
*/
package com.shatteredpixel.shatteredpixeldungeon.levels;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.*;
import com.watabou.utils.SparseArray;
public class Terrain {
public static final int CHASM = 0;
@@ -35,41 +38,29 @@ public class Terrain {
public static final int BARRICADE = 13;
public static final int EMPTY_SP = 14;
public static final int HIGH_GRASS = 15;
public static final int EMPTY_DECO = 24;
public static final int LOCKED_EXIT = 25;
public static final int UNLOCKED_EXIT = 26;
public static final int SIGN = 29;
public static final int WELL = 34;
public static final int STATUE = 35;
public static final int STATUE_SP = 36;
public static final int BOOKSHELF = 41;
public static final int ALCHEMY = 42;
public static final int CHASM_FLOOR = 43;
public static final int CHASM_FLOOR_SP = 44;
public static final int CHASM_WALL = 45;
public static final int CHASM_WATER = 46;
public static final int SECRET_DOOR = 16;
public static final int TOXIC_TRAP = 17;
public static final int SECRET_TOXIC_TRAP = 18;
public static final int FIRE_TRAP = 19;
public static final int SECRET_FIRE_TRAP = 20;
public static final int PARALYTIC_TRAP = 21;
public static final int SECRET_PARALYTIC_TRAP = 22;
public static final int INACTIVE_TRAP = 23;
public static final int POISON_TRAP = 27;
public static final int SECRET_POISON_TRAP = 28;
public static final int ALARM_TRAP = 30;
public static final int SECRET_ALARM_TRAP = 31;
public static final int LIGHTNING_TRAP = 32;
public static final int SECRET_LIGHTNING_TRAP = 33;
public static final int GRIPPING_TRAP = 37;
public static final int SECRET_GRIPPING_TRAP = 38;
public static final int SUMMONING_TRAP = 39;
public static final int SECRET_SUMMONING_TRAP = 40;
public static final int WATER_TILES = 48;
public static final int WATER = 63;
public static final int SECRET_DOOR = 16;
public static final int SECRET_TRAP = 17;
public static final int TRAP = 18;
public static final int INACTIVE_TRAP = 19;
public static final int EMPTY_DECO = 20;
public static final int LOCKED_EXIT = 21;
public static final int UNLOCKED_EXIT = 22;
public static final int SIGN = 23;
public static final int WELL = 24;
public static final int STATUE = 25;
public static final int STATUE_SP = 26;
public static final int BOOKSHELF = 27;
public static final int ALCHEMY = 28;
public static final int CHASM_FLOOR = 29;
public static final int CHASM_FLOOR_SP = 30;
public static final int CHASM_WALL = 31;
public static final int CHASM_WATER = 32;
public static final int WATER_TILES = 48;
public static final int WATER = 63;
public static final int PASSABLE = 0x01;
public static final int LOS_BLOCKING = 0x02;
@@ -101,6 +92,12 @@ public class Terrain {
flags[BARRICADE] = FLAMABLE | SOLID | LOS_BLOCKING;
flags[EMPTY_SP] = flags[EMPTY] | UNSTITCHABLE;
flags[HIGH_GRASS] = PASSABLE | LOS_BLOCKING | FLAMABLE;
flags[SECRET_DOOR] = flags[WALL] | SECRET | UNSTITCHABLE;
flags[SECRET_TRAP] = flags[EMPTY] | SECRET;
flags[TRAP] = AVOID;
flags[INACTIVE_TRAP]= flags[EMPTY];
flags[EMPTY_DECO] = flags[EMPTY];
flags[LOCKED_EXIT] = SOLID;
flags[UNLOCKED_EXIT]= PASSABLE;
@@ -116,52 +113,89 @@ public class Terrain {
flags[CHASM_FLOOR_SP] = flags[CHASM];
flags[CHASM_WATER] = flags[CHASM];
flags[SECRET_DOOR] = flags[WALL] | SECRET | UNSTITCHABLE;
flags[TOXIC_TRAP] = AVOID;
flags[SECRET_TOXIC_TRAP] = flags[EMPTY] | SECRET;
flags[FIRE_TRAP] = AVOID;
flags[SECRET_FIRE_TRAP] = flags[EMPTY] | SECRET;
flags[PARALYTIC_TRAP] = AVOID;
flags[SECRET_PARALYTIC_TRAP] = flags[EMPTY] | SECRET;
flags[POISON_TRAP] = AVOID;
flags[SECRET_POISON_TRAP] = flags[EMPTY] | SECRET;
flags[ALARM_TRAP] = AVOID;
flags[SECRET_ALARM_TRAP] = flags[EMPTY] | SECRET;
flags[LIGHTNING_TRAP] = AVOID;
flags[SECRET_LIGHTNING_TRAP] = flags[EMPTY] | SECRET;
flags[GRIPPING_TRAP] = AVOID;
flags[SECRET_GRIPPING_TRAP] = flags[EMPTY] | SECRET;
flags[SUMMONING_TRAP] = AVOID;
flags[SECRET_SUMMONING_TRAP] = flags[EMPTY] | SECRET;
flags[INACTIVE_TRAP] = flags[EMPTY];
for (int i=WATER_TILES; i < WATER_TILES + 16; i++) {
flags[i] = flags[WATER];
}
};
//TODO: everything that touches this needs new trap logic
public static int discover( int terr ) {
switch (terr) {
case SECRET_DOOR:
return DOOR;
case SECRET_FIRE_TRAP:
return FIRE_TRAP;
case SECRET_PARALYTIC_TRAP:
return PARALYTIC_TRAP;
case SECRET_TOXIC_TRAP:
return TOXIC_TRAP;
case SECRET_POISON_TRAP:
return POISON_TRAP;
case SECRET_ALARM_TRAP:
return ALARM_TRAP;
case SECRET_LIGHTNING_TRAP:
return LIGHTNING_TRAP;
case SECRET_GRIPPING_TRAP:
return GRIPPING_TRAP;
case SECRET_SUMMONING_TRAP:
return SUMMONING_TRAP;
case SECRET_TRAP:
return TRAP;
default:
return terr;
}
}
//converts terrain values from pre versioncode 44 (0.3.0c) saves
//TODO: remove when no longer supporting saves from 0.3.0b and under
public static int[] convertTrapsFrom43( int[] map, SparseArray<Trap> traps){
for (int i = 0; i < map.length; i++){
int c = map[i];
//non-trap tiles getting their values shifted around
if (c >= 24 && c <= 26) {
c -= 4; //24-26 becomes 20-22
} else if (c == 29) {
c = 23; //29 becomes 23
} else if ( c >= 34 && c <= 36) {
c -= 10; //34-36 becomes 24-26
} else if ( c >= 41 && c <= 46) {
c -= 14; //41-46 becomes 27-32
}
//trap tiles, must be converted to general trap tiles and specific traps instantiated
else if (c >= 17 && c <= 40){
//this is going to be messy...
Trap trap = null;
switch(c){
case 17: trap = new ToxicTrap().reveal(); break;
case 18: trap = new ToxicTrap().hide(); break;
case 19: trap = new FireTrap().reveal(); break;
case 20: trap = new FireTrap().hide(); break;
case 21: trap = new ParalyticTrap().reveal(); break;
case 22: trap = new ParalyticTrap().hide(); break;
case 23:
c = INACTIVE_TRAP;
trap = null;
break;
case 27: trap = new PoisonTrap().reveal(); break;
case 28: trap = new PoisonTrap().hide(); break;
case 30: trap = new AlarmTrap().reveal(); break;
case 31: trap = new AlarmTrap().hide(); break;
case 32: trap = new LightningTrap().reveal(); break;
case 33: trap = new LightningTrap().hide(); break;
case 37: trap = new GrippingTrap().reveal(); break;
case 38: trap = new GrippingTrap().hide(); break;
case 39: trap = new SummoningTrap().reveal(); break;
case 40: trap = new SummoningTrap().hide(); break;
}
if (trap != null){
trap.set( i );
traps.put( trap.pos, trap );
if (trap.visible)
c = TRAP;
else
c = SECRET_TRAP;
}
}
map[i] = c;
}
return map;
}
}

View File

@@ -23,6 +23,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FireTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
import com.watabou.utils.Random;
public class BlacksmithPainter extends Painter {
@@ -30,8 +32,14 @@ public class BlacksmithPainter extends Painter {
public static void paint( Level level, Room room ) {
fill( level, room, Terrain.WALL );
fill( level, room, 1, Terrain.FIRE_TRAP );
fill( level, room, 1, Terrain.TRAP );
fill( level, room, 2, Terrain.EMPTY_SP );
for(int cell : room.getCells()) {
if (level.map[cell] == Terrain.TRAP){
level.setTrap(new FireTrap().reveal(), cell);
}
}
for (int i=0; i < 2; i++) {
int pos;

View File

@@ -25,6 +25,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FireTrap;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
@@ -93,22 +94,25 @@ public class StandardPainter extends Painter {
private static void paintBurned( Level level, Room room ) {
for (int i=room.top + 1; i < room.bottom; i++) {
for (int j=room.left + 1; j < room.right; j++) {
int cell = i * Level.WIDTH + j;
int t = Terrain.EMBERS;
switch (Random.Int( 5 )) {
case 0:
t = Terrain.EMPTY;
break;
case 1:
t = Terrain.FIRE_TRAP;
t = Terrain.TRAP;
level.setTrap(new FireTrap().reveal(), cell);
break;
case 2:
t = Terrain.SECRET_FIRE_TRAP;
t = Terrain.SECRET_TRAP;
level.setTrap(new FireTrap().hide(), cell);
break;
case 3:
t = Terrain.INACTIVE_TRAP;
break;
}
level.map[i * Level.WIDTH + j] = t;
level.map[cell] = t;
}
}
}

View File

@@ -18,6 +18,7 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.painters;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
@@ -25,18 +26,29 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLevitation
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ParalyticTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.SummoningTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ToxicTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
import com.watabou.utils.Random;
public class TrapsPainter extends Painter {
public static void paint( Level level, Room room ) {
Integer traps[] = {
Terrain.TOXIC_TRAP, Terrain.TOXIC_TRAP, Terrain.TOXIC_TRAP,
Terrain.PARALYTIC_TRAP, Terrain.PARALYTIC_TRAP,
!Dungeon.bossLevel( Dungeon.depth + 1 ) ? Terrain.CHASM : Terrain.SUMMONING_TRAP };
Class traps[] = new Class[]{
ToxicTrap.class, ToxicTrap.class, ToxicTrap.class,
ParalyticTrap.class, ParalyticTrap.class,
!Dungeon.bossLevel(Dungeon.depth + 1) ? null : SummoningTrap.class};
fill( level, room, Terrain.WALL );
fill( level, room, 1, Random.element( traps ) );
Class trap = Random.element(traps);
if (trap == null){
fill(level, room, 1, Terrain.CHASM);
} else {
fill(level, room, 1, Terrain.TRAP);
}
Room.Door door = room.entrance();
door.set( Room.Door.Type.REGULAR );
@@ -62,6 +74,16 @@ public class TrapsPainter extends Painter {
y = room.top + 1;
fill( level, room.left + 1, y, room.width() - 1, 1 , lastRow );
}
for(int cell : room.getCells()) {
if (level.map[cell] == Terrain.TRAP){
try {
level.setTrap(((Trap) trap.newInstance()).reveal(), cell);
} catch (Exception e) {
e.printStackTrace();
}
}
}
int pos = x + y * Level.WIDTH;
if (Random.Int( 3 ) == 0) {

View File

@@ -4,8 +4,10 @@ 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.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite;
import com.watabou.noosa.audio.Sample;
import com.watabou.noosa.tweeners.AlphaTweener;
import com.watabou.utils.Bundlable;
import com.watabou.utils.Bundle;
@@ -19,23 +21,27 @@ public abstract class Trap implements Bundlable {
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() {
//TODO: fade-in effect here?
public Trap reveal() {
visible = true;
if (sprite != null)
if (sprite != null) {
sprite.visible = true;
sprite.alpha( 0 );
sprite.parent.add( new AlphaTweener( sprite, 1, 0.6f));
}
return this;
}
public void hide() {
public Trap hide() {
visible = false;
if (sprite != null)
sprite.visible = false;
return this;
}
public void trigger() {
@@ -49,19 +55,23 @@ public abstract class Trap implements Bundlable {
public abstract void activate();
protected void disarm(){
//Dungeon.level.traps.delete( pos );
Level.set(pos, Terrain.INACTIVE_TRAP);
sprite.kill();
Dungeon.level.disarmTrap(pos);
if (sprite != null) sprite.kill();
}
private static final String POS = "pos";
private static final String VISIBLE = "visible";
@Override
public void restoreFromBundle( Bundle bundle ) {
pos = bundle.getInt( POS );
visible = bundle.getBoolean( VISIBLE );
}
@Override
public void storeInBundle( Bundle bundle ) {
bundle.put( POS, pos );
bundle.put( VISIBLE, visible );
}
public String desc() {

View File

@@ -30,6 +30,8 @@ import com.shatteredpixel.shatteredpixeldungeon.items.bags.WandHolster;
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfTeleportation;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.MagesStaff;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite;
import com.shatteredpixel.shatteredpixeldungeon.ui.LootIndicator;
import com.shatteredpixel.shatteredpixeldungeon.ui.ResumeIndicator;
import com.watabou.noosa.Camera;
@@ -107,6 +109,7 @@ public class GameScene extends PixelScene {
private Group terrain;
private Group ripples;
private Group plants;
private Group traps;
private Group heaps;
private Group mobs;
private Group emitters;
@@ -151,12 +154,20 @@ public class GameScene extends PixelScene {
tiles = new DungeonTilemap();
terrain.add( tiles );
Dungeon.level.addVisuals( this );
Dungeon.level.addVisuals(this);
traps = new Group();
add(traps);
int size = Dungeon.level.traps.size();
for (int i=0; i < size; i++) {
addTrapSprite( Dungeon.level.traps.valueAt( i ) );
}
plants = new Group();
add( plants );
int size = Dungeon.level.plants.size();
size = Dungeon.level.plants.size();
for (int i=0; i < size; i++) {
addPlantSprite( Dungeon.level.plants.valueAt( i ) );
}
@@ -453,6 +464,11 @@ public class GameScene extends PixelScene {
private void addPlantSprite( Plant plant ) {
(plant.sprite = (PlantSprite)plants.recycle( PlantSprite.class )).reset( plant );
}
private void addTrapSprite( Trap trap ) {
(trap.sprite = (TrapSprite)traps.recycle( TrapSprite.class )).reset( trap );
trap.sprite.visible = trap.visible;
}
private void addBlobSprite( final Blob gas ) {
if (gas.emitter == null) {
@@ -501,6 +517,12 @@ public class GameScene extends PixelScene {
scene.addPlantSprite( plant );
}
}
public static void add( Trap trap ) {
if (scene != null) {
scene.addTrapSprite( trap );
}
}
public static void add( Blob gas ) {
Actor.add( gas );

View File

@@ -18,6 +18,8 @@
package com.shatteredpixel.shatteredpixeldungeon.ui;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
import com.shatteredpixel.shatteredpixeldungeon.windows.WndInfoTrap;
import com.watabou.noosa.Game;
import com.watabou.noosa.Gizmo;
import com.watabou.noosa.Image;
@@ -200,30 +202,29 @@ public class Toolbar extends Component {
return;
}
if (!Dungeon.visible[cell]) {
GameScene.show( new WndInfoCell( cell ) );
return;
}
if (cell == Dungeon.hero.pos) {
GameScene.show( new WndHero() );
return;
}
Mob mob = (Mob)Actor.findChar( cell );
if (mob != null) {
GameScene.show( new WndInfoMob( mob ) );
return;
}
Heap heap = Dungeon.level.heaps.get( cell );
if (heap != null) {
if (heap.type == Heap.Type.FOR_SALE && heap.size() == 1 && heap.peek().price() > 0) {
GameScene.show( new WndTradeItem( heap, false ) );
} else {
GameScene.show( new WndInfoItem( heap ) );
if (Dungeon.visible[cell]) {
Mob mob = (Mob) Actor.findChar(cell);
if (mob != null) {
GameScene.show(new WndInfoMob(mob));
return;
}
return;
Heap heap = Dungeon.level.heaps.get(cell);
if (heap != null) {
if (heap.type == Heap.Type.FOR_SALE && heap.size() == 1 && heap.peek().price() > 0) {
GameScene.show(new WndTradeItem(heap, false));
} else {
GameScene.show(new WndInfoItem(heap));
}
return;
}
}
Plant plant = Dungeon.level.plants.get( cell );
@@ -231,6 +232,12 @@ public class Toolbar extends Component {
GameScene.show( new WndInfoPlant( plant ) );
return;
}
Trap trap = Dungeon.level.traps.get( cell );
if (trap != null && trap.visible) {
GameScene.show( new WndInfoTrap( trap ));
return;
}
GameScene.show( new WndInfoCell( cell ) );
}

View File

@@ -1,5 +1,6 @@
package com.shatteredpixel.shatteredpixeldungeon.windows;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.Trap;
import com.shatteredpixel.shatteredpixeldungeon.sprites.TrapSprite;
@@ -7,7 +8,7 @@ public class WndInfoTrap extends WndTitledMessage {
public WndInfoTrap(Trap trap) {
super(new TrapSprite( trap.image ), trap.name, trap.desc());
super(new TrapSprite( trap.image + (((Dungeon.depth-1) / 5) * 8) ), trap.name, trap.desc());
}