v1.2.0: improved logic for magical fire and toxic gas rooms

This commit is contained in:
Evan Debenham 2022-03-12 23:53:00 -05:00
parent 542eae1bef
commit f58edf216e
4 changed files with 54 additions and 35 deletions

View File

@ -300,7 +300,7 @@ public abstract class RegularLevel extends Level {
continue; continue;
} }
ArrayList<Point> points = room.charWanderablePoints(this); ArrayList<Point> points = room.charPlaceablePoints(this);
if (!points.isEmpty()){ if (!points.isEmpty()){
cell = pointToCell(Random.element(points)); cell = pointToCell(Random.element(points));
if (passable[cell] && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])) { if (passable[cell] && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])) {

View File

@ -329,7 +329,7 @@ public abstract class Room extends Rect implements Graph.Node, Bundlable {
return points; return points;
} }
//whether or not a character (usually spawned) can be placed here //whether or not a character can be placed here (usually via spawn, tele, or wander)
public boolean canPlaceCharacter(Point p, Level l){ public boolean canPlaceCharacter(Point p, Level l){
return inside(p); return inside(p);
} }
@ -345,22 +345,6 @@ public abstract class Room extends Rect implements Graph.Node, Bundlable {
return points; return points;
} }
//whether or not a character can wander here
public boolean canCharacterWander(Point p, Level l) {
return inside(p);
}
public final ArrayList<Point> charWanderablePoints(Level l){
ArrayList<Point> points = new ArrayList<>();
for (int i = left; i <= right; i++) {
for (int j = top; j <= bottom; j++) {
Point p = new Point(i, j);
if (canCharacterWander(p, l)) points.add(p);
}
}
return points;
}
// **** Graph.Node interface **** // **** Graph.Node interface ****

View File

