v0.6.0: Implemented room initialization, converted loads of logic to new levelgen structure

This commit is contained in:
Evan Debenham 2017-04-13 00:10:33 -04:00
parent 7153104e4d
commit 01b4653938
21 changed files with 397 additions and 211 deletions

View File

@ -134,7 +134,7 @@ public class Rect {
}
public ArrayList<Point> getPoints() {
ArrayList<Point> points = new ArrayList<>(square()*2);
ArrayList<Point> points = new ArrayList<>();
for (int i = left; i <= right; i++)
for (int j = top; j <= bottom; j++)
points.add(new Point(i, j));

View File

@ -76,8 +76,6 @@ import java.util.HashSet;
public class Dungeon {
public static int transmutation; // depth number for a well of transmutation
//enum of items which have limited spawns, records how many have spawned
//could all be their own separate numbers, but this allows iterating, much nicer for bundling/initializing.
//TODO: this is fairly brittle when it comes to bundling, should look into a more flexible solution.
@ -156,9 +154,7 @@ public class Dungeon {
Potion.initColors();
Ring.initGems();
transmutation = Random.IntRange( 6, 14 );
SpecialRoom.shuffleTypes();
SpecialRoom.initForRun();
Random.seed();
@ -454,8 +450,6 @@ public class Dungeon {
quickslot.storePlaceholders( bundle );
bundle.put( WT, transmutation );
int[] dropValues = new int[limitedDrops.values().length];
for (limitedDrops value : limitedDrops.values())
dropValues[value.ordinal()] = value.count;
@ -563,8 +557,6 @@ public class Dungeon {
quickslot.restorePlaceholders( bundle );
if (fullLoad) {
transmutation = bundle.getInt( WT );
int[] dropValues = bundle.getIntArray(LIMDROPS);
for (limitedDrops value : limitedDrops.values())
value.count = value.ordinal() < dropValues.length ?

View File

@ -33,8 +33,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.quest.DarkGold;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.Pickaxe;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.BlacksmithRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.BlacksmithRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.BlacksmithSprite;
@ -279,27 +278,13 @@ public class Blacksmith extends NPC {
}
}
//FIXME: refactor this to work with new levelgen
public static boolean spawn( ArrayList<Room> rooms ) {
public static ArrayList<Room> spawn( ArrayList<Room> rooms ) {
if (!spawned && Dungeon.depth > 11 && Random.Int( 15 - Dungeon.depth ) == 0) {
Room blacksmith;
for (Room r : rooms) {
if (r instanceof StandardRoom && r.width() >= 6 && r.height() >= 6) {
blacksmith = new BlacksmithRoom().set(r);
rooms.set(rooms.indexOf(r), blacksmith);
spawned = true;
alternative = Random.Int( 2 ) == 0;
given = false;
break;
}
}
rooms.add(new BlacksmithRoom());
}
return spawned;
return rooms;
}
}
}

View File

@ -37,7 +37,6 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.MassGraveRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RotGardenRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.RitualSiteRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.plants.Rotberry;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
@ -283,8 +282,7 @@ public class Wandmaker extends NPC {
}
}
//FIXME: refactor this to work with new levelgen
public static boolean spawnRoom( ArrayList<Room> rooms) {
public static ArrayList<Room> spawnRoom( ArrayList<Room> rooms) {
questRoomSpawned = false;
if (!spawned && (type != 0 || (Dungeon.depth > 6 && Random.Int( 10 - Dungeon.depth ) == 0))) {
@ -292,41 +290,22 @@ public class Wandmaker extends NPC {
// but if the no herbalism challenge is enabled, only pick 1 or 2, no rotberry.
if (type == 0) type = Random.Int(Dungeon.isChallenged(Challenges.NO_HERBALISM) ? 2 : 3)+1;
//note that we set the type but can fail here. This ensures that if a level needs to be re-generated
//we don't re-roll the quest, it will try to assign itself to that new level with the same type.
Room questRoom = null;
for (Room r : rooms){
if (r instanceof StandardRoom && r.width() >= 7 && r.height() >= 7){
if (type == 2 || r.connected.size() == 1){
questRoom = r;
break;
}
}
}
if (questRoom == null){
return false;
}
Room temp = questRoom;
switch (type){
case 1: default:
questRoom = new MassGraveRoom().set(temp);
rooms.add(new MassGraveRoom());
break;
case 2:
questRoom = new RitualSiteRoom().set(temp);
rooms.add(new RitualSiteRoom());
break;
case 3:
questRoom = new RotGardenRoom().set(temp);
rooms.add(new RotGardenRoom());
break;
}
rooms.set(rooms.indexOf(temp), questRoom);
questRoomSpawned = true;
return true;
} else {
return true;
}
return rooms;
}
public static void complete() {

View File

@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
@ -56,6 +57,8 @@ import com.watabou.utils.PointF;
import com.watabou.utils.Random;
import com.watabou.utils.Rect;
import java.util.ArrayList;
public class CavesLevel extends RegularLevel {
{
@ -65,6 +68,21 @@ public class CavesLevel extends RegularLevel {
viewDistance = 6;
}
@Override
protected ArrayList<Room> initRooms() {
return Blacksmith.Quest.spawn(super.initRooms());
}
@Override
protected int standardRooms() {
return 5+Random.chances(new float[]{2, 2, 3, 2, 1, 1});
}
@Override
protected int specialRooms() {
return 1+Random.chances(new float[]{3, 3, 2, 1});
}
@Override
public String tilesTex() {
return Assets.TILES_CAVES;

View File

@ -58,6 +58,16 @@ public class CityLevel extends RegularLevel {
color2 = 0xf2f2f2;
}
@Override
protected int standardRooms() {
return 6+Random.chances(new float[]{2, 3, 3, 2, 1});
}
@Override
protected int specialRooms() {
return 1 + Random.chances(new float[]{2, 3, 3, 1});
}
@Override
public String tilesTex() {
return Assets.TILES_CITY;

View File

@ -59,7 +59,6 @@ import javax.microedition.khronos.opengles.GL10;
public class HallsLevel extends RegularLevel {
{
minRoomSize = 7;
viewDistance = Math.max( 25 - Dungeon.depth, 1 );
@ -67,6 +66,16 @@ public class HallsLevel extends RegularLevel {
color2 = 0xa68521;
}
@Override
protected int standardRooms() {
return 8+Random.chances(new float[]{3, 3, 2, 2, 1});
}
@Override
protected int specialRooms() {
return 1 + Random.chances(new float[]{1, 3, 3, 2});
}
@Override
public void create() {
addItemToSpawn( new Torch() );

View File

@ -28,11 +28,17 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LegacyBuilder;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.FissureRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.watabou.noosa.Group;
import com.watabou.utils.Random;
import java.util.ArrayList;
public class LastShopLevel extends RegularLevel {
{
@ -50,11 +56,27 @@ public class LastShopLevel extends RegularLevel {
return Assets.WATER_CITY;
}
@Override
protected ArrayList<Room> initRooms() {
ArrayList<Room> rooms = new ArrayList<>();
rooms.add ( roomEntrance = new EntranceRoom());
rooms.add( roomExit = new ExitRoom());
if (Imp.Quest.isCompleted()){
rooms.add( new ShopRoom() );
} else {
rooms.add( new FissureRoom() );
}
return rooms;
}
@Override
protected Builder builder() {
feeling = Feeling.CHASM;
return new LegacyBuilder(LegacyBuilder.Type.LAST_SHOP,
width, height, minRoomSize, maxRoomSize);
//TODO want to use strict line builder here
return super.builder();
}
@Override

View File

@ -260,8 +260,6 @@ public abstract class Level implements Bundlable {
} while (!build());
decorate();
PathFinder.setMapSize(width(), height());
buildFlagMaps();
cleanWalls();

View File

@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker;
import com.shatteredpixel.shatteredpixeldungeon.effects.Halo;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.AlarmTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ChillingTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ConfusionTrap;
@ -48,6 +49,8 @@ import com.watabou.noosa.particles.Emitter;
import com.watabou.utils.PointF;
import com.watabou.utils.Random;
import java.util.ArrayList;
public class PrisonLevel extends RegularLevel {
{
@ -55,6 +58,21 @@ public class PrisonLevel extends RegularLevel {
color2 = 0x88924c;
}
@Override
protected ArrayList<Room> initRooms() {
return Wandmaker.Quest.spawnRoom(super.initRooms());
}
@Override
protected int standardRooms() {
return 4+Random.chances(new float[]{2, 3, 3, 2, 1});
}
@Override
protected int specialRooms() {
return 1+Random.chances(new float[]{4, 3, 3});
}
@Override
public String tilesTex() {
return Assets.TILES_PRISON;

View File

@ -33,11 +33,13 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LegacyBuilder;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LineBuilder;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.RegularPainter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.PitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.WeakFloorRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
@ -70,25 +72,53 @@ public abstract class RegularLevel extends Level {
builder = builder();
rooms = builder.build(null);
if (rooms == null){
return false;
}
ArrayList<Room> initRooms = initRooms();
Collections.shuffle(initRooms);
roomEntrance = ((LegacyBuilder)builder).roomEntrance;
roomExit = ((LegacyBuilder)builder).roomExit;
do {
for (Room r : initRooms){
r.neigbours.clear();
r.connected.clear();
}
rooms = builder.build(initRooms);
} while (rooms == null);
if (!painter().paint(this, rooms)){
return false;
}
return painter().paint(this, rooms);
return true;
}
protected ArrayList<Room> initRooms() {
ArrayList<Room> initRooms = new ArrayList<>();
initRooms.add ( roomEntrance = new EntranceRoom());
initRooms.add( roomExit = new ExitRoom());
int standards = standardRooms();
for (int i = 0; i < standards; i++)
initRooms.add(StandardRoom.createRoom());
if (Dungeon.shopOnLevel())
initRooms.add(new ShopRoom());
int specials = specialRooms();
SpecialRoom.initForFloor();
for (int i = 0; i < specials; i++)
initRooms.add(SpecialRoom.createRoom());
return initRooms;
}
protected int standardRooms(){
return 0;
}
protected int specialRooms(){
return 0;
}
protected Builder builder(){
return new LegacyBuilder(LegacyBuilder.Type.REGULAR,
width, height, minRoomSize, maxRoomSize);
//TODO need a much better builder here
return new LineBuilder();
}
protected Painter painter(){
@ -137,9 +167,6 @@ public abstract class RegularLevel extends Level {
return new float[]{1};
}
protected int minRoomSize = 8;
protected int maxRoomSize = 10;
@Override
public int nMobs() {
switch(Dungeon.depth) {

View File

@ -21,7 +21,6 @@
package com.shatteredpixel.shatteredpixeldungeon.levels;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Bones;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
@ -30,17 +29,17 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LegacyBuilder;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RatKingRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.SewerBossEntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.noosa.Group;
import com.watabou.utils.Bundle;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
public class SewerBossLevel extends RegularLevel {
import java.util.ArrayList;
public class SewerBossLevel extends SewerLevel {
{
color1 = 0x48763c;
@ -50,41 +49,26 @@ public class SewerBossLevel extends RegularLevel {
private int stairs = 0;
@Override
public String tilesTex() {
return Assets.TILES_SEWERS;
protected ArrayList<Room> initRooms() {
ArrayList<Room> initRooms = new ArrayList<>();
initRooms.add ( roomEntrance = roomExit = new SewerBossEntranceRoom());
int standards = standardRooms();
for (int i = 0; i < standards; i++)
initRooms.add(StandardRoom.createRoom());
initRooms.add(new RatKingRoom());
return initRooms;
}
@Override
public String waterTex() {
return Assets.WATER_SEWERS;
}
@Override
protected boolean build() {
if (!super.build())
return false;
//sticks the exit in the room entrance.
exit = roomEntrance.top * width() + (roomEntrance.left + roomEntrance.right) / 2;
map[exit] = Terrain.LOCKED_EXIT;
//make sure the exit is only visible in the entrance room.
int count = 0;
for (int i : PathFinder.NEIGHBOURS8){
//exit must have exactly 3 non-wall tiles around it.
if (map[exit+i] != Terrain.WALL)
count++;
}
if (count > 3)
return false;
return true;
protected int standardRooms() {
return 3+Random.chances(new float[]{4, 2, 2});
}
protected Builder builder(){
return new LegacyBuilder(LegacyBuilder.Type.SEWER_BOSS,
width, height, minRoomSize, maxRoomSize);
//TODO want to use a more simple circular builder here
return super.builder();
}
@Override
@ -110,29 +94,6 @@ public class SewerBossLevel extends RegularLevel {
protected int nTraps() {
return 0;
}
@Override
protected void decorate() {
int start = roomExit.top * width() + roomExit.left + 1;
int end = start + roomExit.width() - 2;
for (int i=start; i < end; i++) {
if (i != exit && map[i] == Terrain.WALL) {
map[i] = Terrain.WALL_DECO;
map[i + width()] = Terrain.WATER;
} else {
map[i + width()] = Terrain.EMPTY;
}
}
placeSign();
}
@Override
public Group addVisuals() {
super.addVisuals();
SewerLevel.addSewerVisuals(this, visuals);
return visuals;
}
@Override
protected void createMobs() {
@ -209,26 +170,4 @@ public class SewerBossLevel extends RegularLevel {
stairs = bundle.getInt( STAIRS );
roomExit = roomEntrance;
}
@Override
public String tileName( int tile ) {
switch (tile) {
case Terrain.WATER:
return Messages.get(SewerLevel.class, "water_name");
default:
return super.tileName( tile );
}
}
@Override
public String tileDesc(int tile) {
switch (tile) {
case Terrain.EMPTY_DECO:
return Messages.get(SewerLevel.class, "empty_deco_desc");
case Terrain.BOOKSHELF:
return Messages.get(SewerLevel.class, "bookshelf_desc");
default:
return super.tileDesc( tile );
}
}
}

View File

@ -53,6 +53,24 @@ public class SewerLevel extends RegularLevel {
color2 = 0x59994a;
}
@Override
protected int standardRooms() {
if (Dungeon.depth == 1){
return 5+Random.chances(new float[]{4, 3, 3});
} else {
return 4+Random.chances(new float[]{2, 4, 2, 1});
}
}
@Override
protected int specialRooms() {
if (Dungeon.depth == 1){
return 1;
} else {
return 1+Random.chances(new float[]{4, 4, 2});
}
}
@Override
public String tilesTex() {
return Assets.TILES_SEWERS;

View File

@ -21,28 +21,11 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.builders;
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ArmoryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.CryptRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.GardenRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.LaboratoryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.LibraryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.MagicWellRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.PitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RatKingRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.StatueRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.TreasuryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.VaultRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.WeakFloorRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
@ -58,6 +41,9 @@ import java.util.ListIterator;
//This builder exactly mimics pre-0.6.0 levelgen, including all of its limitations
//Currently implemented during this transition period, it will likely not survive to 0.6.0 release
//this is now broken due to changes elsewhere and serves only as a reference for older logic.
//DO NOT USE, pending deletion before 0.6.0 release.
public class LegacyBuilder extends Builder {
public enum Type{
@ -190,6 +176,7 @@ public class LegacyBuilder extends Builder {
}
}
/*
specials = new ArrayList<>( SpecialRoom.SPECIALS );
if (Dungeon.bossLevel( Dungeon.depth + 1 )) {
specials.remove( WeakFloorRoom.class );
@ -201,19 +188,21 @@ public class LegacyBuilder extends Builder {
if (Dungeon.isChallenged( Challenges.NO_HERBALISM )){
//sorry warden, no lucky sungrass or blandfruit seeds for you!
specials.remove( GardenRoom.class );
}
}*/
if (!assignRoomType())
return null;
//Quest generation logic
//disabled due to incompatibilities with old logic
/*
if (Dungeon.depth >= 6 && Dungeon.depth <= 9){
if (!Wandmaker.Quest.spawnRoom( rooms ) && Dungeon.depth == 9)
return null;
} else if (Dungeon.depth >= 11 && Dungeon.depth <= 14){
if (!Blacksmith.Quest.spawn( rooms ) && Dungeon.depth == 14)
return null;
}
}*/
ArrayList<Room> resultRooms = new ArrayList<>();
for (Room r : rooms)
@ -478,6 +467,8 @@ public class LegacyBuilder extends Builder {
boolean pitMade = false;
ListIterator<Room> it = rooms.listIterator();
/*
while (it.hasNext()) {
Room r = it.next();
Room temp;
@ -555,7 +546,7 @@ public class LegacyBuilder extends Builder {
}
if (Level.pitRoomNeeded && !pitMade) return false;
*/
Class<? extends Room> tunnelType = TunnelRoom.class;
if ((Dungeon.depth > 5 && Dungeon.depth <= 10) ||
(Dungeon.depth > 15 && Dungeon.depth <= 20)){

View File

@ -58,7 +58,7 @@ public class LineBuilder extends Builder {
}
}
if (entrance == null || exit == null){
if (entrance == null){
return null;
}
@ -80,6 +80,9 @@ public class LineBuilder extends Builder {
Room curr = entrance;
for (int i = 0; i <= roomsOnPath; i++){
if (i == roomsOnPath && exit == null)
continue;
if (Random.Int(2) == 0){
TunnelRoom t = new TunnelRoom();
t.setSize();

View File

@ -82,8 +82,6 @@ public class RegularPainter extends Painter {
level.setSize(width+1, height+1);
PathFinder.setMapSize(level.width(), level.height());
for (Room r : rooms) {
placeDoors( r );
r.paint( level );

View File

@ -21,7 +21,6 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfAwareness;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfHealth;
@ -38,6 +37,8 @@ public class MagicWellRoom extends SpecialRoom {
private static final Class<?>[] WATERS =
{WaterOfAwareness.class, WaterOfHealth.class, WaterOfTransmutation.class};
public Class<?extends WellWater> overrideWater = null;
public void paint( Level level ) {
Painter.fill( level, this, Terrain.WALL );
@ -48,12 +49,12 @@ public class MagicWellRoom extends SpecialRoom {
@SuppressWarnings("unchecked")
Class<? extends WellWater> waterClass =
Dungeon.depth >= Dungeon.transmutation ?
WaterOfTransmutation.class :
overrideWater != null ?
overrideWater :
(Class<? extends WellWater>)Random.element( WATERS );
if (waterClass == WaterOfTransmutation.class) {
Dungeon.transmutation = Integer.MAX_VALUE;
SpecialRoom.disableGaranteedWell();
}
WellWater water = (WellWater)level.blobs.get( waterClass );

View File

@ -92,6 +92,12 @@ public class ShopRoom extends SpecialRoom {
return Math.max(7, (int)(Math.sqrt(itemsToSpawn.size())+3));
}
//FIXME this is messy, the floor 21 shop should probably just be its own class.
@Override
public int maxConnections(int direction) {
return Dungeon.depth == 21 ? 2 : 1;
}
@Override
public int minHeight() {
if (itemsToSpawn == null) generateItems();

View File

@ -21,12 +21,17 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfTransmutation;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.watabou.utils.Bundle;
import com.watabou.utils.Random;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
public class SpecialRoom extends Room {
@ -60,41 +65,112 @@ public class SpecialRoom extends Room {
TreasuryRoom.class, TrapsRoom.class, StorageRoom.class, StatueRoom.class, LaboratoryRoom.class, VaultRoom.class
) );
public static ArrayList<Class<? extends Room>> SPECIALS = new ArrayList<>();
public static ArrayList<Class<? extends Room>> runSpecials = new ArrayList<>();
public static ArrayList<Class<? extends Room>> floorSpecials = new ArrayList<>();
public static void shuffleTypes() {
SPECIALS = (ArrayList<Class<?extends Room>>)ALL_SPEC.clone();
int size = SPECIALS.size();
for (int i=0; i < size - 1; i++) {
int j = Random.Int( i, size );
if (j != i) {
Class<?extends Room> c = SPECIALS.get( i );
SPECIALS.set( i, SPECIALS.get( j ) );
SPECIALS.set( j, c );
}
private static int pitNeededDepth = Integer.MAX_VALUE;
private static int guaranteedWellDepth = Integer.MAX_VALUE;
public static void initForRun() {
runSpecials = (ArrayList<Class<?extends Room>>)ALL_SPEC.clone();
//remove special rooms disallowed by challenges
if (Dungeon.isChallenged( Challenges.NO_ARMOR )){
//no sense in giving an armor reward room on a run with no armor.
runSpecials.remove( CryptRoom.class );
}
if (Dungeon.isChallenged( Challenges.NO_HERBALISM )){
//sorry warden, no lucky sungrass or blandfruit seeds for you!
runSpecials.remove( GardenRoom.class );
}
guaranteedWellDepth = Random.IntRange( 6, 14 );
Collections.shuffle(runSpecials);
}
public static void initForFloor(){
floorSpecials = (ArrayList<Class<?extends Room>>) runSpecials.clone();
}
private static void useType( Class<?extends Room> type ) {
if (runSpecials.remove( type )) {
floorSpecials.remove( type );
runSpecials.add( type );
}
}
public static void useType( Class<?extends Room> type ) {
if (SPECIALS.remove( type )) {
SPECIALS.add( type );
public static void disableGaranteedWell(){
guaranteedWellDepth = Integer.MAX_VALUE;
}
public static SpecialRoom createRoom(){
if (Dungeon.depth == pitNeededDepth){
pitNeededDepth = -1;
floorSpecials.remove( ArmoryRoom.class );
floorSpecials.remove( CryptRoom.class );
floorSpecials.remove( LaboratoryRoom.class );
floorSpecials.remove( LibraryRoom.class );
floorSpecials.remove( StatueRoom.class );
floorSpecials.remove( TreasuryRoom.class );
floorSpecials.remove( VaultRoom.class );
floorSpecials.remove( WeakFloorRoom.class );
return new PitRoom();
//TODO should laboratory rooms be more common like this?
} else if (Dungeon.depth % 5 == 2 && floorSpecials.contains( LaboratoryRoom.class )) {
useType(LaboratoryRoom.class);
return new LaboratoryRoom();
} else if (Dungeon.depth >= guaranteedWellDepth) {
useType( MagicWellRoom.class );
MagicWellRoom r = new MagicWellRoom();
r.overrideWater = WaterOfTransmutation.class;
guaranteedWellDepth = Integer.MAX_VALUE;
return r;
} else {
if (Dungeon.bossLevel(Dungeon.depth + 1)){
floorSpecials.remove(WeakFloorRoom.class);
}
Room r = null;
try {
r = floorSpecials.get( Math.min( Random.Int( floorSpecials.size() ), Random.Int( floorSpecials.size() ) ) ).newInstance();
} catch (Exception e) {
ShatteredPixelDungeon.reportException(e);
}
if (r instanceof WeakFloorRoom){
pitNeededDepth = Dungeon.depth + 1;
}
useType( r.getClass() );
return (SpecialRoom)r;
}
}
private static final String ROOMS = "special_rooms";
private static final String PIT = "pit_needed";
private static final String WELL = "guaranteed_well";
public static void restoreRoomsFromBundle( Bundle bundle ) {
if (bundle.contains( ROOMS )) {
SPECIALS.clear();
for (Class<?extends Room> type : bundle.getClassArray( ROOMS )) {
SPECIALS.add( type );
}
} else {
shuffleTypes();
runSpecials.clear();
for (Class<?extends Room> type : bundle.getClassArray( ROOMS )) {
runSpecials.add( type );
}
pitNeededDepth = bundle.getInt(PIT);
guaranteedWellDepth = bundle.getInt(WELL);
}
public static void storeRoomsInBundle( Bundle bundle ) {
bundle.put( ROOMS, SPECIALS.toArray(new Class[0]) );
bundle.put( ROOMS, runSpecials.toArray(new Class[0]) );
bundle.put( PIT, pitNeededDepth );
bundle.put( WELL, guaranteedWellDepth );
}
}

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
@ -30,9 +30,19 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FireTrap;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
public class BlacksmithRoom extends SpecialRoom {
public void paint( Level level ) {
public class BlacksmithRoom extends StandardRoom {
@Override
public int minWidth() {
return Math.max(super.minWidth(), 6);
}
@Override
public int minHeight() {
return Math.max(super.minHeight(), 6);
}
public void paint(Level level ) {
Painter.fill( level, this, Terrain.WALL );
Painter.fill( level, this, 1, Terrain.TRAP );

View File

@ -0,0 +1,86 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2017 Evan Debenham
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard;
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.watabou.utils.Point;
public class SewerBossEntranceRoom extends EntranceRoom {
@Override
public int minWidth() {
return 11;
}
@Override
public int maxWidth() {
return 11;
}
@Override
public int minHeight() {
return 5;
}
@Override
public int maxHeight() {
return 8;
}
//TODO perhaps I just want to deny all top-side connections
@Override
public boolean canConnect(Point p) {
//refuses connections on the center 3 tiles on the top side
return super.canConnect(p)
&& !(p.y == top && p.x >= (left + (width()/2 - 1)) && p.x <= (left + (width()/2 + 1)));
}
public void paint(Level level ) {
Painter.fill( level, this, Terrain.WALL );
Painter.fill( level, this, 1, Terrain.EMPTY );
Painter.fill( level, left+1, top+1, width()-2, 1, Terrain.WALL_DECO);
Painter.fill( level, left+1, top+2, width()-2, 1, Terrain.WATER);
Painter.set( level, left+width()/2, top+1, Terrain.LOCKED_EXIT);
level.exit = level.pointToCell(new Point(left+width()/2, top+1));
do {
level.entrance = level.pointToCell(random(3));
} while (level.findMob(level.entrance) != null);
Painter.set( level, level.entrance, Terrain.ENTRANCE );
for (Room.Door door : connected.values()) {
door.set( Room.Door.Type.REGULAR );
if (door.y == top){
Painter.set( level, door.x, door.y+1, Terrain.WATER);
}
}
}
}