v1.4.0: fixed rare freezes and crashes with respawn and fall cells

This commit is contained in:
Evan Debenham
2022-08-20 23:30:45 -04:00
parent 76c0e8c622
commit e8aff9652f
10 changed files with 134 additions and 63 deletions

View File

@@ -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<Integer> 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

View File

@@ -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<Integer> 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

View File

@@ -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<Integer> 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

View File

@@ -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<Integer> 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

View File

@@ -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<Integer> 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

View File

@@ -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;

View File

@@ -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<Integer> 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

View File

@@ -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<Integer> 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

View File

@@ -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<Integer> 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);
}
}

View File

@@ -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;
}