@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blizzard; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blizzard;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
@ -56,8 +57,6 @@ public class MagicalFireRoom extends SpecialRoom {
Door door = entrance(); Door door = entrance();
door.set( Door.Type.REGULAR ); door.set( Door.Type.REGULAR );
int x = -1;
int y = -1;
Point firePos = center(); Point firePos = center();
Room behindFire = new EmptyRoom(); Room behindFire = new EmptyRoom();
@ -114,6 +113,25 @@ public class MagicalFireRoom extends SpecialRoom {
return false; return false;
} }
@Override
public boolean canPlaceCharacter(Point p, Level l) {
Blob fire = l.blobs.get(EternalFire.class);
//disallow placing on special tiles or next to fire if fire is present.
//note that this is slightly brittle, assumes the fire is either all there or totally gone
if (fire != null && fire.volume > 0){
int cell = l.pointToCell(p);
if (l.map[cell] == Terrain.EMPTY_SP) return false;
if (fire.cur[cell] > 0) return false;
for (int i : PathFinder.NEIGHBOURS4){
if (fire.cur[cell+i] > 0) return false;
}
}
return super.canPlaceCharacter(p, l);
}
public static class EternalFire extends Fire { public static class EternalFire extends Fire {
@Override @Override
protected void evolve() { protected void evolve() {
@ -123,6 +141,10 @@ public class MagicalFireRoom extends SpecialRoom {
Freezing freeze = (Freezing)Dungeon.level.blobs.get( Freezing.class ); Freezing freeze = (Freezing)Dungeon.level.blobs.get( Freezing.class );
Blizzard bliz = (Blizzard)Dungeon.level.blobs.get( Blizzard.class ); Blizzard bliz = (Blizzard)Dungeon.level.blobs.get( Blizzard.class );
//if any part of the fire is cleared, cleanse the whole thing
//Note that this is a bit brittle atm, it assumes only one group of eternal fire per floor
boolean clearAll = false;
Level l = Dungeon.level; Level l = Dungeon.level;
for (int i = area.left; i < area.right; i++){ for (int i = area.left; i < area.right; i++){
for (int j = area.top; j < area.bottom; j++){ for (int j = area.top; j < area.bottom; j++){
@ -136,23 +158,25 @@ public class MagicalFireRoom extends SpecialRoom {
//potion of purity can cleanse it though //potion of purity can cleanse it though
if (l.water[cell]){ if (l.water[cell]){
cur[cell] = 0; cur[cell] = 0;
clearAll = true;
} }
if (freeze != null && freeze.volume > 0 && freeze.cur[cell] > 0){ if (freeze != null && freeze.volume > 0 && freeze.cur[cell] > 0){
freeze.clear(cell); freeze.clear(cell);
cur[cell] = 0; cur[cell] = 0;
clearAll = true;
} }
if (bliz != null && bliz.volume > 0 && bliz.cur[cell] > 0){ if (bliz != null && bliz.volume > 0 && bliz.cur[cell] > 0){
bliz.clear(cell); bliz.clear(cell);
cur[cell] = 0; cur[cell] = 0;
clearAll = true;
} }
//if the hero is adjacent, set them on fire briefly //if a char is adjacent, set them on fire briefly
//TODO all chars, but prevent random wandering into the fire?
if (cur[cell] > 0){ if (cur[cell] > 0){
for (int k : PathFinder.NEIGHBOURS4){ for (int k : PathFinder.NEIGHBOURS4){
if (Actor.findChar(cell+k) == Dungeon.hero Char ch = Actor.findChar(cell+k);
&& !Dungeon.hero.isImmune(getClass())){ if (ch != null && !ch.isImmune(getClass())){
Buff.affect(Dungeon.hero, Burning.class).reignite(Dungeon.hero, 4f); Buff.affect(ch, Burning.class).reignite(ch, 4f);
} }
} }
} }
@ -160,6 +184,12 @@ public class MagicalFireRoom extends SpecialRoom {
l.passable[cell] = cur[cell] == 0 && (Terrain.flags[l.map[cell]] & Terrain.PASSABLE) != 0; l.passable[cell] = cur[cell] == 0 && (Terrain.flags[l.map[cell]] & Terrain.PASSABLE) != 0;
} }
} }
if (clearAll){
fullyClear();
return;
}
super.evolve(); super.evolve();
} }
@ -171,10 +201,7 @@ public class MagicalFireRoom extends SpecialRoom {
@Override @Override
public void clear(int cell) { public void clear(int cell) {
super.clear(cell); fullyClear();
if (cur == null) return;
Level l = Dungeon.level;
l.passable[cell] = cur[cell] == 0 && (Terrain.flags[l.map[cell]] & Terrain.PASSABLE) != 0;
} }
@Override @Override

View File

@ -47,7 +47,8 @@ public class ToxicGasRoom extends SpecialRoom {
for (Point p : getPoints()){ for (Point p : getPoints()){
int cell = level.pointToCell(p); int cell = level.pointToCell(p);
if (level.map[cell] == Terrain.EMPTY) { if (level.map[cell] == Terrain.EMPTY) {
Blob.seed(cell, 3, ToxicGasSeed.class, level); //as if gas has been spreading in the room for a while
Blob.seed(cell, 30, ToxicGas.class, level);
} }
} }
@ -56,9 +57,10 @@ public class ToxicGasRoom extends SpecialRoom {
for (int i = 0; i < traps; i++){ for (int i = 0; i < traps; i++){
int cell; int cell;
do { do {
cell = level.pointToCell(random(1)); cell = level.pointToCell(random(2));
} while (level.map[cell] == Terrain.INACTIVE_TRAP); } while (level.map[cell] == Terrain.INACTIVE_TRAP);
level.setTrap(new ToxicVent().reveal(), cell); level.setTrap(new ToxicVent().reveal(), cell);
Blob.seed(cell, 12, ToxicGasSeed.class, level);
Painter.set(level, cell, Terrain.INACTIVE_TRAP); Painter.set(level, cell, Terrain.INACTIVE_TRAP);
} }
@ -72,8 +74,9 @@ public class ToxicGasRoom extends SpecialRoom {
} }
@Override @Override
public boolean canCharacterWander(Point p, Level l) { public boolean canPlaceCharacter(Point p, Level l) {
return false; Blob gas = l.blobs.get(ToxicGas.class);
return gas == null || gas.volume == 0 || gas.cur[l.pointToCell(p)] == 0;
} }
public static class ToxicGasSeed extends Blob { public static class ToxicGasSeed extends Blob {
@ -86,13 +89,18 @@ public class ToxicGasRoom extends SpecialRoom {
for (int j = area.left-1; j <= area.right; j++) { for (int j = area.left-1; j <= area.right; j++) {
cell = j + i* Dungeon.level.width(); cell = j + i* Dungeon.level.width();
if (Dungeon.level.insideMap(cell)) { if (Dungeon.level.insideMap(cell)) {
if (Dungeon.level.map[cell] != Terrain.INACTIVE_TRAP){
off[cell] = 0;
continue;
}
off[cell] = cur[cell]; off[cell] = cur[cell];
volume += off[cell]; volume += off[cell];
if (gas == null || gas.volume == 0){ if (gas == null || gas.volume == 0){
GameScene.add(Blob.seed(cell, off[cell], ToxicGas.class)); GameScene.add(Blob.seed(cell, off[cell], ToxicGas.class));
} else if (gas.cur[cell] < off[cell]){ } else if (gas.cur[cell] <= 9*off[cell]){
GameScene.add(Blob.seed(cell, off[cell] - gas.cur[cell], ToxicGas.class)); GameScene.add(Blob.seed(cell, off[cell], ToxicGas.class));
} }
} }
} }