From d51e397c26be2c79f606825b482776fe5c051c11 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Wed, 4 Oct 2023 22:47:26 -0400 Subject: [PATCH] v2.2.0: early code for gnoll caves quest levelgen --- .../main/java/com/watabou/utils/Point.java | 6 +++ .../levels/painters/MiningLevelPainter.java | 13 ++++- .../levels/painters/RegularPainter.java | 3 ++ .../levels/rooms/Room.java | 14 ++++-- .../levels/rooms/quest/MineEntrance.java | 45 ++++++++++++++++- .../levels/rooms/quest/MineGiantRoom.java | 49 +++++++++++++++++++ .../levels/rooms/quest/MineLargeRoom.java | 47 ++++++++++++++++++ .../levels/rooms/quest/MineSecretRoom.java | 10 +++- .../levels/rooms/quest/MineSmallRoom.java | 41 ++++++++++++++++ 9 files changed, 219 insertions(+), 9 deletions(-) diff --git a/SPD-classes/src/main/java/com/watabou/utils/Point.java b/SPD-classes/src/main/java/com/watabou/utils/Point.java index ac4bd507c..7b6a9b2f3 100644 --- a/SPD-classes/src/main/java/com/watabou/utils/Point.java +++ b/SPD-classes/src/main/java/com/watabou/utils/Point.java @@ -80,6 +80,12 @@ public class Point { public float length() { return (float)Math.sqrt( x * x + y * y ); } + + public static float distance( Point a, Point b ) { + float dx = a.x - b.x; + float dy = a.y - b.y; + return (float)Math.sqrt( dx * dx + dy * dy ); + } @Override public boolean equals( Object obj ) { diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/MiningLevelPainter.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/MiningLevelPainter.java index 0fdbc2606..02c2b6d81 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/MiningLevelPainter.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/MiningLevelPainter.java @@ -21,6 +21,9 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.painters; +import com.shatteredpixel.shatteredpixeldungeon.items.Heap; +import com.shatteredpixel.shatteredpixeldungeon.items.Item; +import com.shatteredpixel.shatteredpixeldungeon.items.quest.DarkGold; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; @@ -55,6 +58,11 @@ public class MiningLevelPainter extends CavesPainter { goldToAdd--; } } + for (Heap h : level.heaps.valueList()){ + for (Item i : h.items){ + if (i instanceof DarkGold) goldToAdd -= i.quantity(); + } + } int[] map = level.map; do { @@ -112,15 +120,16 @@ public class MiningLevelPainter extends CavesPainter { float hiddenDoorChance = 0.90f; + //wall doors will still be wall //hidden doors become wall tiles a bit later in painting - //everything else becomes empty + //everything else usually becomes empty, but can be wall sometimes for (Room r : rooms) { for (Room n : r.connected.keySet()) { Room.Door d = r.connected.get(n); int door = d.x + d.y * l.width(); - if (d.type == Room.Door.Type.HIDDEN){ + if (d.type == Room.Door.Type.WALL || d.type == Room.Door.Type.HIDDEN){ l.map[door] = Terrain.WALL; } else { //some of these are randomly hidden, using the same rules as regular levels diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java index 380c1d2f9..e3c6d622f 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/painters/RegularPainter.java @@ -287,6 +287,9 @@ public abstract class RegularPainter extends Painter { case CRYSTAL: l.map[door] = Terrain.CRYSTAL_DOOR; break; + case WALL: + l.map[door] = Terrain.WALL; + break; } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java index e7a2031ed..d3349cd21 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java @@ -428,7 +428,7 @@ public abstract class Room extends Rect implements Graph.Node, Bundlable { public static class Door extends Point implements Bundlable { public enum Type { - EMPTY, TUNNEL, WATER, REGULAR, UNLOCKED, HIDDEN, BARRICADE, LOCKED, CRYSTAL + EMPTY, TUNNEL, WATER, REGULAR, UNLOCKED, HIDDEN, BARRICADE, LOCKED, CRYSTAL, WALL } public Type type = Type.EMPTY; @@ -442,9 +442,15 @@ public abstract class Room extends Rect implements Graph.Node, Bundlable { public Door( int x, int y ) { super( x, y ); } - + + private boolean typeLocked = false; + + public void lockTypeChanges( boolean lock ){ + typeLocked = lock; + } + public void set( Type type ) { - if (type.compareTo( this.type ) > 0) { + if (!typeLocked && type.compareTo( this.type ) > 0) { this.type = type; } } @@ -454,6 +460,7 @@ public abstract class Room extends Rect implements Graph.Node, Bundlable { bundle.put("x", x); bundle.put("y", y); bundle.put("type", type); + bundle.put("type_locked", typeLocked); } @Override @@ -461,6 +468,7 @@ public abstract class Room extends Rect implements Graph.Node, Bundlable { x = bundle.getInt("x"); y = bundle.getInt("y"); type = bundle.getEnum("type", Type.class); + typeLocked = bundle.getBoolean("type_locked"); } } } \ No newline at end of file diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineEntrance.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineEntrance.java index 0d39207b0..c33534285 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineEntrance.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineEntrance.java @@ -28,12 +28,18 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.features.LevelTransition; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.tiles.CustomTilemap; import com.watabou.noosa.Image; import com.watabou.noosa.Tilemap; +import com.watabou.utils.GameMath; import com.watabou.utils.Point; +import com.watabou.utils.Random; + +import java.util.ArrayList; public class MineEntrance extends EntranceRoom { @@ -66,8 +72,8 @@ public class MineEntrance extends EntranceRoom { Painter.set( level, entrance, Terrain.ENTRANCE ); QuestExit vis = new QuestExit(); - Point p = level.cellToPoint(entrance); - vis.pos(p.x - 1, p.y - 1); + Point e = level.cellToPoint(entrance); + vis.pos(e.x - 1, e.y - 1); level.customTiles.add(vis); level.transitions.add(new LevelTransition(level, @@ -84,6 +90,41 @@ public class MineEntrance extends EntranceRoom { Painter.set(level, r, Terrain.MINE_CRYSTAL); } } + } else if (Blacksmith.Quest.Type() == Blacksmith.Quest.GNOLL) { + + //connections to non-secret rooms have a 7/8 chance to become empty, otherwise wall + for (Room n : connected.keySet()){ + if (!(n instanceof SecretRoom) && connected.get(n).type == Door.Type.REGULAR){ + if (Random.Int(8) == 0){ + connected.get(n).set(Door.Type.EMPTY); + } else { + connected.get(n).set(Door.Type.WALL); + } + connected.get(n).lockTypeChanges(true); + } + } + + ArrayList doors = new ArrayList<>(); + for (Door d : connected.values()){ + if (d.type == Door.Type.WALL){ + doors.add(d); + } + } + + for (Point p : getPoints()){ + int cell = level.pointToCell(p); + if (level.distance(cell, entrance) > 1 && level.map[cell] == Terrain.EMPTY){ + float dist = 1000; + for (Door d : doors){ + dist = Math.min(dist, Point.distance(p, d)); + } + dist = GameMath.gate(1f, dist-0.5f, 5f); + if (Random.Float((float) Math.pow(dist, 2)) < 1f) { + Painter.set(level, cell, Terrain.MINE_BOULDER); + } + } + } + } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineGiantRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineGiantRoom.java index e1af1c395..f36e53ffa 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineGiantRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineGiantRoom.java @@ -26,8 +26,14 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.CaveRoom; +import com.watabou.utils.GameMath; import com.watabou.utils.Point; +import com.watabou.utils.Random; + +import java.util.ArrayList; public class MineGiantRoom extends CaveRoom { @@ -61,6 +67,49 @@ public class MineGiantRoom extends CaveRoom { level.mobs.add(m); Painter.set(level, p, Terrain.EMPTY); + } else if (Blacksmith.Quest.Type() == Blacksmith.Quest.GNOLL){ + Painter.fillEllipse(level, this, 3, Terrain.EMPTY); + + //connections to non-secret rooms have a 7/8 chance to become empty, otherwise wall + for (Room n : connected.keySet()){ + if (!(n instanceof SecretRoom) && connected.get(n).type == Door.Type.REGULAR){ + if (Random.Int(8) == 0){ + connected.get(n).set(Door.Type.EMPTY); + } else { + connected.get(n).set(Door.Type.WALL); + } + connected.get(n).lockTypeChanges(true); + } + } + + ArrayList doors = new ArrayList<>(); + for (Door d : connected.values()){ + if (d.type == Door.Type.WALL){ + doors.add(d); + } + } + + for (Point p : getPoints()){ + int cell = level.pointToCell(p); + if (level.map[cell] == Terrain.EMPTY){ + float dist = 1000; + for (Door d : doors){ + dist = Math.min(dist, Point.distance(p, d)); + } + dist = GameMath.gate(1f, dist-0.5f, 3f); + if (Random.Float((float)Math.pow(dist, 2)) < 1f){ + Painter.set(level, cell, Terrain.MINE_BOULDER); + } + } + } + + for (int i = 0; i < 8; i ++){ + Point r = random(5); + if (level.map[level.pointToCell(r)] != Terrain.WALL) { + Painter.set(level, r, Terrain.BARRICADE); + } + } + } else { Painter.fillEllipse(level, this, 3, Terrain.EMPTY); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineLargeRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineLargeRoom.java index 312676789..2f68f871e 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineLargeRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineLargeRoom.java @@ -26,9 +26,13 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.CaveRoom; +import com.watabou.utils.GameMath; import com.watabou.utils.PathFinder; import com.watabou.utils.Point; +import com.watabou.utils.Random; import java.util.ArrayList; @@ -88,6 +92,49 @@ public class MineLargeRoom extends CaveRoom { level.mobs.add(m); Painter.set(level, p, Terrain.EMPTY); + } else if (Blacksmith.Quest.Type() == Blacksmith.Quest.GNOLL){ + Painter.fillEllipse(level, this, 3, Terrain.EMPTY); + + //connections to non-secret rooms have a 7/8 chance to become empty, otherwise wall + for (Room n : connected.keySet()){ + if (!(n instanceof SecretRoom) && connected.get(n).type == Door.Type.REGULAR){ + if (Random.Int(8) == 0){ + connected.get(n).set(Door.Type.EMPTY); + } else { + connected.get(n).set(Door.Type.WALL); + } + connected.get(n).lockTypeChanges(true); + } + } + + ArrayList doors = new ArrayList<>(); + for (Door d : connected.values()){ + if (d.type == Door.Type.WALL){ + doors.add(d); + } + } + + for (Point p : getPoints()){ + int cell = level.pointToCell(p); + if (level.map[cell] == Terrain.EMPTY){ + float dist = 1000; + for (Door d : doors){ + dist = Math.min(dist, Point.distance(p, d)); + } + dist = GameMath.gate(1f, dist-0.5f, 5f); + if (Random.Float((float)Math.pow(dist, 2)) < 1f){ + Painter.set(level, cell, Terrain.MINE_BOULDER); + } + } + } + + for (int i = 0; i < 4; i ++){ + Point r = random(5); + if (level.map[level.pointToCell(r)] != Terrain.WALL) { + Painter.set(level, r, Terrain.BARRICADE); + } + } + } else { Painter.fillEllipse(level, this, 3, Terrain.EMPTY); } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSecretRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSecretRoom.java index e3cff5804..d6ef70648 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSecretRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSecretRoom.java @@ -22,6 +22,8 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith; +import com.shatteredpixel.shatteredpixeldungeon.items.Heap; +import com.shatteredpixel.shatteredpixeldungeon.items.quest.DarkGold; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; @@ -40,14 +42,18 @@ public class MineSecretRoom extends SecretRoom { public void paint(Level level) { Painter.fill( level, this, Terrain.WALL ); + entrance().set( Door.Type.HIDDEN ); + if (Blacksmith.Quest.Type() == Blacksmith.Quest.CRYSTAL) { Painter.fill(level, this, 1, Terrain.MINE_CRYSTAL); + } else if (Blacksmith.Quest.Type() == Blacksmith.Quest.GNOLL) { + Painter.fill( level, this, 1, Terrain.EMPTY_SP ); + level.drop(new DarkGold().quantity(Random.NormalIntRange(3, 5)), level.pointToCell(center())).type = Heap.Type.CHEST; + return; } else { Painter.fill(level, this, 1, Terrain.EMPTY); } - entrance().set( Door.Type.HIDDEN ); - int goldAmount = Random.NormalIntRange(3, 5); for (int i = 0; i < goldAmount; i++){ diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSmallRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSmallRoom.java index 92b7573f2..804b8f869 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSmallRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/quest/MineSmallRoom.java @@ -25,8 +25,14 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.CaveRoom; +import com.watabou.utils.GameMath; import com.watabou.utils.Point; +import com.watabou.utils.Random; + +import java.util.ArrayList; public class MineSmallRoom extends CaveRoom { @@ -57,6 +63,41 @@ public class MineSmallRoom extends CaveRoom { Painter.set(level, r, Terrain.MINE_CRYSTAL); } } + } else if (Blacksmith.Quest.Type() == Blacksmith.Quest.GNOLL) { + + //connections to non-secret rooms have a 7/8 chance to become empty, otherwise wall + for (Room n : connected.keySet()){ + if (!(n instanceof SecretRoom) && connected.get(n).type == Door.Type.REGULAR){ + if (Random.Int(8) == 0){ + connected.get(n).set(Door.Type.EMPTY); + } else { + connected.get(n).set(Door.Type.WALL); + } + connected.get(n).lockTypeChanges(true); + } + } + + ArrayList doors = new ArrayList<>(); + for (Door d : connected.values()){ + if (d.type == Door.Type.WALL){ + doors.add(d); + } + } + + for (Point p : getPoints()){ + int cell = level.pointToCell(p); + if (level.map[cell] == Terrain.EMPTY){ + float dist = 1000; + for (Door d : doors){ + dist = Math.min(dist, Point.distance(p, d)); + } + dist = GameMath.gate(1f, dist, 5f); + if (Random.Float((float) Math.pow(dist, 2)) < 1f) { + Painter.set(level, cell, Terrain.MINE_BOULDER); + } + } + } + } }