From e8aff9652ffb6e813f16e2b4ced14a2992419305 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sat, 20 Aug 2022 23:30:45 -0400 Subject: [PATCH] v1.4.0: fixed rare freezes and crashes with respawn and fall cells --- .../levels/CavesBossLevel.java | 24 ++++++++++-------- .../levels/CityBossLevel.java | 22 ++++++++++------ .../levels/HallsBossLevel.java | 25 +++++++++++++------ .../levels/LastLevel.java | 23 +++++++++++------ .../levels/LastShopLevel.java | 25 +++++++++++++------ .../shatteredpixeldungeon/levels/Level.java | 8 ++++++ .../levels/PrisonBossLevel.java | 23 +++++++++++------ .../levels/RegularLevel.java | 21 ++++++++++------ .../levels/SewerBossLevel.java | 24 ++++++++++++------ .../levels/rooms/special/SpecialRoom.java | 2 ++ 10 files changed, 134 insertions(+), 63 deletions(-) diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java index efb783eb3..810e98a00 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CavesBossLevel.java @@ -219,17 +219,21 @@ public class CavesBossLevel extends Level { @Override public int randomRespawnCell( Char ch ) { - //this check is mainly here for DM-300, to prevent an infinite loop - if (Char.hasProp(ch, Char.Property.LARGE) && map[entrance()] != Terrain.ENTRANCE){ - return -1; + ArrayList candidates = new ArrayList<>(); + for (int i : PathFinder.NEIGHBOURS8){ + int cell = entrance() + i; + if (passable[cell] + && Actor.findChar(cell) != null + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])){ + candidates.add(cell); + } + } + + if (candidates.isEmpty()){ + return -1; + } else { + return Random.element(candidates); } - int cell; - do { - cell = entrance() + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] - || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) - || Actor.findChar(cell) != null); - return cell; } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java index 566e6743c..336f2b182 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/CityBossLevel.java @@ -275,13 +275,21 @@ public class CityBossLevel extends Level { @Override public int randomRespawnCell( Char ch ) { - int cell; - do { - cell = entrance() + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] - || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) - || Actor.findChar(cell) != null); - return cell; + ArrayList candidates = new ArrayList<>(); + for (int i : PathFinder.NEIGHBOURS8){ + int cell = entrance() + i; + if (passable[cell] + && Actor.findChar(cell) != null + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])){ + candidates.add(cell); + } + } + + if (candidates.isEmpty()){ + return -1; + } else { + return Random.element(candidates); + } } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java index 293cbaae6..29302052a 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/HallsBossLevel.java @@ -48,6 +48,8 @@ import com.watabou.utils.Callback; import com.watabou.utils.PathFinder; import com.watabou.utils.Random; +import java.util.ArrayList; + public class HallsBossLevel extends Level { { @@ -198,14 +200,21 @@ public class HallsBossLevel extends Level { @Override public int randomRespawnCell( Char ch ) { - int pos = entrance(); - int cell; - do { - cell = pos + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] - || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) - || Actor.findChar(cell) != null); - return cell; + ArrayList candidates = new ArrayList<>(); + for (int i : PathFinder.NEIGHBOURS8){ + int cell = entrance() + i; + if (passable[cell] + && Actor.findChar(cell) != null + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])){ + candidates.add(cell); + } + } + + if (candidates.isEmpty()){ + return -1; + } else { + return Random.element(candidates); + } } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java index 27f081e17..372b1445d 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastLevel.java @@ -40,6 +40,7 @@ import com.watabou.utils.Bundle; import com.watabou.utils.PathFinder; import com.watabou.utils.Random; +import java.util.ArrayList; import java.util.Arrays; public class LastLevel extends Level { @@ -166,13 +167,21 @@ public class LastLevel extends Level { @Override public int randomRespawnCell( Char ch ) { - int cell; - do { - cell = entrance() + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] - || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) - || Actor.findChar(cell) != null); - return cell; + ArrayList candidates = new ArrayList<>(); + for (int i : PathFinder.NEIGHBOURS8){ + int cell = entrance() + i; + if (passable[cell] + && Actor.findChar(cell) != null + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])){ + candidates.add(cell); + } + } + + if (candidates.isEmpty()){ + return -1; + } else { + return Random.element(candidates); + } } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java index ba73ffdf6..2a1b80700 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/LastShopLevel.java @@ -38,6 +38,9 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ImpShopRoom; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.watabou.noosa.Group; +import com.watabou.utils.PathFinder; +import com.watabou.utils.Point; +import com.watabou.utils.Random; import java.util.ArrayList; @@ -128,13 +131,21 @@ public class LastShopLevel extends RegularLevel { @Override public int randomRespawnCell( Char ch ) { - int cell; - do { - cell = pointToCell( roomEntrance.random() ); - } while (!passable[cell] - || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) - || Actor.findChar(cell) != null); - return cell; + ArrayList candidates = new ArrayList<>(); + for (Point p : roomEntrance.getPoints()){ + int cell = pointToCell(p); + if (passable[cell] + && Actor.findChar(cell) == null + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])){ + candidates.add(cell); + } + } + + if (candidates.isEmpty()){ + return -1; + } else { + return Random.element(candidates); + } } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java index de44d3ca7..61e45f879 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/Level.java @@ -689,8 +689,15 @@ public abstract class Level implements Bundlable { public int randomRespawnCell( Char ch ) { int cell; + int count = 0; do { + + if (++count > 30) { + return -1; + } + cell = Random.Int( length() ); + } while ((Dungeon.level == this && heroFOV[cell]) || !passable[cell] || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) @@ -1012,6 +1019,7 @@ public abstract class Level implements Bundlable { int result; do { result = randomRespawnCell( null ); + if (result == -1) return -1; } while (traps.get(result) != null || findMob(result) != null); return result; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java index 0cb31f5be..b336de635 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/PrisonBossLevel.java @@ -688,14 +688,21 @@ public class PrisonBossLevel extends Level { @Override public int randomRespawnCell( Char ch ) { - int pos = ENTRANCE_POS; //random cell adjacent to the entrance. - int cell; - do { - cell = pos + PathFinder.NEIGHBOURS8[Random.Int(8)]; - } while (!passable[cell] - || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[cell]) - || Actor.findChar(cell) != null); - return cell; + ArrayList candidates = new ArrayList<>(); + for (int i : PathFinder.NEIGHBOURS8){ + int cell = ENTRANCE_POS + i; + if (passable[cell] + && Actor.findChar(cell) != null + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])){ + candidates.add(cell); + } + } + + if (candidates.isEmpty()){ + return -1; + } else { + return Random.element(candidates); + } } @Override 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 0df6ca5ba..13e8d3740 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/RegularLevel.java @@ -549,18 +549,23 @@ public abstract class RegularLevel extends Level { if (fallIntoPit) { for (Room room : rooms) { if (room instanceof PitRoom) { - int result; - do { - result = pointToCell(room.random()); - } while (traps.get(result) != null - || findMob(result) != null - || heaps.get(result) != null); - return result; + ArrayList candidates = new ArrayList<>(); + for (Point p : room.getPoints()){ + int cell = pointToCell(p); + if (passable[cell] && + findMob(cell) == null){ + candidates.add(cell); + } + } + + if (!candidates.isEmpty()){ + return Random.element(candidates); + } } } } - return super.fallCell( false ); + return super.fallCell( fallIntoPit ); } @Override diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java index cf47078f1..b2fc84372 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/SewerBossLevel.java @@ -46,6 +46,7 @@ import com.watabou.noosa.Group; import com.watabou.noosa.audio.Music; import com.watabou.utils.Bundle; import com.watabou.utils.Callback; +import com.watabou.utils.Point; import com.watabou.utils.Random; import java.util.ArrayList; @@ -153,14 +154,21 @@ public class SewerBossLevel extends SewerLevel { @Override public int randomRespawnCell( Char ch ) { - int pos; - do { - pos = pointToCell(roomEntrance.random()); - } while (pos == entrance() - || !passable[pos] - || (Char.hasProp(ch, Char.Property.LARGE) && !openSpace[pos]) - || Actor.findChar(pos) != null); - return pos; + ArrayList candidates = new ArrayList<>(); + for (Point p : roomEntrance.getPoints()){ + int cell = pointToCell(p); + if (passable[cell] + && Actor.findChar(cell) == null + && (!Char.hasProp(ch, Char.Property.LARGE) || openSpace[cell])){ + candidates.add(cell); + } + } + + if (candidates.isEmpty()){ + return -1; + } else { + return Random.element(candidates); + } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/SpecialRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/SpecialRoom.java index c600901a3..74225c847 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/SpecialRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/special/SpecialRoom.java @@ -125,6 +125,8 @@ public abstract class SpecialRoom extends Room { if (!runConsSpecials.isEmpty()) runSpecials.add(runConsSpecials.remove(0)); } + runSpecials.add(0, WeakFloorRoom.class); + pitNeededDepth = -1; }