v0.7.3: various trap adjustments in prep for new reclaim trap:

- disintegration trap no longer does % health damage
- flock trap duration no longer scales with depth
- bosses now resist grim traps, Yog is immune
- pitfall traps do not work on boss floors
- reduced poison dart trap scaling with depth
- rockfall traps are a static 5x5 AOE if they aren't on the ground
- summoning traps now work on boss floors
  - note that the curse of multiplicity also now works on boss floors
- bosses resist weakening traps
This commit is contained in:
Evan Debenham 2019-05-04 18:40:02 -04:00
parent a9add83d2c
commit 21f52e1928
19 changed files with 57 additions and 70 deletions

View File

@ -73,6 +73,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.darts.Shoc
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog; import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
@ -595,7 +596,7 @@ public abstract class Char extends Actor {
} }
public enum Property{ public enum Property{
BOSS ( new HashSet<Class>( Arrays.asList(Grim.class, ScrollOfRetribution.class, ScrollOfPsionicBlast.class)), BOSS ( new HashSet<Class>( Arrays.asList(Grim.class, GrimTrap.class, ScrollOfRetribution.class, ScrollOfPsionicBlast.class)),
new HashSet<Class>( Arrays.asList(Corruption.class, StoneOfAggression.Aggression.class) )), new HashSet<Class>( Arrays.asList(Corruption.class, StoneOfAggression.Aggression.class) )),
MINIBOSS ( new HashSet<Class>(), MINIBOSS ( new HashSet<Class>(),
new HashSet<Class>( Arrays.asList(Corruption.class) )), new HashSet<Class>( Arrays.asList(Corruption.class) )),

View File

@ -55,7 +55,7 @@ public class Bestiary {
return new ArrayList<>(Arrays.asList(Rat.class, Rat.class, return new ArrayList<>(Arrays.asList(Rat.class, Rat.class,
Gnoll.class, Gnoll.class, Gnoll.class, Gnoll.class, Gnoll.class, Gnoll.class, Gnoll.class, Gnoll.class,
Crab.class, Swarm.class)); Crab.class, Swarm.class));
case 4: case 4: case 5:
//1x rat, 2x gnoll, 3x crab, 1x swarm //1x rat, 2x gnoll, 3x crab, 1x swarm
return new ArrayList<>(Arrays.asList(Rat.class, return new ArrayList<>(Arrays.asList(Rat.class,
Gnoll.class, Gnoll.class, Gnoll.class, Gnoll.class,
@ -80,7 +80,7 @@ public class Bestiary {
Thief.class, Thief.class,
Shaman.class, Shaman.class, Shaman.class, Shaman.class,
Guard.class, Guard.class)); Guard.class, Guard.class));
case 9: case 9: case 10:
//3x skeleton, 1x thief, 2x shaman, 3x guard //3x skeleton, 1x thief, 2x shaman, 3x guard
return new ArrayList<>(Arrays.asList(Skeleton.class, Skeleton.class, Skeleton.class, return new ArrayList<>(Arrays.asList(Skeleton.class, Skeleton.class, Skeleton.class,
Thief.class, Thief.class,
@ -106,7 +106,7 @@ public class Bestiary {
Brute.class, Brute.class, Brute.class, Brute.class, Brute.class, Brute.class,
Shaman.class, Shaman.class,
Spinner.class)); Spinner.class));
case 14: case 14: case 15:
//1x bat, 3x brute, 1x shaman, 4x spinner //1x bat, 3x brute, 1x shaman, 4x spinner
return new ArrayList<>(Arrays.asList( return new ArrayList<>(Arrays.asList(
Bat.class, Bat.class,
@ -134,7 +134,7 @@ public class Bestiary {
Warlock.class, Warlock.class,
Monk.class, Monk.class, Monk.class, Monk.class,
Golem.class)); Golem.class));
case 19: case 19: case 20:
//1x elemental, 1x warlock, 2x monk, 3x golem //1x elemental, 1x warlock, 2x monk, 3x golem
return new ArrayList<>(Arrays.asList( return new ArrayList<>(Arrays.asList(
Elemental.class, Elemental.class,
@ -143,7 +143,7 @@ public class Bestiary {
Golem.class, Golem.class, Golem.class)); Golem.class, Golem.class, Golem.class));
// Halls // Halls
case 22: case 21: case 22:
//3x succubus, 3x evil eye //3x succubus, 3x evil eye
return new ArrayList<>(Arrays.asList( return new ArrayList<>(Arrays.asList(
Succubus.class, Succubus.class, Succubus.class, Succubus.class, Succubus.class, Succubus.class,
@ -154,7 +154,7 @@ public class Bestiary {
Succubus.class, Succubus.class, Succubus.class, Succubus.class,
Eye.class, Eye.class, Eye.class, Eye.class, Eye.class, Eye.class, Eye.class, Eye.class,
Scorpio.class, Scorpio.class)); Scorpio.class, Scorpio.class));
case 24: case 24: case 25: case 26:
//1x succubus, 2x evil eye, 3x scorpio //1x succubus, 2x evil eye, 3x scorpio
return new ArrayList<>(Arrays.asList( return new ArrayList<>(Arrays.asList(
Succubus.class, Succubus.class,

View File

@ -44,6 +44,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetribution; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRetribution;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.exotic.ScrollOfPsionicBlast;
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim; import com.shatteredpixel.shatteredpixeldungeon.items.weapon.enchantments.Grim;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GrimTrap;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica; import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
@ -180,8 +181,8 @@ public class Yog extends Mob {
} }
{ {
immunities.add( Grim.class ); immunities.add( Grim.class );
immunities.add( GrimTrap.class );
immunities.add( Terror.class ); immunities.add( Terror.class );
immunities.add( Amok.class ); immunities.add( Amok.class );
immunities.add( Charm.class ); immunities.add( Charm.class );

View File

@ -181,11 +181,6 @@ public class CavesBossLevel extends Level {
return true; return true;
} }
@Override
public Mob createMob() {
return null;
}
@Override @Override
protected void createMobs() { protected void createMobs() {
} }

View File

@ -150,11 +150,6 @@ public class CityBossLevel extends Level {
} }
} }
@Override
public Mob createMob() {
return null;
}
@Override @Override
protected void createMobs() { protected void createMobs() {
} }

View File

@ -142,11 +142,6 @@ public class HallsBossLevel extends Level {
return true; return true;
} }
@Override
public Mob createMob() {
return null;
}
@Override @Override
protected void createMobs() { protected void createMobs() {
} }

View File

@ -41,6 +41,7 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass; import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlowParticle; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlowParticle;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.WindParticle; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.WindParticle;
@ -375,6 +376,12 @@ public abstract class Level implements Bundlable {
if (feeling == Feeling.DARK) if (feeling == Feeling.DARK)
viewDistance = Math.round(viewDistance/2f); viewDistance = Math.round(viewDistance/2f);
if (bundle.contains( "mobs_to_spawn" )) {
for (Class<? extends Mob> mob : bundle.getClassArray("mobs_to_spawn")) {
if (mob != null) mobsToSpawn.add(mob);
}
}
buildFlagMaps(); buildFlagMaps();
cleanWalls(); cleanWalls();
} }
@ -398,6 +405,7 @@ public abstract class Level implements Bundlable {
bundle.put( MOBS, mobs ); bundle.put( MOBS, mobs );
bundle.put( BLOBS, blobs.values() ); bundle.put( BLOBS, blobs.values() );
bundle.put( FEELING, feeling ); bundle.put( FEELING, feeling );
bundle.put( "mobs_to_spawn", mobsToSpawn.toArray(new Class[0]));
} }
public int tunnelTile() { public int tunnelTile() {
@ -426,7 +434,19 @@ public abstract class Level implements Bundlable {
abstract protected boolean build(); abstract protected boolean build();
abstract public Mob createMob(); private ArrayList<Class<?extends Mob>> mobsToSpawn = new ArrayList<>();
public Mob createMob() {
if (mobsToSpawn == null || mobsToSpawn.isEmpty())
mobsToSpawn = Bestiary.getMobRotation(Dungeon.depth);
try {
return mobsToSpawn.remove(0).newInstance();
} catch (Exception e) {
ShatteredPixelDungeon.reportException(e);
return null;
}
}
abstract protected void createMobs(); abstract protected void createMobs();

View File

@ -141,11 +141,6 @@ public class PrisonBossLevel extends Level {
return true; return true;
} }
@Override
public Mob createMob() {
return null;
}
@Override @Override
protected void createMobs() { protected void createMobs() {
tengu = new Tengu(); //We want to keep track of tengu independently of other mobs, he's not always in the level. tengu = new Tengu(); //We want to keep track of tengu independently of other mobs, he's not always in the level.

View File

@ -180,21 +180,6 @@ public abstract class RegularLevel extends Level {
} }
} }
private ArrayList<Class<?extends Mob>> mobsToSpawn = new ArrayList<>();
@Override
public Mob createMob() {
if (mobsToSpawn == null || mobsToSpawn.isEmpty())
mobsToSpawn = Bestiary.getMobRotation(Dungeon.depth);
try {
return mobsToSpawn.remove(0).newInstance();
} catch (Exception e) {
ShatteredPixelDungeon.reportException(e);
return null;
}
}
@Override @Override
protected void createMobs() { protected void createMobs() {
//on floor 1, 10 rats are created so the player can get level 2. //on floor 1, 10 rats are created so the player can get level 2.
@ -479,7 +464,6 @@ public abstract class RegularLevel extends Level {
public void storeInBundle( Bundle bundle ) { public void storeInBundle( Bundle bundle ) {
super.storeInBundle( bundle ); super.storeInBundle( bundle );
bundle.put( "rooms", rooms ); bundle.put( "rooms", rooms );
bundle.put( "mobs_to_spawn", mobsToSpawn.toArray(new Class[0]));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -496,12 +480,6 @@ public abstract class RegularLevel extends Level {
roomExit = r; roomExit = r;
} }
} }
if (bundle.contains( "mobs_to_spawn" )) {
for (Class<? extends Mob> mob : bundle.getClassArray("mobs_to_spawn")) {
if (mob != null) mobsToSpawn.add(mob);
}
}
} }
} }

View File

@ -110,11 +110,6 @@ public class SewerBossLevel extends SewerLevel {
mobs.add( boss ); mobs.add( boss );
} }
@Override
public Mob createMob() {
return null;
}
public Actor respawner() { public Actor respawner() {
return null; return null;
} }

View File

@ -125,13 +125,13 @@ public class CursingTrap extends Trap {
if (item instanceof Weapon){ if (item instanceof Weapon){
Weapon w = (Weapon) item; Weapon w = (Weapon) item;
if (w.enchantment == null){ if (w.enchantment == null){
w.enchantment = Weapon.Enchantment.randomCurse(); w.enchant(Weapon.Enchantment.randomCurse());
} }
} }
if (item instanceof Armor){ if (item instanceof Armor){
Armor a = (Armor) item; Armor a = (Armor) item;
if (a.glyph == null){ if (a.glyph == null){
a.glyph = Armor.Glyph.randomCurse(); a.inscribe(Armor.Glyph.randomCurse());
} }
} }
} }

View File

@ -74,7 +74,7 @@ public class DisintegrationTrap extends Trap {
Sample.INSTANCE.play(Assets.SND_RAY); Sample.INSTANCE.play(Assets.SND_RAY);
ShatteredPixelDungeon.scene().add(new Beam.DeathRay(DungeonTilemap.tileCenterToWorld(pos), target.sprite.center())); ShatteredPixelDungeon.scene().add(new Beam.DeathRay(DungeonTilemap.tileCenterToWorld(pos), target.sprite.center()));
} }
target.damage( Math.max( target.HT/5, Random.Int(target.HP / 2, 2 * target.HP / 3) ), this ); target.damage( Random.NormalIntRange(30, 50) + Dungeon.depth, this );
if (target == Dungeon.hero){ if (target == Dungeon.hero){
Hero hero = (Hero)target; Hero hero = (Hero)target;
if (!hero.isAlive()){ if (!hero.isAlive()){

View File

@ -57,7 +57,7 @@ public class FlockTrap extends Trap {
&& Actor.findChar(i) == null && Actor.findChar(i) == null
&& !(Dungeon.level.pit[i])) { && !(Dungeon.level.pit[i])) {
Sheep sheep = new Sheep(); Sheep sheep = new Sheep();
sheep.lifespan = Random.NormalIntRange(3 + Dungeon.depth/4, 6 + Dungeon.depth/2 ); sheep.lifespan = Random.NormalIntRange( 4, 8 );
sheep.pos = i; sheep.pos = i;
GameScene.add(sheep); GameScene.add(sheep);
CellEmitter.get(i).burst(Speck.factory(Speck.WOOL), 4); CellEmitter.get(i).burst(Speck.factory(Speck.WOOL), 4);

View File

@ -28,7 +28,9 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm; import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
public class PitfallTrap extends Trap { public class PitfallTrap extends Trap {
@ -39,6 +41,12 @@ public class PitfallTrap extends Trap {
@Override @Override
public void activate() { public void activate() {
if( Dungeon.bossLevel() || Dungeon.depth > 25){
GLog.w(Messages.get(this, "no_pit"));
return;
}
Heap heap = Dungeon.level.heaps.get( pos ); Heap heap = Dungeon.level.heaps.get( pos );
if (heap != null){ if (heap != null){

View File

@ -86,7 +86,7 @@ public class PoisonDartTrap extends Trap {
Dungeon.fail( trap.getClass() ); Dungeon.fail( trap.getClass() );
} }
Buff.affect( finalTarget, Poison.class ) Buff.affect( finalTarget, Poison.class )
.set( 4 + Dungeon.depth ); .set( 8 + Math.round(2*Dungeon.depth / 3f) );
Sample.INSTANCE.play(Assets.SND_HIT, 1, 1, Random.Float(0.8f, 1.25f)); Sample.INSTANCE.play(Assets.SND_HIT, 1, 1, Random.Float(0.8f, 1.25f));
finalTarget.sprite.bloodBurstA(finalTarget.sprite.center(), dmg); finalTarget.sprite.bloodBurstA(finalTarget.sprite.center(), dmg);
finalTarget.sprite.flash(); finalTarget.sprite.flash();

View File

@ -60,7 +60,10 @@ public class RockfallTrap extends Trap {
ArrayList<Integer> rockCells = new ArrayList<>(); ArrayList<Integer> rockCells = new ArrayList<>();
if (Dungeon.level instanceof RegularLevel){ //determines if the trap is actually in the world, or if it is being spawned for its effect
boolean onGround = Dungeon.level.traps.get(pos) == this;
if (onGround && Dungeon.level instanceof RegularLevel){
Room r = ((RegularLevel) Dungeon.level).room(pos); Room r = ((RegularLevel) Dungeon.level).room(pos);
int cell; int cell;
for (Point p : r.getPoints()){ for (Point p : r.getPoints()){

View File

@ -43,10 +43,6 @@ public class SummoningTrap extends Trap {
@Override @Override
public void activate() { public void activate() {
if (Dungeon.bossLevel()) {
return;
}
int nMobs = 1; int nMobs = 1;
if (Random.Int( 2 ) == 0) { if (Random.Int( 2 ) == 0) {
nMobs++; nMobs++;

View File

@ -43,7 +43,11 @@ public class WeakeningTrap extends Trap{
} }
Char ch = Actor.findChar( pos ); Char ch = Actor.findChar( pos );
if (ch != null && !ch.flying){ if (ch != null){
if (ch.properties().contains(Char.Property.BOSS)
|| ch.properties().contains(Char.Property.MINIBOSS)){
Buff.prolong( ch, Weakness.class, Weakness.DURATION/2f );
}
Buff.prolong( ch, Weakness.class, Weakness.DURATION*2f ); Buff.prolong( ch, Weakness.class, Weakness.DURATION*2f );
} }
} }

View File

@ -82,14 +82,15 @@ levels.traps.oozetrap.name=ooze trap
levels.traps.oozetrap.desc=This trap will splash out caustic ooze when activated, which will burn until it is washed away. levels.traps.oozetrap.desc=This trap will splash out caustic ooze when activated, which will burn until it is washed away.
levels.traps.pitfalltrap.name=pitfall trap levels.traps.pitfalltrap.name=pitfall trap
levels.traps.pitfalltrap.desc=This pressure plate rests atop a fairly weak floor, and will likely collapse into a pit if it is pressed. levels.traps.pitfalltrap.no_pit=the ground is too solid for a pitfall trap to work here.
levels.traps.pitfalltrap.desc=This trap will cause anything that triggers it to slip right through the ground and fall! It won't work in areas with especially solid floors though.
levels.traps.poisondarttrap.name=poison dart trap levels.traps.poisondarttrap.name=poison dart trap
levels.traps.poisondarttrap.desc=A small dart-blower must be hidden nearby, activating this trap will cause it to shoot a poisoned dart at the nearest target.\n\nThankfully the trigger mechanism isn't hidden. levels.traps.poisondarttrap.desc=A small dart-blower must be hidden nearby, activating this trap will cause it to shoot a poisoned dart at the nearest target.\n\nThankfully the trigger mechanism isn't hidden.
levels.traps.rockfalltrap.name=rockfall trap levels.traps.rockfalltrap.name=rockfall trap
levels.traps.rockfalltrap.ondeath=You were crushed by the rockfall trap... levels.traps.rockfalltrap.ondeath=You were crushed by the rockfall trap...
levels.traps.rockfalltrap.desc=This trap is connected to a series of loose rocks above, triggering it will cause them to come crashing down over the entire room!\n\nThankfully the trigger mechanism isn't hidden. levels.traps.rockfalltrap.desc=This trap is connected to a series of loose rocks above, triggering it will cause them to come crashing down over the entire room! If the trap isn't in a specific room, rocks will fall in an area around the trap instead.\n\nThankfully the trigger mechanism isn't hidden.
levels.traps.shockingtrap.name=shocking trap levels.traps.shockingtrap.name=shocking trap
levels.traps.shockingtrap.desc=A mechanism with a large amount of energy stored into it. Triggering this trap will discharge that energy into a field around it. levels.traps.shockingtrap.desc=A mechanism with a large amount of energy stored into it. Triggering this trap will discharge that energy into a field around it.
@ -115,7 +116,7 @@ levels.traps.warpingtrap.name=warping trap
levels.traps.warpingtrap.desc=Whatever triggers this trap will be warped to some other location on this floor. levels.traps.warpingtrap.desc=Whatever triggers this trap will be warped to some other location on this floor.
levels.traps.weakeningtrap.name=weakening trap levels.traps.weakeningtrap.name=weakening trap
levels.traps.weakeningtrap.desc=Dark magic in this trap sucks the energy out of anything that comes into contact with it. levels.traps.weakeningtrap.desc=Dark magic in this trap sucks the energy out of anything that comes into contact with it. Powerful enemies may resist the effect, however.
levels.traps.worndarttrap.name=worn dart trap levels.traps.worndarttrap.name=worn dart trap
levels.traps.worndarttrap.desc=A small dart-blower must be hidden nearby, activating this trap will cause it to shoot at the nearest target.\n\nDue to its age it's not very harmful though, it isn't even hidden... levels.traps.worndarttrap.desc=A small dart-blower must be hidden nearby, activating this trap will cause it to shoot at the nearest target.\n\nDue to its age it's not very harmful though, it isn't even hidden...