V0.1.0 Partial Commit
changed package and application names to differentiate from main PD release
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Camera;
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class CavesBossLevel extends Level {
|
||||
|
||||
{
|
||||
color1 = 0x534f3e;
|
||||
color2 = 0xb9d661;
|
||||
|
||||
viewDistance = 6;
|
||||
}
|
||||
|
||||
private static final int ROOM_LEFT = WIDTH / 2 - 2;
|
||||
private static final int ROOM_RIGHT = WIDTH / 2 + 2;
|
||||
private static final int ROOM_TOP = HEIGHT / 2 - 2;
|
||||
private static final int ROOM_BOTTOM = HEIGHT / 2 + 2;
|
||||
|
||||
private int arenaDoor;
|
||||
private boolean enteredArena = false;
|
||||
private boolean keyDropped = false;
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_CAVES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_CAVES;
|
||||
}
|
||||
|
||||
private static final String DOOR = "door";
|
||||
private static final String ENTERED = "entered";
|
||||
private static final String DROPPED = "droppped";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( DOOR, arenaDoor );
|
||||
bundle.put( ENTERED, enteredArena );
|
||||
bundle.put( DROPPED, keyDropped );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
arenaDoor = bundle.getInt( DOOR );
|
||||
enteredArena = bundle.getBoolean( ENTERED );
|
||||
keyDropped = bundle.getBoolean( DROPPED );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
int topMost = Integer.MAX_VALUE;
|
||||
|
||||
for (int i=0; i < 8; i++) {
|
||||
int left, right, top, bottom;
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
left = Random.Int( 1, ROOM_LEFT - 3 );
|
||||
right = ROOM_RIGHT + 3;
|
||||
} else {
|
||||
left = ROOM_LEFT - 3;
|
||||
right = Random.Int( ROOM_RIGHT + 3, WIDTH - 1 );
|
||||
}
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
top = Random.Int( 2, ROOM_TOP - 3 );
|
||||
bottom = ROOM_BOTTOM + 3;
|
||||
} else {
|
||||
top = ROOM_LEFT - 3;
|
||||
bottom = Random.Int( ROOM_TOP + 3, HEIGHT - 1 );
|
||||
}
|
||||
|
||||
Painter.fill( this, left, top, right - left + 1, bottom - top + 1, Terrain.EMPTY );
|
||||
|
||||
if (top < topMost) {
|
||||
topMost = top;
|
||||
exit = Random.Int( left, right ) + (top - 1) * WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
map[exit] = Terrain.LOCKED_EXIT;
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && Random.Int( 6 ) == 0) {
|
||||
map[i] = Terrain.INACTIVE_TRAP;
|
||||
}
|
||||
}
|
||||
|
||||
Painter.fill( this, ROOM_LEFT - 1, ROOM_TOP - 1,
|
||||
ROOM_RIGHT - ROOM_LEFT + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL );
|
||||
Painter.fill( this, ROOM_LEFT, ROOM_TOP + 1,
|
||||
ROOM_RIGHT - ROOM_LEFT + 1, ROOM_BOTTOM - ROOM_TOP, Terrain.EMPTY );
|
||||
|
||||
Painter.fill( this, ROOM_LEFT, ROOM_TOP,
|
||||
ROOM_RIGHT - ROOM_LEFT + 1, 1, Terrain.TOXIC_TRAP );
|
||||
|
||||
arenaDoor = Random.Int( ROOM_LEFT, ROOM_RIGHT ) + (ROOM_BOTTOM + 1) * WIDTH;
|
||||
map[arenaDoor] = Terrain.DOOR;
|
||||
|
||||
entrance = Random.Int( ROOM_LEFT + 1, ROOM_RIGHT - 1 ) +
|
||||
Random.Int( ROOM_TOP + 1, ROOM_BOTTOM - 1 ) * WIDTH;
|
||||
map[entrance] = Terrain.ENTRANCE;
|
||||
|
||||
boolean[] patch = Patch.generate( 0.45f, 6 );
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && patch[i]) {
|
||||
map[i] = Terrain.WATER;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=WIDTH + 1; i < LENGTH - WIDTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY) {
|
||||
int n = 0;
|
||||
if (map[i+1] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (map[i-1] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (map[i+WIDTH] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (map[i-WIDTH] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (Random.Int( 8 ) <= n) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.WALL && Random.Int( 8 ) == 0) {
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
int sign;
|
||||
do {
|
||||
sign = Random.Int( ROOM_LEFT, ROOM_RIGHT ) + Random.Int( ROOM_TOP, ROOM_BOTTOM ) * WIDTH;
|
||||
} while (sign == entrance);
|
||||
map[sign] = Terrain.SIGN;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
}
|
||||
|
||||
public Actor respawner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
Item item = Bones.get();
|
||||
if (item != null) {
|
||||
int pos;
|
||||
do {
|
||||
pos = Random.IntRange( ROOM_LEFT, ROOM_RIGHT ) + Random.IntRange( ROOM_TOP + 1, ROOM_BOTTOM ) * WIDTH;
|
||||
} while (pos == entrance || map[pos] == Terrain.SIGN);
|
||||
drop( item, pos ).type = Heap.Type.SKELETON;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void press( int cell, Char hero ) {
|
||||
|
||||
super.press( cell, hero );
|
||||
|
||||
if (!enteredArena && outsideEntraceRoom( cell ) && hero == Dungeon.hero) {
|
||||
|
||||
enteredArena = true;
|
||||
|
||||
Mob boss = Bestiary.mob( Dungeon.depth );
|
||||
boss.state = Mob.State.HUNTING;
|
||||
do {
|
||||
boss.pos = Random.Int( LENGTH );
|
||||
} while (
|
||||
!passable[boss.pos] ||
|
||||
!outsideEntraceRoom( boss.pos ) ||
|
||||
Dungeon.visible[boss.pos]);
|
||||
GameScene.add( boss );
|
||||
|
||||
set( arenaDoor, Terrain.WALL );
|
||||
GameScene.updateMap( arenaDoor );
|
||||
Dungeon.observe();
|
||||
|
||||
CellEmitter.get( arenaDoor ).start( Speck.factory( Speck.ROCK ), 0.07f, 10 );
|
||||
Camera.main.shake( 3, 0.7f );
|
||||
Sample.INSTANCE.play( Assets.SND_ROCKS );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Heap drop( Item item, int cell ) {
|
||||
|
||||
if (!keyDropped && item instanceof SkeletonKey) {
|
||||
|
||||
keyDropped = true;
|
||||
|
||||
CellEmitter.get( arenaDoor ).start( Speck.factory( Speck.ROCK ), 0.07f, 10 );
|
||||
|
||||
set( arenaDoor, Terrain.EMPTY_DECO );
|
||||
GameScene.updateMap( arenaDoor );
|
||||
Dungeon.observe();
|
||||
}
|
||||
|
||||
return super.drop( item, cell );
|
||||
}
|
||||
|
||||
private boolean outsideEntraceRoom( int cell ) {
|
||||
int cx = cell % WIDTH;
|
||||
int cy = cell / WIDTH;
|
||||
return cx < ROOM_LEFT-1 || cx > ROOM_RIGHT+1 || cy < ROOM_TOP-1 || cy > ROOM_BOTTOM+1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.GRASS:
|
||||
return "Fluorescent moss";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Fluorescent mushrooms";
|
||||
case Terrain.WATER:
|
||||
return "Freezing cold water.";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.ENTRANCE:
|
||||
return "The ladder leads up to the upper depth.";
|
||||
case Terrain.EXIT:
|
||||
return "The ladder leads down to the lower depth.";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Huge mushrooms block the view.";
|
||||
case Terrain.WALL_DECO:
|
||||
return "A vein of some ore is visible on the wall. Gold?";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
CavesLevel.addVisuals( this, scene );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.Group;
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.watabou.noosa.particles.PixelParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
import com.watabou.utils.Rect;
|
||||
|
||||
public class CavesLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
color1 = 0x534f3e;
|
||||
color2 = 0xb9d661;
|
||||
|
||||
viewDistance = 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_CAVES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_CAVES;
|
||||
}
|
||||
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( feeling == Feeling.WATER ? 0.60f : 0.45f, 6 );
|
||||
}
|
||||
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( feeling == Feeling.GRASS ? 0.55f : 0.35f, 3 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assignRoomType() {
|
||||
super.assignRoomType();
|
||||
|
||||
Blacksmith.Quest.spawn( rooms );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (Room room : rooms) {
|
||||
if (room.type != Room.Type.STANDARD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (room.width() <= 3 || room.height() <= 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int s = room.square();
|
||||
|
||||
if (Random.Int( s ) > 8) {
|
||||
int corner = (room.left + 1) + (room.top + 1) * WIDTH;
|
||||
if (map[corner - 1] == Terrain.WALL && map[corner - WIDTH] == Terrain.WALL) {
|
||||
map[corner] = Terrain.WALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (Random.Int( s ) > 8) {
|
||||
int corner = (room.right - 1) + (room.top + 1) * WIDTH;
|
||||
if (map[corner + 1] == Terrain.WALL && map[corner - WIDTH] == Terrain.WALL) {
|
||||
map[corner] = Terrain.WALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (Random.Int( s ) > 8) {
|
||||
int corner = (room.left + 1) + (room.bottom - 1) * WIDTH;
|
||||
if (map[corner - 1] == Terrain.WALL && map[corner + WIDTH] == Terrain.WALL) {
|
||||
map[corner] = Terrain.WALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (Random.Int( s ) > 8) {
|
||||
int corner = (room.right - 1) + (room.bottom - 1) * WIDTH;
|
||||
if (map[corner + 1] == Terrain.WALL && map[corner + WIDTH] == Terrain.WALL) {
|
||||
map[corner] = Terrain.WALL;
|
||||
}
|
||||
}
|
||||
|
||||
for (Room n : room.connected.keySet()) {
|
||||
if ((n.type == Room.Type.STANDARD || n.type == Room.Type.TUNNEL) && Random.Int( 3 ) == 0) {
|
||||
Painter.set( this, room.connected.get( n ), Terrain.EMPTY_DECO );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=WIDTH + 1; i < LENGTH - WIDTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY) {
|
||||
int n = 0;
|
||||
if (map[i+1] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (map[i-1] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (map[i+WIDTH] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (map[i-WIDTH] == Terrain.WALL) {
|
||||
n++;
|
||||
}
|
||||
if (Random.Int( 6 ) <= n) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.WALL && Random.Int( 12 ) == 0) {
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Dungeon.bossLevel( Dungeon.depth + 1 )) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.STANDARD) {
|
||||
for (Room n : r.neigbours) {
|
||||
if (n.type == Type.STANDARD && !r.connected.containsKey( n )/* && Random.Int( 2 ) == 0*/) {
|
||||
Rect w = r.intersect( n );
|
||||
if (w.left == w.right && w.bottom - w.top >= 5) {
|
||||
|
||||
w.top += 2;
|
||||
w.bottom -= 1;
|
||||
|
||||
w.right++;
|
||||
|
||||
Painter.fill( this, w.left, w.top, 1, w.height(), Terrain.CHASM );
|
||||
|
||||
} else if (w.top == w.bottom && w.right - w.left >= 5) {
|
||||
|
||||
w.left += 2;
|
||||
w.right -= 1;
|
||||
|
||||
w.bottom++;
|
||||
|
||||
Painter.fill( this, w.left, w.top, w.width(), 1, Terrain.CHASM );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.GRASS:
|
||||
return "Fluorescent moss";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Fluorescent mushrooms";
|
||||
case Terrain.WATER:
|
||||
return "Freezing cold water.";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.ENTRANCE:
|
||||
return "The ladder leads up to the upper depth.";
|
||||
case Terrain.EXIT:
|
||||
return "The ladder leads down to the lower depth.";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Huge mushrooms block the view.";
|
||||
case Terrain.WALL_DECO:
|
||||
return "A vein of some ore is visible on the wall. Gold?";
|
||||
case Terrain.BOOKSHELF:
|
||||
return "Who would need a bookshelf in a cave?";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
super.addVisuals( scene );
|
||||
addVisuals( this, scene );
|
||||
}
|
||||
|
||||
public static void addVisuals( Level level, Scene scene ) {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (level.map[i] == Terrain.WALL_DECO) {
|
||||
scene.add( new Vein( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Vein extends Group {
|
||||
|
||||
private int pos;
|
||||
|
||||
private float delay;
|
||||
|
||||
public Vein( int pos ) {
|
||||
super();
|
||||
|
||||
this.pos = pos;
|
||||
|
||||
delay = Random.Float( 2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
|
||||
if (visible = Dungeon.visible[pos]) {
|
||||
|
||||
super.update();
|
||||
|
||||
if ((delay -= Game.elapsed) <= 0) {
|
||||
|
||||
delay = Random.Float();
|
||||
|
||||
PointF p = DungeonTilemap.tileToWorld( pos );
|
||||
((Sparkle)recycle( Sparkle.class )).reset(
|
||||
p.x + Random.Float( DungeonTilemap.SIZE ),
|
||||
p.y + Random.Float( DungeonTilemap.SIZE ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Sparkle extends PixelParticle {
|
||||
|
||||
public void reset( float x, float y ) {
|
||||
revive();
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
left = lifespan = 0.5f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
|
||||
float p = left / lifespan;
|
||||
size( (am = p < 0.5f ? p * 2 : (1 - p) * 2) * 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class CityBossLevel extends Level {
|
||||
|
||||
{
|
||||
color1 = 0x4b6636;
|
||||
color2 = 0xf2f2f2;
|
||||
}
|
||||
|
||||
private static final int TOP = 2;
|
||||
private static final int HALL_WIDTH = 7;
|
||||
private static final int HALL_HEIGHT = 15;
|
||||
private static final int CHAMBER_HEIGHT = 3;
|
||||
|
||||
private static final int LEFT = (WIDTH - HALL_WIDTH) / 2;
|
||||
private static final int CENTER = LEFT + HALL_WIDTH / 2;
|
||||
|
||||
private int arenaDoor;
|
||||
private boolean enteredArena = false;
|
||||
private boolean keyDropped = false;
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_CITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_CITY;
|
||||
}
|
||||
|
||||
private static final String DOOR = "door";
|
||||
private static final String ENTERED = "entered";
|
||||
private static final String DROPPED = "droppped";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( DOOR, arenaDoor );
|
||||
bundle.put( ENTERED, enteredArena );
|
||||
bundle.put( DROPPED, keyDropped );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
arenaDoor = bundle.getInt( DOOR );
|
||||
enteredArena = bundle.getBoolean( ENTERED );
|
||||
keyDropped = bundle.getBoolean( DROPPED );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
Painter.fill( this, LEFT, TOP, HALL_WIDTH, HALL_HEIGHT, Terrain.EMPTY );
|
||||
Painter.fill( this, CENTER, TOP, 1, HALL_HEIGHT, Terrain.EMPTY_SP );
|
||||
|
||||
int y = TOP + 1;
|
||||
while (y < TOP + HALL_HEIGHT) {
|
||||
map[y * WIDTH + CENTER - 2] = Terrain.STATUE_SP;
|
||||
map[y * WIDTH + CENTER + 2] = Terrain.STATUE_SP;
|
||||
y += 2;
|
||||
}
|
||||
|
||||
int left = pedestal( true );
|
||||
int right = pedestal( false );
|
||||
map[left] = map[right] = Terrain.PEDESTAL;
|
||||
for (int i=left+1; i < right; i++) {
|
||||
map[i] = Terrain.EMPTY_SP;
|
||||
}
|
||||
|
||||
exit = (TOP - 1) * WIDTH + CENTER;
|
||||
map[exit] = Terrain.LOCKED_EXIT;
|
||||
|
||||
arenaDoor = (TOP + HALL_HEIGHT) * WIDTH + CENTER;
|
||||
map[arenaDoor] = Terrain.DOOR;
|
||||
|
||||
Painter.fill( this, LEFT, TOP + HALL_HEIGHT + 1, HALL_WIDTH, CHAMBER_HEIGHT, Terrain.EMPTY );
|
||||
Painter.fill( this, LEFT, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, Terrain.BOOKSHELF );
|
||||
Painter.fill( this, LEFT + HALL_WIDTH - 1, TOP + HALL_HEIGHT + 1, 1, CHAMBER_HEIGHT, Terrain.BOOKSHELF );
|
||||
|
||||
entrance = (TOP + HALL_HEIGHT + 2 + Random.Int( CHAMBER_HEIGHT - 1 )) * WIDTH + LEFT + (/*1 +*/ Random.Int( HALL_WIDTH-2 ));
|
||||
map[entrance] = Terrain.ENTRANCE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && Random.Int( 10 ) == 0) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
} else if (map[i] == Terrain.WALL && Random.Int( 8 ) == 0) {
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
int sign = arenaDoor + WIDTH + 1;
|
||||
map[sign] = Terrain.SIGN;
|
||||
}
|
||||
|
||||
public static int pedestal( boolean left ) {
|
||||
if (left) {
|
||||
return (TOP + HALL_HEIGHT / 2) * WIDTH + CENTER - 2;
|
||||
} else {
|
||||
return (TOP + HALL_HEIGHT / 2) * WIDTH + CENTER + 2;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
}
|
||||
|
||||
public Actor respawner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
Item item = Bones.get();
|
||||
if (item != null) {
|
||||
int pos;
|
||||
do {
|
||||
pos =
|
||||
Random.IntRange( LEFT + 1, LEFT + HALL_WIDTH - 2 ) +
|
||||
Random.IntRange( TOP + HALL_HEIGHT + 1, TOP + HALL_HEIGHT + CHAMBER_HEIGHT ) * WIDTH;
|
||||
} while (pos == entrance || map[pos] == Terrain.SIGN);
|
||||
drop( item, pos ).type = Heap.Type.SKELETON;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void press( int cell, Char hero ) {
|
||||
|
||||
super.press( cell, hero );
|
||||
|
||||
if (!enteredArena && outsideEntraceRoom( cell ) && hero == Dungeon.hero) {
|
||||
|
||||
enteredArena = true;
|
||||
|
||||
Mob boss = Bestiary.mob( Dungeon.depth );
|
||||
boss.state = Mob.State.HUNTING;
|
||||
do {
|
||||
boss.pos = Random.Int( LENGTH );
|
||||
} while (
|
||||
!passable[boss.pos] ||
|
||||
!outsideEntraceRoom( boss.pos ) ||
|
||||
Dungeon.visible[boss.pos]);
|
||||
GameScene.add( boss );
|
||||
|
||||
set( arenaDoor, Terrain.LOCKED_DOOR );
|
||||
GameScene.updateMap( arenaDoor );
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Heap drop( Item item, int cell ) {
|
||||
|
||||
if (!keyDropped && item instanceof SkeletonKey) {
|
||||
|
||||
keyDropped = true;
|
||||
|
||||
set( arenaDoor, Terrain.DOOR );
|
||||
GameScene.updateMap( arenaDoor );
|
||||
Dungeon.observe();
|
||||
}
|
||||
|
||||
return super.drop( item, cell );
|
||||
}
|
||||
|
||||
private boolean outsideEntraceRoom( int cell ) {
|
||||
return cell / WIDTH < arenaDoor / WIDTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Suspiciously colored water";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "High blooming flowers";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.ENTRANCE:
|
||||
return "A ramp leads up to the upper depth.";
|
||||
case Terrain.EXIT:
|
||||
return "A ramp leads down to the lower depth.";
|
||||
case Terrain.WALL_DECO:
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Several tiles are missing here.";
|
||||
case Terrain.EMPTY_SP:
|
||||
return "Thick carpet covers the floor.";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "The statue depicts some dwarf standing in a heroic stance.";
|
||||
case Terrain.BOOKSHELF:
|
||||
return "The rows of books on different disciplines fill the bookshelf.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
CityLevel.addVisuals( this, scene );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.watabou.noosa.particles.Emitter;
|
||||
import com.watabou.noosa.particles.PixelParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class CityLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
color1 = 0x4b6636;
|
||||
color2 = 0xf2f2f2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_CITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_CITY;
|
||||
}
|
||||
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( feeling == Feeling.WATER ? 0.65f : 0.45f, 4 );
|
||||
}
|
||||
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( feeling == Feeling.GRASS ? 0.60f : 0.40f, 3 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assignRoomType() {
|
||||
super.assignRoomType();
|
||||
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.TUNNEL) {
|
||||
r.type = Type.PASSAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && Random.Int( 10 ) == 0) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
} else if (map[i] == Terrain.WALL && Random.Int( 8 ) == 0) {
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
super.createItems();
|
||||
|
||||
Imp.Quest.spawn( this, roomEntrance );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Suspiciously colored water";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "High blooming flowers";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.ENTRANCE:
|
||||
return "A ramp leads up to the upper depth.";
|
||||
case Terrain.EXIT:
|
||||
return "A ramp leads down to the lower depth.";
|
||||
case Terrain.WALL_DECO:
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Several tiles are missing here.";
|
||||
case Terrain.EMPTY_SP:
|
||||
return "Thick carpet covers the floor.";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "The statue depicts some dwarf standing in a heroic stance.";
|
||||
case Terrain.BOOKSHELF:
|
||||
return "The rows of books on different disciplines fill the bookshelf.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
super.addVisuals( scene );
|
||||
addVisuals( this, scene );
|
||||
}
|
||||
|
||||
public static void addVisuals( Level level, Scene scene ) {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (level.map[i] == Terrain.WALL_DECO) {
|
||||
scene.add( new Smoke( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Smoke extends Emitter {
|
||||
|
||||
private int pos;
|
||||
|
||||
private static final Emitter.Factory factory = new Factory() {
|
||||
|
||||
@Override
|
||||
public void emit( Emitter emitter, int index, float x, float y ) {
|
||||
SmokeParticle p = (SmokeParticle)emitter.recycle( SmokeParticle.class );
|
||||
p.reset( x, y );
|
||||
}
|
||||
};
|
||||
|
||||
public Smoke( int pos ) {
|
||||
super();
|
||||
|
||||
this.pos = pos;
|
||||
|
||||
PointF p = DungeonTilemap.tileCenterToWorld( pos );
|
||||
pos( p.x - 4, p.y - 2, 4, 0 );
|
||||
|
||||
pour( factory, 0.2f );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
if (visible = Dungeon.visible[pos]) {
|
||||
super.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class SmokeParticle extends PixelParticle {
|
||||
|
||||
public SmokeParticle() {
|
||||
super();
|
||||
|
||||
color( 0x000000 );
|
||||
speed.set( Random.Float( 8 ), -Random.Float( 8 ) );
|
||||
}
|
||||
|
||||
public void reset( float x, float y ) {
|
||||
revive();
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
left = lifespan = 2f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
float p = left / lifespan;
|
||||
am = p > 0.8f ? 1 - p : p * 0.25f;
|
||||
size( 8 - p * 4 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class DeadEndLevel extends Level {
|
||||
|
||||
private static final int SIZE = 5;
|
||||
|
||||
{
|
||||
color1 = 0x534f3e;
|
||||
color2 = 0xb9d661;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_CAVES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_HALLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
Arrays.fill( map, Terrain.WALL );
|
||||
|
||||
for (int i=2; i < SIZE; i++) {
|
||||
for (int j=2; j < SIZE; j++) {
|
||||
map[i * WIDTH + j] = Terrain.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=1; i <= SIZE; i++) {
|
||||
map[WIDTH + i] =
|
||||
map[WIDTH * SIZE + i] =
|
||||
map[WIDTH * i + 1] =
|
||||
map[WIDTH * i + SIZE] =
|
||||
Terrain.WATER;
|
||||
}
|
||||
|
||||
entrance = SIZE * WIDTH + SIZE / 2 + 1;
|
||||
map[entrance] = Terrain.ENTRANCE;
|
||||
|
||||
exit = -1;
|
||||
|
||||
map[(SIZE / 2 + 1) * (WIDTH + 1)] = Terrain.SIGN;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && Random.Int( 10 ) == 0) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
} else if (map[i] == Terrain.WALL && Random.Int( 8 ) == 0) {
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Yog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class HallsBossLevel extends Level {
|
||||
|
||||
{
|
||||
color1 = 0x801500;
|
||||
color2 = 0xa68521;
|
||||
|
||||
viewDistance = 3;
|
||||
}
|
||||
|
||||
private static final int ROOM_LEFT = WIDTH / 2 - 1;
|
||||
private static final int ROOM_RIGHT = WIDTH / 2 + 1;
|
||||
private static final int ROOM_TOP = HEIGHT / 2 - 1;
|
||||
private static final int ROOM_BOTTOM = HEIGHT / 2 + 1;
|
||||
|
||||
private int stairs = -1;
|
||||
private boolean enteredArena = false;
|
||||
private boolean keyDropped = false;
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_HALLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_HALLS;
|
||||
}
|
||||
|
||||
private static final String STAIRS = "stairs";
|
||||
private static final String ENTERED = "entered";
|
||||
private static final String DROPPED = "droppped";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( STAIRS, stairs );
|
||||
bundle.put( ENTERED, enteredArena );
|
||||
bundle.put( DROPPED, keyDropped );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
stairs = bundle.getInt( STAIRS );
|
||||
enteredArena = bundle.getBoolean( ENTERED );
|
||||
keyDropped = bundle.getBoolean( DROPPED );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
for (int i=0; i < 5; i++) {
|
||||
|
||||
int top = Random.IntRange( 2, ROOM_TOP - 1 );
|
||||
int bottom = Random.IntRange( ROOM_BOTTOM + 1, 22 );
|
||||
Painter.fill( this, 2 + i * 4, top, 4, bottom - top + 1, Terrain.EMPTY );
|
||||
|
||||
if (i == 2) {
|
||||
exit = (i * 4 + 3) + (top - 1) * WIDTH ;
|
||||
}
|
||||
|
||||
for (int j=0; j < 4; j++) {
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
int y = Random.IntRange( top + 1, bottom - 1 );
|
||||
map[i*4+j + y*WIDTH] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map[exit] = Terrain.LOCKED_EXIT;
|
||||
|
||||
Painter.fill( this, ROOM_LEFT - 1, ROOM_TOP - 1,
|
||||
ROOM_RIGHT - ROOM_LEFT + 3, ROOM_BOTTOM - ROOM_TOP + 3, Terrain.WALL );
|
||||
Painter.fill( this, ROOM_LEFT, ROOM_TOP,
|
||||
ROOM_RIGHT - ROOM_LEFT + 1, ROOM_BOTTOM - ROOM_TOP + 1, Terrain.EMPTY );
|
||||
|
||||
entrance = Random.Int( ROOM_LEFT + 1, ROOM_RIGHT - 1 ) +
|
||||
Random.Int( ROOM_TOP + 1, ROOM_BOTTOM - 1 ) * WIDTH;
|
||||
map[entrance] = Terrain.ENTRANCE;
|
||||
|
||||
boolean[] patch = Patch.generate( 0.45f, 6 );
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && patch[i]) {
|
||||
map[i] = Terrain.WATER;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && Random.Int( 10 ) == 0) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
}
|
||||
|
||||
public Actor respawner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
Item item = Bones.get();
|
||||
if (item != null) {
|
||||
int pos;
|
||||
do {
|
||||
pos = Random.IntRange( ROOM_LEFT, ROOM_RIGHT ) + Random.IntRange( ROOM_TOP + 1, ROOM_BOTTOM ) * WIDTH;
|
||||
} while (pos == entrance || map[pos] == Terrain.SIGN);
|
||||
drop( item, pos ).type = Heap.Type.SKELETON;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void press( int cell, Char hero ) {
|
||||
|
||||
super.press( cell, hero );
|
||||
|
||||
if (!enteredArena && hero == Dungeon.hero && cell != entrance) {
|
||||
|
||||
enteredArena = true;
|
||||
|
||||
for (int i=ROOM_LEFT-1; i <= ROOM_RIGHT + 1; i++) {
|
||||
doMagic( (ROOM_TOP - 1) * WIDTH + i );
|
||||
doMagic( (ROOM_BOTTOM + 1) * WIDTH + i );
|
||||
}
|
||||
for (int i=ROOM_TOP; i < ROOM_BOTTOM + 1; i++) {
|
||||
doMagic( i * WIDTH + ROOM_LEFT - 1 );
|
||||
doMagic( i * WIDTH + ROOM_RIGHT + 1 );
|
||||
}
|
||||
doMagic( entrance );
|
||||
GameScene.updateMap();
|
||||
|
||||
Dungeon.observe();
|
||||
|
||||
Yog boss = new Yog();
|
||||
do {
|
||||
boss.pos = Random.Int( LENGTH );
|
||||
} while (
|
||||
!passable[boss.pos] ||
|
||||
Dungeon.visible[boss.pos]);
|
||||
GameScene.add( boss );
|
||||
boss.spawnFists();
|
||||
|
||||
stairs = entrance;
|
||||
entrance = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void doMagic( int cell ) {
|
||||
set( cell, Terrain.EMPTY_SP );
|
||||
CellEmitter.get( cell ).start( FlameParticle.FACTORY, 0.1f, 3 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Heap drop( Item item, int cell ) {
|
||||
|
||||
if (!keyDropped && item instanceof SkeletonKey) {
|
||||
keyDropped = true;
|
||||
|
||||
entrance = stairs;
|
||||
set( entrance, Terrain.ENTRANCE );
|
||||
GameScene.updateMap( entrance );
|
||||
}
|
||||
|
||||
return super.drop( item, cell );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Cold lava";
|
||||
case Terrain.GRASS:
|
||||
return "Embermoss";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Emberfungi";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "Pillar";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "It looks like lava, but it's cold and probably safe to touch.";
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Candles on the floor are probably remains of some ritual that took place here.";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "The pillar is made of real humanoid skulls. Awesome.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
HallsLevel.addVisuals( this, scene );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import javax.microedition.khronos.opengles.GL10;
|
||||
|
||||
import android.opengl.GLES20;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.Group;
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.watabou.noosa.particles.PixelParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Torch;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class HallsLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
minRoomSize = 6;
|
||||
|
||||
viewDistance = Math.max( 25 - Dungeon.depth, 1 );
|
||||
|
||||
color1 = 0x801500;
|
||||
color2 = 0xa68521;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
addItemToSpawn( new Torch() );
|
||||
super.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_HALLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_HALLS;
|
||||
}
|
||||
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( feeling == Feeling.WATER ? 0.55f : 0.40f, 6 );
|
||||
}
|
||||
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( feeling == Feeling.GRASS ? 0.55f : 0.30f, 3 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=WIDTH + 1; i < LENGTH - WIDTH - 1; i++) {
|
||||
if (map[i] == Terrain.EMPTY) {
|
||||
|
||||
int count = 0;
|
||||
for (int j=0; j < NEIGHBOURS8.length; j++) {
|
||||
if ((Terrain.flags[map[i + NEIGHBOURS8[j]]] & Terrain.PASSABLE) > 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (Random.Int( 80 ) < count) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
|
||||
} else
|
||||
if (map[i] == Terrain.WALL) {
|
||||
|
||||
int count = 0;
|
||||
for (int j=0; j < NEIGHBOURS4.length; j++) {
|
||||
if (map[i + NEIGHBOURS4[j]] == Terrain.WATER) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (Random.Int( 4 ) < count) {
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Cold lava";
|
||||
case Terrain.GRASS:
|
||||
return "Embermoss";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Emberfungi";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "Pillar";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "It looks like lava, but it's cold and probably safe to touch.";
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Candles on the floor are probably remains of some ritual that took place here.";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "The pillar is made of real humanoid skulls. Awesome.";
|
||||
case Terrain.BOOKSHELF:
|
||||
return "Books in ancient languages smoulder in the bookshelf.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
super.addVisuals( scene );
|
||||
addVisuals( this, scene );
|
||||
}
|
||||
|
||||
public static void addVisuals( Level level, Scene scene ) {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (level.map[i] == 63) {
|
||||
scene.add( new Stream( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Stream extends Group {
|
||||
|
||||
private int pos;
|
||||
|
||||
private float delay;
|
||||
|
||||
public Stream( int pos ) {
|
||||
super();
|
||||
|
||||
this.pos = pos;
|
||||
|
||||
delay = Random.Float( 2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
|
||||
if (visible = Dungeon.visible[pos]) {
|
||||
|
||||
super.update();
|
||||
|
||||
if ((delay -= Game.elapsed) <= 0) {
|
||||
|
||||
delay = Random.Float( 2 );
|
||||
|
||||
PointF p = DungeonTilemap.tileToWorld( pos );
|
||||
((FireParticle)recycle( FireParticle.class )).reset(
|
||||
p.x + Random.Float( DungeonTilemap.SIZE ),
|
||||
p.y + Random.Float( DungeonTilemap.SIZE ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE );
|
||||
super.draw();
|
||||
GLES20.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA );
|
||||
}
|
||||
}
|
||||
|
||||
public static class FireParticle extends PixelParticle.Shrinking {
|
||||
|
||||
public FireParticle() {
|
||||
super();
|
||||
|
||||
color( 0xEE7722 );
|
||||
lifespan = 1f;
|
||||
|
||||
acc.set( 0, +80 );
|
||||
}
|
||||
|
||||
public void reset( float x, float y ) {
|
||||
revive();
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
left = lifespan;
|
||||
|
||||
speed.set( 0, -40 );
|
||||
size = 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
super.update();
|
||||
float p = left / lifespan;
|
||||
am = p > 0.8f ? (1 - p) * 5 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Amulet;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class LastLevel extends Level {
|
||||
|
||||
private static final int SIZE = 7;
|
||||
|
||||
{
|
||||
color1 = 0x801500;
|
||||
color2 = 0xa68521;
|
||||
}
|
||||
|
||||
private int pedestal;
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_HALLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_HALLS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
Arrays.fill( map, Terrain.WALL );
|
||||
Painter.fill( this, 1, 1, SIZE, SIZE, Terrain.WATER );
|
||||
Painter.fill( this, 2, 2, SIZE-2, SIZE-2, Terrain.EMPTY );
|
||||
Painter.fill( this, SIZE/2, SIZE/2, 3, 3, Terrain.EMPTY_SP );
|
||||
|
||||
entrance = SIZE * WIDTH + SIZE / 2 + 1;
|
||||
map[entrance] = Terrain.ENTRANCE;
|
||||
|
||||
exit = entrance - WIDTH * SIZE;
|
||||
map[exit] = Terrain.LOCKED_EXIT;
|
||||
|
||||
pedestal = (SIZE / 2 + 1) * (WIDTH + 1);
|
||||
map[pedestal] = Terrain.PEDESTAL;
|
||||
map[pedestal-1] = map[pedestal+1] = Terrain.STATUE_SP;
|
||||
|
||||
feeling = Feeling.NONE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && Random.Int( 10 ) == 0) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
drop( new Amulet(), pedestal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Cold lava";
|
||||
case Terrain.GRASS:
|
||||
return "Embermoss";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Emberfungi";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "Pillar";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "It looks like lava, but it's cold and probably safe to touch.";
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Candles on the floor are probably remains of some ritual that took place here.";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "The pillar is made of real humanoid skulls. Awesome.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
HallsLevel.addVisuals( this, scene );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
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.Room.Type;
|
||||
import com.watabou.utils.Graph;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class LastShopLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
color1 = 0x4b6636;
|
||||
color2 = 0xf2f2f2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_CITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_CITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
initRooms();
|
||||
|
||||
int distance;
|
||||
int retry = 0;
|
||||
int minDistance = (int)Math.sqrt( rooms.size() );
|
||||
do {
|
||||
int innerRetry = 0;
|
||||
do {
|
||||
if (innerRetry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
roomEntrance = Random.element( rooms );
|
||||
} while (roomEntrance.width() < 4 || roomEntrance.height() < 4);
|
||||
|
||||
innerRetry = 0;
|
||||
do {
|
||||
if (innerRetry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
roomExit = Random.element( rooms );
|
||||
} while (roomExit == roomEntrance || roomExit.width() < 6 || roomExit.height() < 6 || roomExit.top == 0);
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
distance = Graph.buildPath( rooms, roomEntrance, roomExit ).size();
|
||||
|
||||
if (retry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} while (distance < minDistance);
|
||||
|
||||
roomEntrance.type = Type.ENTRANCE;
|
||||
roomExit.type = Type.EXIT;
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
List<Room> path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
|
||||
Graph.setPrice( path, roomEntrance.distance );
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
|
||||
Room room = roomEntrance;
|
||||
for (Room next : path) {
|
||||
room.connect( next );
|
||||
room = next;
|
||||
}
|
||||
|
||||
Room roomShop = null;
|
||||
int shopSquare = 0;
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.NULL && r.connected.size() > 0) {
|
||||
r.type = Type.PASSAGE;
|
||||
if (r.square() > shopSquare) {
|
||||
roomShop = r;
|
||||
shopSquare = r.square();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (roomShop == null || shopSquare < 30) {
|
||||
return false;
|
||||
} else {
|
||||
roomShop.type = Imp.Quest.isCompleted() ? Room.Type.SHOP : Room.Type.STANDARD;
|
||||
}
|
||||
|
||||
paint();
|
||||
|
||||
paintWater();
|
||||
paintGrass();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && Random.Int( 10 ) == 0) {
|
||||
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
|
||||
} else if (map[i] == Terrain.WALL && Random.Int( 8 ) == 0) {
|
||||
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
|
||||
} else if (map[i] == Terrain.SECRET_DOOR) {
|
||||
|
||||
map[i] = Terrain.DOOR;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (Imp.Quest.isCompleted()) {
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
}
|
||||
|
||||
public Actor respawner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
Item item = Bones.get();
|
||||
if (item != null) {
|
||||
int pos;
|
||||
do {
|
||||
pos = roomEntrance.random();
|
||||
} while (pos == entrance || map[pos] == Terrain.SIGN);
|
||||
drop( item, pos ).type = Heap.Type.SKELETON;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Suspiciously colored water";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "High blooming flowers";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.ENTRANCE:
|
||||
return "A ramp leads up to the upper depth.";
|
||||
case Terrain.EXIT:
|
||||
return "A ramp leads down to the Inferno.";
|
||||
case Terrain.WALL_DECO:
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Several tiles are missing here.";
|
||||
case Terrain.EMPTY_SP:
|
||||
return "Thick carpet covers the floor.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( 0.35f, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( 0.30f, 3 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
CityLevel.addVisuals( this, scene );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,975 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Statistics;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Alchemy;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WellWater;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Awareness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Blindness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.MindVision;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Shadows;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlowParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.WindParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Stylus;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfStrength;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Chasm;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.Door;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.features.HighGrass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.*;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.mechanics.ShadowCaster;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.plants.Plant;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.watabou.utils.Bundlable;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Random;
|
||||
import com.watabou.utils.SparseArray;
|
||||
|
||||
public abstract class Level implements Bundlable {
|
||||
|
||||
public static enum Feeling {
|
||||
NONE,
|
||||
CHASM,
|
||||
WATER,
|
||||
GRASS
|
||||
};
|
||||
|
||||
public static final int WIDTH = 32;
|
||||
public static final int HEIGHT = 32;
|
||||
public static final int LENGTH = WIDTH * HEIGHT;
|
||||
|
||||
public static final int[] NEIGHBOURS4 = {-WIDTH, +1, +WIDTH, -1};
|
||||
public static final int[] NEIGHBOURS8 = {+1, -1, +WIDTH, -WIDTH, +1+WIDTH, +1-WIDTH, -1+WIDTH, -1-WIDTH};
|
||||
public static final int[] NEIGHBOURS9 = {0, +1, -1, +WIDTH, -WIDTH, +1+WIDTH, +1-WIDTH, -1+WIDTH, -1-WIDTH};
|
||||
|
||||
protected static final float TIME_TO_RESPAWN = 50;
|
||||
|
||||
private static final String TXT_HIDDEN_PLATE_CLICKS = "A hidden pressure plate clicks!";
|
||||
|
||||
public static boolean resizingNeeded;
|
||||
// This one can be different from resizingNeeded if the level
|
||||
// was created in the older version of the game
|
||||
public static int loadedMapSize;
|
||||
|
||||
public int[] map;
|
||||
public boolean[] visited;
|
||||
public boolean[] mapped;
|
||||
|
||||
public int viewDistance = 8;
|
||||
|
||||
public static boolean[] fieldOfView = new boolean[LENGTH];
|
||||
|
||||
public static boolean[] passable = new boolean[LENGTH];
|
||||
public static boolean[] losBlocking = new boolean[LENGTH];
|
||||
public static boolean[] flamable = new boolean[LENGTH];
|
||||
public static boolean[] secret = new boolean[LENGTH];
|
||||
public static boolean[] solid = new boolean[LENGTH];
|
||||
public static boolean[] avoid = new boolean[LENGTH];
|
||||
public static boolean[] water = new boolean[LENGTH];
|
||||
public static boolean[] pit = new boolean[LENGTH];
|
||||
|
||||
public static boolean[] discoverable = new boolean[LENGTH];
|
||||
|
||||
public Feeling feeling = Feeling.NONE;
|
||||
|
||||
public int entrance;
|
||||
public int exit;
|
||||
|
||||
public HashSet<Mob> mobs;
|
||||
public SparseArray<Heap> heaps;
|
||||
public HashMap<Class<? extends Blob>,Blob> blobs;
|
||||
public SparseArray<Plant> plants;
|
||||
|
||||
protected ArrayList<Item> itemsToSpawn = new ArrayList<Item>();
|
||||
|
||||
public int color1 = 0x004400;
|
||||
public int color2 = 0x88CC44;
|
||||
|
||||
protected static boolean pitRoomNeeded = false;
|
||||
protected static boolean weakFloorCreated = false;
|
||||
|
||||
private static final String MAP = "map";
|
||||
private static final String VISITED = "visited";
|
||||
private static final String MAPPED = "mapped";
|
||||
private static final String ENTRANCE = "entrance";
|
||||
private static final String EXIT = "exit";
|
||||
private static final String HEAPS = "heaps";
|
||||
private static final String PLANTS = "plants";
|
||||
private static final String MOBS = "mobs";
|
||||
private static final String BLOBS = "blobs";
|
||||
|
||||
public void create() {
|
||||
|
||||
resizingNeeded = false;
|
||||
|
||||
map = new int[LENGTH];
|
||||
visited = new boolean[LENGTH];
|
||||
Arrays.fill( visited, false );
|
||||
mapped = new boolean[LENGTH];
|
||||
Arrays.fill( mapped, false );
|
||||
|
||||
mobs = new HashSet<Mob>();
|
||||
heaps = new SparseArray<Heap>();
|
||||
blobs = new HashMap<Class<? extends Blob>,Blob>();
|
||||
plants = new SparseArray<Plant>();
|
||||
|
||||
if (!Dungeon.bossLevel()) {
|
||||
addItemToSpawn( Generator.random( Generator.Category.FOOD ) );
|
||||
if (Dungeon.posNeeded()) {
|
||||
addItemToSpawn( new PotionOfStrength() );
|
||||
Dungeon.potionOfStrength++;
|
||||
}
|
||||
if (Dungeon.soeNeeded()) {
|
||||
addItemToSpawn( new ScrollOfUpgrade() );
|
||||
Dungeon.scrollsOfUpgrade++;
|
||||
}
|
||||
if (Dungeon.asNeeded()) {
|
||||
addItemToSpawn( new Stylus() );
|
||||
Dungeon.arcaneStyli++;
|
||||
}
|
||||
|
||||
if (Dungeon.depth > 1) {
|
||||
switch (Random.Int( 10 )) {
|
||||
case 0:
|
||||
if (!Dungeon.bossLevel( Dungeon.depth + 1 )) {
|
||||
feeling = Feeling.CHASM;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
feeling = Feeling.WATER;
|
||||
break;
|
||||
case 2:
|
||||
feeling = Feeling.GRASS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean pitNeeded = Dungeon.depth > 1 && weakFloorCreated;
|
||||
|
||||
do {
|
||||
Arrays.fill( map, feeling == Feeling.CHASM ? Terrain.CHASM : Terrain.WALL );
|
||||
|
||||
pitRoomNeeded = pitNeeded;
|
||||
weakFloorCreated = false;
|
||||
|
||||
} while (!build());
|
||||
decorate();
|
||||
|
||||
buildFlagMaps();
|
||||
cleanWalls();
|
||||
|
||||
createMobs();
|
||||
createItems();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
|
||||
for (Mob mob : mobs.toArray( new Mob[0] )) {
|
||||
if (!mob.reset()) {
|
||||
mobs.remove( mob );
|
||||
}
|
||||
}
|
||||
createMobs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
|
||||
mobs = new HashSet<Mob>();
|
||||
heaps = new SparseArray<Heap>();
|
||||
blobs = new HashMap<Class<? extends Blob>, Blob>();
|
||||
plants = new SparseArray<Plant>();
|
||||
|
||||
map = bundle.getIntArray( MAP );
|
||||
visited = bundle.getBooleanArray( VISITED );
|
||||
mapped = bundle.getBooleanArray( MAPPED );
|
||||
|
||||
entrance = bundle.getInt( ENTRANCE );
|
||||
exit = bundle.getInt( EXIT );
|
||||
|
||||
weakFloorCreated = false;
|
||||
|
||||
adjustMapSize();
|
||||
|
||||
Collection<Bundlable> collection = bundle.getCollection( HEAPS );
|
||||
for (Bundlable h : collection) {
|
||||
Heap heap = (Heap)h;
|
||||
if (resizingNeeded) {
|
||||
heap.pos = adjustPos( heap.pos );
|
||||
}
|
||||
heaps.put( heap.pos, heap );
|
||||
}
|
||||
|
||||
collection = bundle.getCollection( PLANTS );
|
||||
for (Bundlable p : collection) {
|
||||
Plant plant = (Plant)p;
|
||||
if (resizingNeeded) {
|
||||
plant.pos = adjustPos( plant.pos );
|
||||
}
|
||||
plants.put( plant.pos, plant );
|
||||
}
|
||||
|
||||
collection = bundle.getCollection( MOBS );
|
||||
for (Bundlable m : collection) {
|
||||
Mob mob = (Mob)m;
|
||||
if (mob != null) {
|
||||
if (resizingNeeded) {
|
||||
mob.pos = adjustPos( mob.pos );
|
||||
}
|
||||
mobs.add( mob );
|
||||
}
|
||||
}
|
||||
|
||||
collection = bundle.getCollection( BLOBS );
|
||||
for (Bundlable b : collection) {
|
||||
Blob blob = (Blob)b;
|
||||
blobs.put( blob.getClass(), blob );
|
||||
}
|
||||
|
||||
buildFlagMaps();
|
||||
cleanWalls();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( MAP, map );
|
||||
bundle.put( VISITED, visited );
|
||||
bundle.put( MAPPED, mapped );
|
||||
bundle.put( ENTRANCE, entrance );
|
||||
bundle.put( EXIT, exit );
|
||||
bundle.put( HEAPS, heaps.values() );
|
||||
bundle.put( PLANTS, plants.values() );
|
||||
bundle.put( MOBS, mobs );
|
||||
bundle.put( BLOBS, blobs.values() );
|
||||
}
|
||||
|
||||
public int tunnelTile() {
|
||||
return feeling == Feeling.CHASM ? Terrain.EMPTY_SP : Terrain.EMPTY;
|
||||
}
|
||||
|
||||
private void adjustMapSize() {
|
||||
// For levels from older saves
|
||||
if (map.length < LENGTH) {
|
||||
|
||||
resizingNeeded = true;
|
||||
loadedMapSize = (int)Math.sqrt( map.length );
|
||||
|
||||
int[] map = new int[LENGTH];
|
||||
Arrays.fill( map, Terrain.WALL );
|
||||
|
||||
boolean[] visited = new boolean[LENGTH];
|
||||
Arrays.fill( visited, false );
|
||||
|
||||
boolean[] mapped = new boolean[LENGTH];
|
||||
Arrays.fill( mapped, false );
|
||||
|
||||
for (int i=0; i < loadedMapSize; i++) {
|
||||
System.arraycopy( this.map, i * loadedMapSize, map, i * WIDTH, loadedMapSize );
|
||||
System.arraycopy( this.visited, i * loadedMapSize, visited, i * WIDTH, loadedMapSize );
|
||||
System.arraycopy( this.mapped, i * loadedMapSize, mapped, i * WIDTH, loadedMapSize );
|
||||
}
|
||||
|
||||
this.map = map;
|
||||
this.visited = visited;
|
||||
this.mapped = mapped;
|
||||
|
||||
entrance = adjustPos( entrance );
|
||||
exit = adjustPos( exit );
|
||||
} else {
|
||||
resizingNeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
public int adjustPos( int pos ) {
|
||||
return (pos / loadedMapSize) * WIDTH + (pos % loadedMapSize);
|
||||
}
|
||||
|
||||
public String tilesTex() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String waterTex() {
|
||||
return null;
|
||||
}
|
||||
|
||||
abstract protected boolean build();
|
||||
abstract protected void decorate();
|
||||
abstract protected void createMobs();
|
||||
abstract protected void createItems();
|
||||
|
||||
public void addVisuals( Scene scene ) {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (pit[i]) {
|
||||
scene.add( new WindParticle.Wind( i ) );
|
||||
if (i >= WIDTH && water[i-WIDTH]) {
|
||||
scene.add( new FlowParticle.Flow( i - WIDTH ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int nMobs() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Actor respawner() {
|
||||
return new Actor() {
|
||||
@Override
|
||||
protected boolean act() {
|
||||
if (mobs.size() < nMobs()) {
|
||||
|
||||
Mob mob = Bestiary.mutable( Dungeon.depth );
|
||||
mob.state = Mob.State.WANDERING;
|
||||
mob.pos = randomRespawnCell();
|
||||
if (Dungeon.hero.isAlive() && mob.pos != -1) {
|
||||
GameScene.add( mob );
|
||||
if (Statistics.amuletObtained) {
|
||||
mob.beckon( Dungeon.hero.pos );
|
||||
}
|
||||
}
|
||||
}
|
||||
spend( Dungeon.nightMode || Statistics.amuletObtained ? TIME_TO_RESPAWN / 2 : TIME_TO_RESPAWN );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int randomRespawnCell() {
|
||||
int cell;
|
||||
do {
|
||||
cell = Random.Int( LENGTH );
|
||||
} while (!passable[cell] || Dungeon.visible[cell] || Actor.findChar( cell ) != null);
|
||||
return cell;
|
||||
}
|
||||
|
||||
public int randomDestination() {
|
||||
int cell;
|
||||
do {
|
||||
cell = Random.Int( LENGTH );
|
||||
} while (!passable[cell]);
|
||||
return cell;
|
||||
}
|
||||
|
||||
public void addItemToSpawn( Item item ) {
|
||||
if (item != null) {
|
||||
itemsToSpawn.add( item );
|
||||
}
|
||||
}
|
||||
|
||||
public Item itemToSpanAsPrize() {
|
||||
if (Random.Int( itemsToSpawn.size() + 1 ) > 0) {
|
||||
Item item = Random.element( itemsToSpawn );
|
||||
itemsToSpawn.remove( item );
|
||||
return item;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void buildFlagMaps() {
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
int flags = Terrain.flags[map[i]];
|
||||
passable[i] = (flags & Terrain.PASSABLE) != 0;
|
||||
losBlocking[i] = (flags & Terrain.LOS_BLOCKING) != 0;
|
||||
flamable[i] = (flags & Terrain.FLAMABLE) != 0;
|
||||
secret[i] = (flags & Terrain.SECRET) != 0;
|
||||
solid[i] = (flags & Terrain.SOLID) != 0;
|
||||
avoid[i] = (flags & Terrain.AVOID) != 0;
|
||||
water[i] = (flags & Terrain.LIQUID) != 0;
|
||||
pit[i] = (flags & Terrain.PIT) != 0;
|
||||
}
|
||||
|
||||
int lastRow = LENGTH - WIDTH;
|
||||
for (int i=0; i < WIDTH; i++) {
|
||||
passable[i] = avoid[i] = false;
|
||||
passable[lastRow + i] = avoid[lastRow + i] = false;
|
||||
}
|
||||
for (int i=WIDTH; i < lastRow; i += WIDTH) {
|
||||
passable[i] = avoid[i] = false;
|
||||
passable[i + WIDTH-1] = avoid[i + WIDTH-1] = false;
|
||||
}
|
||||
|
||||
for (int i=WIDTH; i < LENGTH - WIDTH; i++) {
|
||||
|
||||
if (water[i]) {
|
||||
int t = Terrain.WATER_TILES;
|
||||
for (int j=0; j < NEIGHBOURS4.length; j++) {
|
||||
if ((Terrain.flags[map[i + NEIGHBOURS4[j]]] & Terrain.UNSTITCHABLE) != 0) {
|
||||
t += 1 << j;
|
||||
}
|
||||
}
|
||||
map[i] = t;
|
||||
}
|
||||
|
||||
if (pit[i]) {
|
||||
if (!pit[i - WIDTH]) {
|
||||
int c = map[i - WIDTH];
|
||||
if (c == Terrain.EMPTY_SP || c == Terrain.STATUE_SP) {
|
||||
map[i] = Terrain.CHASM_FLOOR_SP;
|
||||
} else if (water[i - WIDTH]) {
|
||||
map[i] = Terrain.CHASM_WATER;
|
||||
} else if ((Terrain.flags[c] & Terrain.UNSTITCHABLE) != 0) {
|
||||
map[i] = Terrain.CHASM_WALL;
|
||||
} else {
|
||||
map[i] = Terrain.CHASM_FLOOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanWalls() {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
|
||||
boolean d = false;
|
||||
|
||||
for (int j=0; j < NEIGHBOURS9.length; j++) {
|
||||
int n = i + NEIGHBOURS9[j];
|
||||
if (n >= 0 && n < LENGTH && map[n] != Terrain.WALL && map[n] != Terrain.WALL_DECO) {
|
||||
d = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (d) {
|
||||
d = false;
|
||||
|
||||
for (int j=0; j < NEIGHBOURS9.length; j++) {
|
||||
int n = i + NEIGHBOURS9[j];
|
||||
if (n >= 0 && n < LENGTH && !pit[n]) {
|
||||
d = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
discoverable[i] = d;
|
||||
}
|
||||
}
|
||||
|
||||
public static void set( int cell, int terrain ) {
|
||||
Painter.set( Dungeon.level, cell, terrain );
|
||||
|
||||
int flags = Terrain.flags[terrain];
|
||||
passable[cell] = (flags & Terrain.PASSABLE) != 0;
|
||||
losBlocking[cell] = (flags & Terrain.LOS_BLOCKING) != 0;
|
||||
flamable[cell] = (flags & Terrain.FLAMABLE) != 0;
|
||||
secret[cell] = (flags & Terrain.SECRET) != 0;
|
||||
solid[cell] = (flags & Terrain.SOLID) != 0;
|
||||
avoid[cell] = (flags & Terrain.AVOID) != 0;
|
||||
pit[cell] = (flags & Terrain.PIT) != 0;
|
||||
water[cell] = terrain == Terrain.WATER || terrain >= Terrain.WATER_TILES;
|
||||
}
|
||||
|
||||
public Heap drop( Item item, int cell ) {
|
||||
|
||||
if ((map[cell] == Terrain.ALCHEMY) && !(item instanceof Plant.Seed)) {
|
||||
int n;
|
||||
do {
|
||||
n = cell + NEIGHBOURS8[Random.Int( 8 )];
|
||||
} while (map[n] != Terrain.EMPTY_SP);
|
||||
cell = n;
|
||||
}
|
||||
|
||||
Heap heap = heaps.get( cell );
|
||||
if (heap == null) {
|
||||
|
||||
heap = new Heap();
|
||||
heap.pos = cell;
|
||||
if (map[cell] == Terrain.CHASM || (Dungeon.level != null && pit[cell])) {
|
||||
GameScene.discard( heap );
|
||||
} else {
|
||||
heaps.put( cell, heap );
|
||||
GameScene.add( heap );
|
||||
}
|
||||
|
||||
} else if (heap.type == Heap.Type.LOCKED_CHEST || heap.type == Heap.Type.CRYSTAL_CHEST) {
|
||||
|
||||
int n;
|
||||
do {
|
||||
n = cell + Level.NEIGHBOURS8[Random.Int( 8 )];
|
||||
} while (!Level.passable[n] && !Level.avoid[n]);
|
||||
return drop( item, n );
|
||||
|
||||
}
|
||||
heap.drop( item );
|
||||
|
||||
if (Dungeon.level != null) {
|
||||
press( cell, null );
|
||||
}
|
||||
|
||||
return heap;
|
||||
}
|
||||
|
||||
public Plant plant( Plant.Seed seed, int pos ) {
|
||||
|
||||
Plant plant = plants.get( pos );
|
||||
if (plant != null) {
|
||||
plant.wither();
|
||||
}
|
||||
|
||||
plant = seed.couch( pos );
|
||||
plants.put( pos, plant );
|
||||
|
||||
GameScene.add( plant );
|
||||
|
||||
return plant;
|
||||
}
|
||||
|
||||
public void uproot( int pos ) {
|
||||
plants.delete( pos );
|
||||
}
|
||||
|
||||
public int pitCell() {
|
||||
return randomRespawnCell();
|
||||
}
|
||||
|
||||
public void press( int cell, Char ch ) {
|
||||
|
||||
if (pit[cell] && ch == Dungeon.hero) {
|
||||
Chasm.heroFall( cell );
|
||||
return;
|
||||
}
|
||||
|
||||
boolean trap = false;
|
||||
|
||||
switch (map[cell]) {
|
||||
|
||||
case Terrain.SECRET_TOXIC_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.TOXIC_TRAP:
|
||||
trap = true;
|
||||
ToxicTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.SECRET_FIRE_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.FIRE_TRAP:
|
||||
trap = true;
|
||||
FireTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.SECRET_PARALYTIC_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.PARALYTIC_TRAP:
|
||||
trap = true;
|
||||
ParalyticTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.SECRET_POISON_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.POISON_TRAP:
|
||||
trap = true;
|
||||
PoisonTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.SECRET_ALARM_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.ALARM_TRAP:
|
||||
trap = true;
|
||||
AlarmTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.SECRET_LIGHTNING_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.LIGHTNING_TRAP:
|
||||
trap = true;
|
||||
LightningTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.SECRET_GRIPPING_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.GRIPPING_TRAP:
|
||||
trap = true;
|
||||
GrippingTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.SECRET_SUMMONING_TRAP:
|
||||
GLog.i( TXT_HIDDEN_PLATE_CLICKS );
|
||||
case Terrain.SUMMONING_TRAP:
|
||||
trap = true;
|
||||
SummoningTrap.trigger( cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.HIGH_GRASS:
|
||||
HighGrass.trample( this, cell, ch );
|
||||
break;
|
||||
|
||||
case Terrain.WELL:
|
||||
WellWater.affectCell( cell );
|
||||
break;
|
||||
|
||||
case Terrain.ALCHEMY:
|
||||
if (ch == null) {
|
||||
Alchemy.transmute( cell );
|
||||
}
|
||||
break;
|
||||
|
||||
case Terrain.DOOR:
|
||||
Door.enter( cell );
|
||||
break;
|
||||
}
|
||||
|
||||
if (trap) {
|
||||
Sample.INSTANCE.play( Assets.SND_TRAP );
|
||||
if (ch == Dungeon.hero) {
|
||||
Dungeon.hero.interrupt();
|
||||
}
|
||||
set( cell, Terrain.INACTIVE_TRAP );
|
||||
GameScene.updateMap( cell );
|
||||
}
|
||||
|
||||
Plant plant = plants.get( cell );
|
||||
if (plant != null) {
|
||||
plant.activate( ch );
|
||||
}
|
||||
}
|
||||
|
||||
public void mobPress( Mob mob ) {
|
||||
|
||||
int cell = mob.pos;
|
||||
|
||||
if (pit[cell] && !mob.flying) {
|
||||
Chasm.mobFall( mob );
|
||||
return;
|
||||
}
|
||||
|
||||
boolean trap = true;
|
||||
switch (map[cell]) {
|
||||
|
||||
case Terrain.TOXIC_TRAP:
|
||||
ToxicTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.FIRE_TRAP:
|
||||
FireTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.PARALYTIC_TRAP:
|
||||
ParalyticTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.POISON_TRAP:
|
||||
PoisonTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.ALARM_TRAP:
|
||||
AlarmTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.LIGHTNING_TRAP:
|
||||
LightningTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.GRIPPING_TRAP:
|
||||
GrippingTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.SUMMONING_TRAP:
|
||||
SummoningTrap.trigger( cell, mob );
|
||||
break;
|
||||
|
||||
case Terrain.DOOR:
|
||||
Door.enter( cell );
|
||||
|
||||
default:
|
||||
trap = false;
|
||||
}
|
||||
|
||||
if (trap) {
|
||||
if (Dungeon.visible[cell]) {
|
||||
Sample.INSTANCE.play( Assets.SND_TRAP );
|
||||
}
|
||||
set( cell, Terrain.INACTIVE_TRAP );
|
||||
GameScene.updateMap( cell );
|
||||
}
|
||||
|
||||
Plant plant = plants.get( cell );
|
||||
if (plant != null) {
|
||||
plant.activate( mob );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean[] updateFieldOfView( Char c ) {
|
||||
|
||||
int cx = c.pos % WIDTH;
|
||||
int cy = c.pos / WIDTH;
|
||||
|
||||
boolean sighted = c.buff( Blindness.class ) == null && c.buff( Shadows.class ) == null && c.isAlive();
|
||||
if (sighted) {
|
||||
ShadowCaster.castShadow( cx, cy, fieldOfView, c.viewDistance );
|
||||
} else {
|
||||
Arrays.fill( fieldOfView, false );
|
||||
}
|
||||
|
||||
int sense = 1;
|
||||
if (c.isAlive()) {
|
||||
for (Buff b : c.buffs( MindVision.class )) {
|
||||
sense = Math.max( ((MindVision)b).distance, sense );
|
||||
}
|
||||
}
|
||||
|
||||
if ((sighted && sense > 1) || !sighted) {
|
||||
|
||||
int ax = Math.max( 0, cx - sense );
|
||||
int bx = Math.min( cx + sense, WIDTH - 1 );
|
||||
int ay = Math.max( 0, cy - sense );
|
||||
int by = Math.min( cy + sense, HEIGHT - 1 );
|
||||
|
||||
int len = bx - ax + 1;
|
||||
int pos = ax + ay * WIDTH;
|
||||
for (int y = ay; y <= by; y++, pos+=WIDTH) {
|
||||
Arrays.fill( fieldOfView, pos, pos + len, true );
|
||||
}
|
||||
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
fieldOfView[i] &= discoverable[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (c.isAlive()) {
|
||||
if (c.buff( MindVision.class ) != null) {
|
||||
for (Mob mob : mobs) {
|
||||
int p = mob.pos;
|
||||
fieldOfView[p] = true;
|
||||
fieldOfView[p + 1] = true;
|
||||
fieldOfView[p - 1] = true;
|
||||
fieldOfView[p + WIDTH + 1] = true;
|
||||
fieldOfView[p + WIDTH - 1] = true;
|
||||
fieldOfView[p - WIDTH + 1] = true;
|
||||
fieldOfView[p - WIDTH - 1] = true;
|
||||
fieldOfView[p + WIDTH] = true;
|
||||
fieldOfView[p - WIDTH] = true;
|
||||
}
|
||||
} else if (c == Dungeon.hero && ((Hero)c).heroClass == HeroClass.HUNTRESS) {
|
||||
for (Mob mob : mobs) {
|
||||
int p = mob.pos;
|
||||
if (distance( c.pos, p) == 2) {
|
||||
fieldOfView[p] = true;
|
||||
fieldOfView[p + 1] = true;
|
||||
fieldOfView[p - 1] = true;
|
||||
fieldOfView[p + WIDTH + 1] = true;
|
||||
fieldOfView[p + WIDTH - 1] = true;
|
||||
fieldOfView[p - WIDTH + 1] = true;
|
||||
fieldOfView[p - WIDTH - 1] = true;
|
||||
fieldOfView[p + WIDTH] = true;
|
||||
fieldOfView[p - WIDTH] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (c.buff( Awareness.class ) != null) {
|
||||
|
||||
for (Heap heap : heaps.values()) {
|
||||
int p = heap.pos;
|
||||
fieldOfView[p] = true;
|
||||
fieldOfView[p + 1] = true;
|
||||
fieldOfView[p - 1] = true;
|
||||
fieldOfView[p + WIDTH + 1] = true;
|
||||
fieldOfView[p + WIDTH - 1] = true;
|
||||
fieldOfView[p - WIDTH + 1] = true;
|
||||
fieldOfView[p - WIDTH - 1] = true;
|
||||
fieldOfView[p + WIDTH] = true;
|
||||
fieldOfView[p - WIDTH] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fieldOfView;
|
||||
}
|
||||
|
||||
public static int distance( int a, int b ) {
|
||||
int ax = a % WIDTH;
|
||||
int ay = a / WIDTH;
|
||||
int bx = b % WIDTH;
|
||||
int by = b / WIDTH;
|
||||
return Math.max( Math.abs( ax - bx ), Math.abs( ay - by ) );
|
||||
}
|
||||
|
||||
public static boolean adjacent( int a, int b ) {
|
||||
int diff = Math.abs( a - b );
|
||||
return diff == 1 || diff == WIDTH || diff == WIDTH + 1 || diff == WIDTH - 1;
|
||||
}
|
||||
|
||||
public String tileName( int tile ) {
|
||||
|
||||
if (tile >= Terrain.WATER_TILES) {
|
||||
return tileName( Terrain.WATER );
|
||||
}
|
||||
|
||||
if (tile != Terrain.CHASM && (Terrain.flags[tile] & Terrain.PIT) != 0) {
|
||||
return tileName( Terrain.CHASM );
|
||||
}
|
||||
|
||||
switch (tile) {
|
||||
case Terrain.CHASM:
|
||||
return "Chasm";
|
||||
case Terrain.EMPTY:
|
||||
case Terrain.EMPTY_SP:
|
||||
case Terrain.EMPTY_DECO:
|
||||
case Terrain.SECRET_TOXIC_TRAP:
|
||||
case Terrain.SECRET_FIRE_TRAP:
|
||||
case Terrain.SECRET_PARALYTIC_TRAP:
|
||||
case Terrain.SECRET_POISON_TRAP:
|
||||
case Terrain.SECRET_ALARM_TRAP:
|
||||
case Terrain.SECRET_LIGHTNING_TRAP:
|
||||
return "Floor";
|
||||
case Terrain.GRASS:
|
||||
return "Grass";
|
||||
case Terrain.WATER:
|
||||
return "Water";
|
||||
case Terrain.WALL:
|
||||
case Terrain.WALL_DECO:
|
||||
case Terrain.SECRET_DOOR:
|
||||
return "Wall";
|
||||
case Terrain.DOOR:
|
||||
return "Closed door";
|
||||
case Terrain.OPEN_DOOR:
|
||||
return "Open door";
|
||||
case Terrain.ENTRANCE:
|
||||
return "Depth entrance";
|
||||
case Terrain.EXIT:
|
||||
return "Depth exit";
|
||||
case Terrain.EMBERS:
|
||||
return "Embers";
|
||||
case Terrain.LOCKED_DOOR:
|
||||
return "Locked door";
|
||||
case Terrain.PEDESTAL:
|
||||
return "Pedestal";
|
||||
case Terrain.BARRICADE:
|
||||
return "Barricade";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "High grass";
|
||||
case Terrain.LOCKED_EXIT:
|
||||
return "Locked depth exit";
|
||||
case Terrain.UNLOCKED_EXIT:
|
||||
return "Unlocked depth exit";
|
||||
case Terrain.SIGN:
|
||||
return "Sign";
|
||||
case Terrain.WELL:
|
||||
return "Well";
|
||||
case Terrain.EMPTY_WELL:
|
||||
return "Empty well";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "Statue";
|
||||
case Terrain.TOXIC_TRAP:
|
||||
return "Toxic gas trap";
|
||||
case Terrain.FIRE_TRAP:
|
||||
return "Fire trap";
|
||||
case Terrain.PARALYTIC_TRAP:
|
||||
return "Paralytic gas trap";
|
||||
case Terrain.POISON_TRAP:
|
||||
return "Poison dart trap";
|
||||
case Terrain.ALARM_TRAP:
|
||||
return "Alarm trap";
|
||||
case Terrain.LIGHTNING_TRAP:
|
||||
return "Lightning trap";
|
||||
case Terrain.GRIPPING_TRAP:
|
||||
return "Gripping trap";
|
||||
case Terrain.SUMMONING_TRAP:
|
||||
return "Summoning trap";
|
||||
case Terrain.INACTIVE_TRAP:
|
||||
return "Triggered trap";
|
||||
case Terrain.BOOKSHELF:
|
||||
return "Bookshelf";
|
||||
case Terrain.ALCHEMY:
|
||||
return "Alchemy pot";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
public String tileDesc( int tile ) {
|
||||
|
||||
switch (tile) {
|
||||
case Terrain.CHASM:
|
||||
return "You can't see the bottom.";
|
||||
case Terrain.WATER:
|
||||
return "In case of burning step into the water to extinguish the fire.";
|
||||
case Terrain.ENTRANCE:
|
||||
return "Stairs lead up to the upper depth.";
|
||||
case Terrain.EXIT:
|
||||
case Terrain.UNLOCKED_EXIT:
|
||||
return "Stairs lead down to the lower depth.";
|
||||
case Terrain.EMBERS:
|
||||
return "Embers cover the floor.";
|
||||
case Terrain.HIGH_GRASS:
|
||||
return "Dense vegetation blocks the view.";
|
||||
case Terrain.LOCKED_DOOR:
|
||||
return "This door is locked, you need a matching key to unlock it.";
|
||||
case Terrain.LOCKED_EXIT:
|
||||
return "Heavy bars block the stairs leading down.";
|
||||
case Terrain.BARRICADE:
|
||||
return "The wooden barricade is firmly set but has dried over the years. Might it burn?";
|
||||
case Terrain.SIGN:
|
||||
return "You can't read the text from here.";
|
||||
case Terrain.TOXIC_TRAP:
|
||||
case Terrain.FIRE_TRAP:
|
||||
case Terrain.PARALYTIC_TRAP:
|
||||
case Terrain.POISON_TRAP:
|
||||
case Terrain.ALARM_TRAP:
|
||||
case Terrain.LIGHTNING_TRAP:
|
||||
case Terrain.GRIPPING_TRAP:
|
||||
case Terrain.SUMMONING_TRAP:
|
||||
return "Stepping onto a hidden pressure plate will activate the trap.";
|
||||
case Terrain.INACTIVE_TRAP:
|
||||
return "The trap has been triggered before and it's not dangerous anymore.";
|
||||
case Terrain.STATUE:
|
||||
case Terrain.STATUE_SP:
|
||||
return "Someone wanted to adorn this place, but failed, obviously.";
|
||||
case Terrain.ALCHEMY:
|
||||
return "Drop some seeds here to cook a potion.";
|
||||
case Terrain.EMPTY_WELL:
|
||||
return "The well has run dry.";
|
||||
default:
|
||||
if (tile >= Terrain.WATER_TILES) {
|
||||
return tileDesc( Terrain.WATER );
|
||||
}
|
||||
if ((Terrain.flags[tile] & Terrain.PIT) != 0) {
|
||||
return tileDesc( Terrain.CHASM );
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Patch {
|
||||
|
||||
private static boolean[] cur = new boolean[Level.LENGTH];
|
||||
private static boolean[] off = new boolean[Level.LENGTH];
|
||||
|
||||
public static boolean[] generate( float seed, int nGen ) {
|
||||
|
||||
int w = Level.WIDTH;
|
||||
int h = Level.HEIGHT;
|
||||
|
||||
for (int i=0; i < Level.LENGTH; i++) {
|
||||
off[i] = Random.Float() < seed;
|
||||
}
|
||||
|
||||
for (int i=0; i < nGen; i++) {
|
||||
|
||||
for (int y=1; y < h-1; y++) {
|
||||
for (int x=1; x < w-1; x++) {
|
||||
|
||||
int pos = x + y * w;
|
||||
int count = 0;
|
||||
if (off[pos-w-1]) {
|
||||
count++;
|
||||
}
|
||||
if (off[pos-w]) {
|
||||
count++;
|
||||
}
|
||||
if (off[pos-w+1]) {
|
||||
count++;
|
||||
}
|
||||
if (off[pos-1]) {
|
||||
count++;
|
||||
}
|
||||
if (off[pos+1]) {
|
||||
count++;
|
||||
}
|
||||
if (off[pos+w-1]) {
|
||||
count++;
|
||||
}
|
||||
if (off[pos+w]) {
|
||||
count++;
|
||||
}
|
||||
if (off[pos+w+1]) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!off[pos] && count >= 5) {
|
||||
cur[pos] = true;
|
||||
} else if (off[pos] && count >= 4) {
|
||||
cur[pos] = true;
|
||||
} else {
|
||||
cur[pos] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean[] tmp = cur;
|
||||
cur = off;
|
||||
off = tmp;
|
||||
}
|
||||
|
||||
return off;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.SkeletonKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Graph;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class PrisonBossLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
color1 = 0x6a723d;
|
||||
color2 = 0x88924c;
|
||||
}
|
||||
|
||||
private Room anteroom;
|
||||
private int arenaDoor;
|
||||
|
||||
private boolean enteredArena = false;
|
||||
private boolean keyDropped = false;
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_PRISON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_PRISON;
|
||||
}
|
||||
|
||||
private static final String ARENA = "arena";
|
||||
private static final String DOOR = "door";
|
||||
private static final String ENTERED = "entered";
|
||||
private static final String DROPPED = "droppped";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( ARENA, roomExit );
|
||||
bundle.put( DOOR, arenaDoor );
|
||||
bundle.put( ENTERED, enteredArena );
|
||||
bundle.put( DROPPED, keyDropped );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
roomExit = (Room)bundle.get( ARENA );
|
||||
arenaDoor = bundle.getInt( DOOR );
|
||||
enteredArena = bundle.getBoolean( ENTERED );
|
||||
keyDropped = bundle.getBoolean( DROPPED );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
initRooms();
|
||||
|
||||
int distance;
|
||||
int retry = 0;
|
||||
|
||||
do {
|
||||
|
||||
if (retry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int innerRetry = 0;
|
||||
do {
|
||||
if (innerRetry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
roomEntrance = Random.element( rooms );
|
||||
} while (roomEntrance.width() < 4 || roomEntrance.height() < 4);
|
||||
|
||||
innerRetry = 0;
|
||||
do {
|
||||
if (innerRetry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
roomExit = Random.element( rooms );
|
||||
} while (
|
||||
roomExit == roomEntrance ||
|
||||
roomExit.width() < 7 ||
|
||||
roomExit.height() < 7 ||
|
||||
roomExit.top == 0);
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
distance = Graph.buildPath( rooms, roomEntrance, roomExit ).size();
|
||||
|
||||
} while (distance < 3);
|
||||
|
||||
roomEntrance.type = Type.ENTRANCE;
|
||||
roomExit.type = Type.BOSS_EXIT;
|
||||
|
||||
List<Room> path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
Graph.setPrice( path, roomEntrance.distance );
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
|
||||
anteroom = path.get( path.size() - 2 );
|
||||
anteroom.type = Type.STANDARD;
|
||||
|
||||
Room room = roomEntrance;
|
||||
for (Room next : path) {
|
||||
room.connect( next );
|
||||
room = next;
|
||||
}
|
||||
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.NULL && r.connected.size() > 0) {
|
||||
r.type = Type.PASSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
paint();
|
||||
|
||||
Room r = (Room)roomExit.connected.keySet().toArray()[0];
|
||||
if (roomExit.connected.get( r ).y == roomExit.top) {
|
||||
return false;
|
||||
}
|
||||
|
||||
paintWater();
|
||||
paintGrass();
|
||||
|
||||
placeTraps();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( 0.45f, 5 );
|
||||
}
|
||||
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( 0.30f, 4 );
|
||||
}
|
||||
|
||||
protected void paintDoors( Room r ) {
|
||||
|
||||
for (Room n : r.connected.keySet()) {
|
||||
|
||||
if (r.type == Type.NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Point door = r.connected.get( n );
|
||||
|
||||
if (r.type == Room.Type.PASSAGE && n.type == Room.Type.PASSAGE) {
|
||||
|
||||
Painter.set( this, door, Terrain.EMPTY );
|
||||
|
||||
} else {
|
||||
|
||||
Painter.set( this, door, Terrain.DOOR );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void placeTraps() {
|
||||
|
||||
int nTraps = nTraps();
|
||||
|
||||
for (int i=0; i < nTraps; i++) {
|
||||
|
||||
int trapPos = Random.Int( LENGTH );
|
||||
|
||||
if (map[trapPos] == Terrain.EMPTY) {
|
||||
map[trapPos] = Terrain.POISON_TRAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=WIDTH + 1; i < LENGTH - WIDTH - 1; i++) {
|
||||
if (map[i] == Terrain.EMPTY) {
|
||||
|
||||
float c = 0.15f;
|
||||
if (map[i + 1] == Terrain.WALL && map[i + WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
if (map[i - 1] == Terrain.WALL && map[i + WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
if (map[i + 1] == Terrain.WALL && map[i - WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
if (map[i - 1] == Terrain.WALL && map[i - WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
|
||||
if (Random.Float() < c) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < WIDTH; i++) {
|
||||
if (map[i] == Terrain.WALL &&
|
||||
(map[i + WIDTH] == Terrain.EMPTY || map[i + WIDTH] == Terrain.EMPTY_SP) &&
|
||||
Random.Int( 4 ) == 0) {
|
||||
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=WIDTH; i < LENGTH - WIDTH; i++) {
|
||||
if (map[i] == Terrain.WALL &&
|
||||
map[i - WIDTH] == Terrain.WALL &&
|
||||
(map[i + WIDTH] == Terrain.EMPTY || map[i + WIDTH] == Terrain.EMPTY_SP) &&
|
||||
Random.Int( 2 ) == 0) {
|
||||
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Point door = roomExit.entrance();
|
||||
arenaDoor = door.x + door.y * WIDTH;
|
||||
Painter.set( this, arenaDoor, Terrain.LOCKED_DOOR );
|
||||
|
||||
Painter.fill( this,
|
||||
roomExit.left + 2,
|
||||
roomExit.top + 2,
|
||||
roomExit.width() - 3,
|
||||
roomExit.height() - 3,
|
||||
Terrain.INACTIVE_TRAP );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
}
|
||||
|
||||
public Actor respawner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
|
||||
int keyPos = anteroom.random();
|
||||
while (!passable[keyPos]) {
|
||||
keyPos = anteroom.random();
|
||||
}
|
||||
drop( new IronKey( Dungeon.depth ), keyPos ).type = Heap.Type.CHEST;
|
||||
|
||||
Item item = Bones.get();
|
||||
if (item != null) {
|
||||
int pos;
|
||||
do {
|
||||
pos = roomEntrance.random();
|
||||
} while (pos == entrance || map[pos] == Terrain.SIGN);
|
||||
drop( item, pos ).type = Heap.Type.SKELETON;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void press( int cell, Char ch ) {
|
||||
|
||||
super.press( cell, ch );
|
||||
|
||||
if (ch == Dungeon.hero && !enteredArena && roomExit.inside( cell )) {
|
||||
|
||||
enteredArena = true;
|
||||
|
||||
int pos;
|
||||
do {
|
||||
pos = roomExit.random();
|
||||
} while (pos == cell || Actor.findChar( pos ) != null);
|
||||
|
||||
Mob boss = Bestiary.mob( Dungeon.depth );
|
||||
boss.state = Mob.State.HUNTING;
|
||||
boss.pos = pos;
|
||||
GameScene.add( boss );
|
||||
boss.notice();
|
||||
|
||||
mobPress( boss );
|
||||
|
||||
set( arenaDoor, Terrain.LOCKED_DOOR );
|
||||
GameScene.updateMap( arenaDoor );
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Heap drop( Item item, int cell ) {
|
||||
|
||||
if (!keyDropped && item instanceof SkeletonKey) {
|
||||
|
||||
keyDropped = true;
|
||||
|
||||
set( arenaDoor, Terrain.DOOR );
|
||||
GameScene.updateMap( arenaDoor );
|
||||
Dungeon.observe();
|
||||
}
|
||||
|
||||
return super.drop( item, cell );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Dark cold water.";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "There are old blood stains on the floor.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
PrisonLevel.addVisuals( this, scene );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.watabou.noosa.particles.Emitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
|
||||
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.Room.Type;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class PrisonLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
color1 = 0x6a723d;
|
||||
color2 = 0x88924c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_PRISON;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_PRISON;
|
||||
}
|
||||
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( feeling == Feeling.WATER ? 0.65f : 0.45f, 4 );
|
||||
}
|
||||
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( feeling == Feeling.GRASS ? 0.60f : 0.40f, 3 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assignRoomType() {
|
||||
super.assignRoomType();
|
||||
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.TUNNEL) {
|
||||
r.type = Type.PASSAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
super.createMobs();
|
||||
|
||||
Wandmaker.Quest.spawn( this, roomEntrance );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=WIDTH + 1; i < LENGTH - WIDTH - 1; i++) {
|
||||
if (map[i] == Terrain.EMPTY) {
|
||||
|
||||
float c = 0.05f;
|
||||
if (map[i + 1] == Terrain.WALL && map[i + WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
if (map[i - 1] == Terrain.WALL && map[i + WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
if (map[i + 1] == Terrain.WALL && map[i - WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
if (map[i - 1] == Terrain.WALL && map[i - WIDTH] == Terrain.WALL) {
|
||||
c += 0.2f;
|
||||
}
|
||||
|
||||
if (Random.Float() < c) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i < WIDTH; i++) {
|
||||
if (map[i] == Terrain.WALL &&
|
||||
(map[i + WIDTH] == Terrain.EMPTY || map[i + WIDTH] == Terrain.EMPTY_SP) &&
|
||||
Random.Int( 6 ) == 0) {
|
||||
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=WIDTH; i < LENGTH - WIDTH; i++) {
|
||||
if (map[i] == Terrain.WALL &&
|
||||
map[i - WIDTH] == Terrain.WALL &&
|
||||
(map[i + WIDTH] == Terrain.EMPTY || map[i + WIDTH] == Terrain.EMPTY_SP) &&
|
||||
Random.Int( 3 ) == 0) {
|
||||
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Dark cold water.";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "There are old blood stains on the floor.";
|
||||
case Terrain.BOOKSHELF:
|
||||
return "This is probably a vestige of a prison library. Might it burn?";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
super.addVisuals( scene );
|
||||
addVisuals( this, scene );
|
||||
}
|
||||
|
||||
public static void addVisuals( Level level, Scene scene ) {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (level.map[i] == Terrain.WALL_DECO) {
|
||||
scene.add( new Torch( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class Torch extends Emitter {
|
||||
|
||||
private int pos;
|
||||
|
||||
public Torch( int pos ) {
|
||||
super();
|
||||
|
||||
this.pos = pos;
|
||||
|
||||
PointF p = DungeonTilemap.tileCenterToWorld( pos );
|
||||
pos( p.x - 1, p.y + 3, 2, 0 );
|
||||
|
||||
pour( FlameParticle.FACTORY, 0.15f );
|
||||
|
||||
add( new Halo( 16, 0xFFFFCC, 0.2f ).point( p.x, p.y ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
if (visible = Dungeon.visible[pos]) {
|
||||
super.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,694 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.*;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Graph;
|
||||
import com.watabou.utils.Random;
|
||||
import com.watabou.utils.Rect;
|
||||
|
||||
public abstract class RegularLevel extends Level {
|
||||
|
||||
protected HashSet<Room> rooms;
|
||||
|
||||
protected Room roomEntrance;
|
||||
protected Room roomExit;
|
||||
|
||||
protected ArrayList<Room.Type> specials;
|
||||
|
||||
public int secretDoors;
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
if (!initRooms()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int distance;
|
||||
int retry = 0;
|
||||
int minDistance = (int)Math.sqrt( rooms.size() );
|
||||
do {
|
||||
do {
|
||||
roomEntrance = Random.element( rooms );
|
||||
} while (roomEntrance.width() < 4 || roomEntrance.height() < 4);
|
||||
|
||||
do {
|
||||
roomExit = Random.element( rooms );
|
||||
} while (roomExit == roomEntrance || roomExit.width() < 4 || roomExit.height() < 4);
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
distance = roomEntrance.distance();
|
||||
|
||||
if (retry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} while (distance < minDistance);
|
||||
|
||||
roomEntrance.type = Type.ENTRANCE;
|
||||
roomExit.type = Type.EXIT;
|
||||
|
||||
HashSet<Room> connected = new HashSet<Room>();
|
||||
connected.add( roomEntrance );
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
List<Room> path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
|
||||
Room room = roomEntrance;
|
||||
for (Room next : path) {
|
||||
room.connect( next );
|
||||
room = next;
|
||||
connected.add( room );
|
||||
}
|
||||
|
||||
Graph.setPrice( path, roomEntrance.distance );
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
|
||||
room = roomEntrance;
|
||||
for (Room next : path) {
|
||||
room.connect( next );
|
||||
room = next;
|
||||
connected.add( room );
|
||||
}
|
||||
|
||||
int nConnected = (int)(rooms.size() * Random.Float( 0.5f, 0.7f ));
|
||||
while (connected.size() < nConnected) {
|
||||
|
||||
Room cr = Random.element( connected );
|
||||
Room or = Random.element( cr.neigbours );
|
||||
if (!connected.contains( or )) {
|
||||
|
||||
cr.connect( or );
|
||||
connected.add( or );
|
||||
}
|
||||
}
|
||||
|
||||
if (Dungeon.shopOnLevel()) {
|
||||
Room shop = null;
|
||||
for (Room r : roomEntrance.connected.keySet()) {
|
||||
if (r.connected.size() == 1 && r.width() >= 5 && r.height() >= 5) {
|
||||
shop = r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shop == null) {
|
||||
return false;
|
||||
} else {
|
||||
shop.type = Room.Type.SHOP;
|
||||
}
|
||||
}
|
||||
|
||||
specials = new ArrayList<Room.Type>( Room.SPECIALS );
|
||||
if (Dungeon.bossLevel( Dungeon.depth + 1 )) {
|
||||
specials.remove( Room.Type.WEAK_FLOOR );
|
||||
}
|
||||
assignRoomType();
|
||||
|
||||
paint();
|
||||
paintWater();
|
||||
paintGrass();
|
||||
|
||||
placeTraps();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean initRooms() {
|
||||
|
||||
rooms = new HashSet<Room>();
|
||||
split( new Rect( 0, 0, WIDTH - 1, HEIGHT - 1 ) );
|
||||
|
||||
if (rooms.size() < 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Room[] ra = rooms.toArray( new Room[0] );
|
||||
for (int i=0; i < ra.length-1; i++) {
|
||||
for (int j=i+1; j < ra.length; j++) {
|
||||
ra[i].addNeigbour( ra[j] );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void assignRoomType() {
|
||||
|
||||
int specialRooms = 0;
|
||||
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.NULL &&
|
||||
r.connected.size() == 1) {
|
||||
|
||||
if (specials.size() > 0 &&
|
||||
r.width() > 3 && r.height() > 3 &&
|
||||
Random.Int( specialRooms * specialRooms + 2 ) == 0) {
|
||||
|
||||
if (pitRoomNeeded) {
|
||||
|
||||
r.type = Type.PIT;
|
||||
pitRoomNeeded = false;
|
||||
|
||||
specials.remove( Type.ARMORY );
|
||||
specials.remove( Type.CRYPT );
|
||||
specials.remove( Type.LABORATORY );
|
||||
specials.remove( Type.LIBRARY );
|
||||
specials.remove( Type.STATUE );
|
||||
specials.remove( Type.TREASURY );
|
||||
specials.remove( Type.VAULT );
|
||||
specials.remove( Type.WEAK_FLOOR );
|
||||
|
||||
} else if (Dungeon.depth % 5 == 2 && specials.contains( Type.LABORATORY )) {
|
||||
|
||||
r.type = Type.LABORATORY;
|
||||
|
||||
} else if (Dungeon.depth >= Dungeon.transmutation && specials.contains( Type.MAGIC_WELL )) {
|
||||
|
||||
r.type = Type.MAGIC_WELL;
|
||||
|
||||
} else {
|
||||
|
||||
int n = specials.size();
|
||||
r.type = specials.get( Math.min( Random.Int( n ), Random.Int( n ) ) );
|
||||
if (r.type == Type.WEAK_FLOOR) {
|
||||
weakFloorCreated = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Room.useType( r.type );
|
||||
specials.remove( r.type );
|
||||
specialRooms++;
|
||||
|
||||
} else if (Random.Int( 2 ) == 0){
|
||||
|
||||
HashSet<Room> neigbours = new HashSet<Room>();
|
||||
for (Room n : r.neigbours) {
|
||||
if (!r.connected.containsKey( n ) &&
|
||||
!Room.SPECIALS.contains( n.type ) &&
|
||||
n.type != Type.PIT) {
|
||||
|
||||
neigbours.add( n );
|
||||
}
|
||||
}
|
||||
if (neigbours.size() > 1) {
|
||||
r.connect( Random.element( neigbours ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.NULL) {
|
||||
int connections = r.connected.size();
|
||||
if (connections == 0) {
|
||||
|
||||
} else if (Random.Int( connections * connections ) == 0) {
|
||||
r.type = Type.STANDARD;
|
||||
count++;
|
||||
} else {
|
||||
r.type = Type.TUNNEL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (count < 4) {
|
||||
Room r = randomRoom( Type.TUNNEL, 1 );
|
||||
if (r != null) {
|
||||
r.type = Type.STANDARD;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintWater() {
|
||||
boolean[] lake = water();
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (map[i] == Terrain.EMPTY && lake[i]) {
|
||||
map[i] = Terrain.WATER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintGrass() {
|
||||
boolean[] grass = grass();
|
||||
|
||||
if (feeling == Feeling.GRASS) {
|
||||
|
||||
for (Room room : rooms) {
|
||||
if (room.type != Type.NULL && room.type != Type.PASSAGE && room.type != Type.TUNNEL) {
|
||||
grass[(room.left + 1) + (room.top + 1) * WIDTH] = true;
|
||||
grass[(room.right - 1) + (room.top + 1) * WIDTH] = true;
|
||||
grass[(room.left + 1) + (room.bottom - 1) * WIDTH] = true;
|
||||
grass[(room.right - 1) + (room.bottom - 1) * WIDTH] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=WIDTH+1; i < LENGTH-WIDTH-1; i++) {
|
||||
if (map[i] == Terrain.EMPTY && grass[i]) {
|
||||
int count = 1;
|
||||
for (int n : NEIGHBOURS8) {
|
||||
if (grass[i + n]) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
map[i] = (Random.Float() < count / 12f) ? Terrain.HIGH_GRASS : Terrain.GRASS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean[] water();
|
||||
protected abstract boolean[] grass();
|
||||
|
||||
protected void placeTraps() {
|
||||
|
||||
int nTraps = nTraps();
|
||||
float[] trapChances = trapChances();
|
||||
|
||||
for (int i=0; i < nTraps; i++) {
|
||||
|
||||
int trapPos = Random.Int( LENGTH );
|
||||
|
||||
if (map[trapPos] == Terrain.EMPTY) {
|
||||
switch (Random.chances( trapChances )) {
|
||||
case 0:
|
||||
map[trapPos] = Terrain.SECRET_TOXIC_TRAP;
|
||||
break;
|
||||
case 1:
|
||||
map[trapPos] = Terrain.SECRET_FIRE_TRAP;
|
||||
break;
|
||||
case 2:
|
||||
map[trapPos] = Terrain.SECRET_PARALYTIC_TRAP;
|
||||
break;
|
||||
case 3:
|
||||
map[trapPos] = Terrain.SECRET_POISON_TRAP;
|
||||
break;
|
||||
case 4:
|
||||
map[trapPos] = Terrain.SECRET_ALARM_TRAP;
|
||||
break;
|
||||
case 5:
|
||||
map[trapPos] = Terrain.SECRET_LIGHTNING_TRAP;
|
||||
break;
|
||||
case 6:
|
||||
map[trapPos] = Terrain.SECRET_GRIPPING_TRAP;
|
||||
break;
|
||||
case 7:
|
||||
map[trapPos] = Terrain.SECRET_SUMMONING_TRAP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected int nTraps() {
|
||||
return Dungeon.depth <= 1 ? 0 : Random.Int( 1, rooms.size() + Dungeon.depth );
|
||||
}
|
||||
|
||||
protected float[] trapChances() {
|
||||
float[] chances = { 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
return chances;
|
||||
}
|
||||
|
||||
protected int minRoomSize = 7;
|
||||
protected int maxRoomSize = 9;
|
||||
|
||||
protected void split( Rect rect ) {
|
||||
|
||||
int w = rect.width();
|
||||
int h = rect.height();
|
||||
|
||||
if (w > maxRoomSize && h < minRoomSize) {
|
||||
|
||||
int vw = Random.Int( rect.left + 3, rect.right - 3 );
|
||||
split( new Rect( rect.left, rect.top, vw, rect.bottom ) );
|
||||
split( new Rect( vw, rect.top, rect.right, rect.bottom ) );
|
||||
|
||||
} else
|
||||
if (h > maxRoomSize && w < minRoomSize) {
|
||||
|
||||
int vh = Random.Int( rect.top + 3, rect.bottom - 3 );
|
||||
split( new Rect( rect.left, rect.top, rect.right, vh ) );
|
||||
split( new Rect( rect.left, vh, rect.right, rect.bottom ) );
|
||||
|
||||
} else
|
||||
if ((Math.random() <= (minRoomSize * minRoomSize / rect.square()) && w <= maxRoomSize && h <= maxRoomSize) || w < minRoomSize || h < minRoomSize) {
|
||||
|
||||
rooms.add( (Room)new Room().set( rect ) );
|
||||
|
||||
} else {
|
||||
|
||||
if (Random.Float() < (float)(w - 2) / (w + h - 4)) {
|
||||
int vw = Random.Int( rect.left + 3, rect.right - 3 );
|
||||
split( new Rect( rect.left, rect.top, vw, rect.bottom ) );
|
||||
split( new Rect( vw, rect.top, rect.right, rect.bottom ) );
|
||||
} else {
|
||||
int vh = Random.Int( rect.top + 3, rect.bottom - 3 );
|
||||
split( new Rect( rect.left, rect.top, rect.right, vh ) );
|
||||
split( new Rect( rect.left, vh, rect.right, rect.bottom ) );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected void paint() {
|
||||
|
||||
for (Room r : rooms) {
|
||||
if (r.type != Type.NULL) {
|
||||
placeDoors( r );
|
||||
r.type.paint( this, r );
|
||||
} else {
|
||||
if (feeling == Feeling.CHASM && Random.Int( 2 ) == 0) {
|
||||
Painter.fill( this, r, Terrain.WALL );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Room r : rooms) {
|
||||
paintDoors( r );
|
||||
}
|
||||
}
|
||||
|
||||
private void placeDoors( Room r ) {
|
||||
for (Room n : r.connected.keySet()) {
|
||||
Room.Door door = r.connected.get( n );
|
||||
if (door == null) {
|
||||
|
||||
Rect i = r.intersect( n );
|
||||
if (i.width() == 0) {
|
||||
door = new Room.Door(
|
||||
i.left,
|
||||
Random.Int( i.top + 1, i.bottom ) );
|
||||
} else {
|
||||
door = new Room.Door(
|
||||
Random.Int( i.left + 1, i.right ),
|
||||
i.top);
|
||||
}
|
||||
|
||||
r.connected.put( n, door );
|
||||
n.connected.put( r, door );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void paintDoors( Room r ) {
|
||||
for (Room n : r.connected.keySet()) {
|
||||
|
||||
if (joinRooms( r, n )) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Room.Door d = r.connected.get( n );
|
||||
int door = d.x + d.y * WIDTH;
|
||||
|
||||
switch (d.type) {
|
||||
case EMPTY:
|
||||
map[door] = Terrain.EMPTY;
|
||||
break;
|
||||
case TUNNEL:
|
||||
map[door] = tunnelTile();
|
||||
break;
|
||||
case REGULAR:
|
||||
if (Dungeon.depth <= 1) {
|
||||
map[door] = Terrain.DOOR;
|
||||
} else {
|
||||
boolean secret = (Dungeon.depth < 6 ? Random.Int( 12 - Dungeon.depth ) : Random.Int( 6 )) == 0;
|
||||
map[door] = secret ? Terrain.SECRET_DOOR : Terrain.DOOR;
|
||||
if (secret) {
|
||||
secretDoors++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UNLOCKED:
|
||||
map[door] = Terrain.DOOR;
|
||||
break;
|
||||
case HIDDEN:
|
||||
map[door] = Terrain.SECRET_DOOR;
|
||||
break;
|
||||
case BARRICADE:
|
||||
map[door] = Random.Int( 3 ) == 0 ? Terrain.BOOKSHELF : Terrain.BARRICADE;
|
||||
break;
|
||||
case LOCKED:
|
||||
map[door] = Terrain.LOCKED_DOOR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean joinRooms( Room r, Room n ) {
|
||||
|
||||
if (r.type != Room.Type.STANDARD || n.type != Room.Type.STANDARD) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Rect w = r.intersect( n );
|
||||
if (w.left == w.right) {
|
||||
|
||||
if (w.bottom - w.top < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (w.height() == Math.max( r.height(), n.height() )) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r.width() + n.width() > maxRoomSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
w.top += 1;
|
||||
w.bottom -= 0;
|
||||
|
||||
w.right++;
|
||||
|
||||
Painter.fill( this, w.left, w.top, 1, w.height(), Terrain.EMPTY );
|
||||
|
||||
} else {
|
||||
|
||||
if (w.right - w.left < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (w.width() == Math.max( r.width(), n.width() )) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (r.height() + n.height() > maxRoomSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
w.left += 1;
|
||||
w.right -= 0;
|
||||
|
||||
w.bottom++;
|
||||
|
||||
Painter.fill( this, w.left, w.top, w.width(), 1, Terrain.EMPTY );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nMobs() {
|
||||
return 2 + Dungeon.depth % 5 + Random.Int( 3 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
int nMobs = nMobs();
|
||||
for (int i=0; i < nMobs; i++) {
|
||||
Mob mob = Bestiary.mob( Dungeon.depth );
|
||||
do {
|
||||
mob.pos = randomRespawnCell();
|
||||
} while (mob.pos == -1);
|
||||
mobs.add( mob );
|
||||
Actor.occupyCell( mob );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomRespawnCell() {
|
||||
int count = 0;
|
||||
int cell = -1;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (++count > 10) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Room room = randomRoom( Room.Type.STANDARD, 10 );
|
||||
if (room == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cell = room.random();
|
||||
if (!Dungeon.visible[cell] && Actor.findChar( cell ) == null && Level.passable[cell]) {
|
||||
return cell;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int randomDestination() {
|
||||
|
||||
int cell = -1;
|
||||
|
||||
while (true) {
|
||||
|
||||
Room room = Random.element( rooms );
|
||||
if (room == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cell = room.random();
|
||||
if (Level.passable[cell]) {
|
||||
return cell;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
|
||||
int nItems = 3;
|
||||
while (Random.Float() < 0.3f) {
|
||||
nItems++;
|
||||
}
|
||||
|
||||
for (int i=0; i < nItems; i++) {
|
||||
Heap.Type type = null;
|
||||
switch (Random.Int( 20 )) {
|
||||
case 0:
|
||||
type = Heap.Type.SKELETON;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
type = Heap.Type.CHEST;
|
||||
break;
|
||||
default:
|
||||
type = Heap.Type.HEAP;
|
||||
}
|
||||
drop( Generator.random(), randomDropCell() ).type = type;
|
||||
}
|
||||
|
||||
for (Item item : itemsToSpawn) {
|
||||
int cell = randomDropCell();
|
||||
if (item instanceof ScrollOfUpgrade) {
|
||||
while (map[cell] == Terrain.FIRE_TRAP || map[cell] == Terrain.SECRET_FIRE_TRAP) {
|
||||
cell = randomDropCell();
|
||||
}
|
||||
}
|
||||
drop( item, cell ).type = Heap.Type.HEAP;
|
||||
}
|
||||
|
||||
Item item = Bones.get();
|
||||
if (item != null) {
|
||||
drop( item, randomDropCell() ).type = Heap.Type.SKELETON;
|
||||
}
|
||||
}
|
||||
|
||||
protected Room randomRoom( Room.Type type, int tries ) {
|
||||
for (int i=0; i < tries; i++) {
|
||||
Room room = Random.element( rooms );
|
||||
if (room.type == type) {
|
||||
return room;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Room room( int pos ) {
|
||||
for (Room room : rooms) {
|
||||
if (room.type != Type.NULL && room.inside( pos )) {
|
||||
return room;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int randomDropCell() {
|
||||
while (true) {
|
||||
Room room = randomRoom( Room.Type.STANDARD, 1 );
|
||||
if (room != null) {
|
||||
int pos = room.random();
|
||||
if (passable[pos]) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int pitCell() {
|
||||
for (Room room : rooms) {
|
||||
if (room.type == Type.PIT) {
|
||||
return room.random();
|
||||
}
|
||||
}
|
||||
|
||||
return super.pitCell();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( "rooms", rooms );
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
|
||||
rooms = new HashSet<Room>( (Collection<? extends Room>) bundle.getCollection( "rooms" ) );
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.WEAK_FLOOR) {
|
||||
weakFloorCreated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.*;
|
||||
import com.watabou.utils.Bundlable;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Graph;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
import com.watabou.utils.Rect;
|
||||
|
||||
public class Room extends Rect implements Graph.Node, Bundlable {
|
||||
|
||||
public HashSet<Room> neigbours = new HashSet<Room>();
|
||||
public HashMap<Room, Door> connected = new HashMap<Room, Door>();
|
||||
|
||||
public int distance;
|
||||
public int price = 1;
|
||||
|
||||
public static enum Type {
|
||||
NULL( null ),
|
||||
STANDARD ( StandardPainter.class ),
|
||||
ENTRANCE ( EntrancePainter.class ),
|
||||
EXIT ( ExitPainter.class ),
|
||||
BOSS_EXIT ( BossExitPainter.class ),
|
||||
TUNNEL ( TunnelPainter.class ),
|
||||
PASSAGE ( PassagePainter.class ),
|
||||
SHOP ( ShopPainter.class ),
|
||||
BLACKSMITH ( BlacksmithPainter.class ),
|
||||
TREASURY ( TreasuryPainter.class ),
|
||||
ARMORY ( ArmoryPainter.class ),
|
||||
LIBRARY ( LibraryPainter.class ),
|
||||
LABORATORY ( LaboratoryPainter.class ),
|
||||
VAULT ( VaultPainter.class ),
|
||||
TRAPS ( TrapsPainter.class ),
|
||||
STORAGE ( StoragePainter.class ),
|
||||
MAGIC_WELL ( MagicWellPainter.class ),
|
||||
GARDEN ( GardenPainter.class ),
|
||||
CRYPT ( CryptPainter.class ),
|
||||
STATUE ( StatuePainter.class ),
|
||||
POOL ( PoolPainter.class ),
|
||||
RAT_KING ( RatKingPainter.class ),
|
||||
WEAK_FLOOR ( WeakFloorPainter.class ),
|
||||
PIT ( PitPainter.class );
|
||||
|
||||
private Method paint;
|
||||
|
||||
private Type( Class<? extends Painter> painter ) {
|
||||
try {
|
||||
paint = painter.getMethod( "paint", Level.class, Room.class );
|
||||
} catch (Exception e) {
|
||||
paint = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void paint( Level level, Room room ) {
|
||||
try {
|
||||
paint.invoke( null, level, room );
|
||||
} catch (Exception e) {
|
||||
ShatteredPixelDungeon.reportException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static final ArrayList<Type> SPECIALS = new ArrayList<Type>( Arrays.asList(
|
||||
Type.WEAK_FLOOR, Type.MAGIC_WELL, Type.CRYPT, Type.POOL, Type.GARDEN, Type.LIBRARY, Type.ARMORY,
|
||||
Type.TREASURY, Type.TRAPS, Type.STORAGE, Type.STATUE, Type.LABORATORY, Type.VAULT
|
||||
) );
|
||||
|
||||
public Type type = Type.NULL;
|
||||
|
||||
public int random() {
|
||||
return random( 0 );
|
||||
}
|
||||
|
||||
public int random( int m ) {
|
||||
int x = Random.Int( left + 1 + m, right - m );
|
||||
int y = Random.Int( top + 1 + m, bottom - m );
|
||||
return x + y * Level.WIDTH;
|
||||
}
|
||||
|
||||
public void addNeigbour( Room other ) {
|
||||
|
||||
Rect i = intersect( other );
|
||||
if ((i.width() == 0 && i.height() >= 3) ||
|
||||
(i.height() == 0 && i.width() >= 3)) {
|
||||
neigbours.add( other );
|
||||
other.neigbours.add( this );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void connect( Room room ) {
|
||||
if (!connected.containsKey( room )) {
|
||||
connected.put( room, null );
|
||||
room.connected.put( this, null );
|
||||
}
|
||||
}
|
||||
|
||||
public Door entrance() {
|
||||
return connected.values().iterator().next();
|
||||
}
|
||||
|
||||
public boolean inside( int p ) {
|
||||
int x = p % Level.WIDTH;
|
||||
int y = p / Level.WIDTH;
|
||||
return x > left && y > top && x < right && y < bottom;
|
||||
}
|
||||
|
||||
public Point center() {
|
||||
return new Point(
|
||||
(left + right) / 2 + (((right - left) & 1) == 1 ? Random.Int( 2 ) : 0),
|
||||
(top + bottom) / 2 + (((bottom - top) & 1) == 1 ? Random.Int( 2 ) : 0) );
|
||||
}
|
||||
|
||||
// **** Graph.Node interface ****
|
||||
|
||||
@Override
|
||||
public int distance() {
|
||||
return distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void distance( int value ) {
|
||||
distance = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int price() {
|
||||
return price;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void price( int value ) {
|
||||
price = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Room> edges() {
|
||||
return neigbours;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
bundle.put( "left", left );
|
||||
bundle.put( "top", top );
|
||||
bundle.put( "right", right );
|
||||
bundle.put( "bottom", bottom );
|
||||
bundle.put( "type", type.toString() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
left = bundle.getInt( "left" );
|
||||
top = bundle.getInt( "top" );
|
||||
right = bundle.getInt( "right" );
|
||||
bottom = bundle.getInt( "bottom" );
|
||||
type = Type.valueOf( bundle.getString( "type" ) );
|
||||
}
|
||||
|
||||
public static void shuffleTypes() {
|
||||
int size = SPECIALS.size();
|
||||
for (int i=0; i < size - 1; i++) {
|
||||
int j = Random.Int( i, size );
|
||||
if (j != i) {
|
||||
Type t = SPECIALS.get( i );
|
||||
SPECIALS.set( i, SPECIALS.get( j ) );
|
||||
SPECIALS.set( j, t );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void useType( Type type ) {
|
||||
if (SPECIALS.remove( type )) {
|
||||
SPECIALS.add( type );
|
||||
}
|
||||
}
|
||||
|
||||
private static final String ROOMS = "rooms";
|
||||
|
||||
public static void restoreRoomsFromBundle( Bundle bundle ) {
|
||||
if (bundle.contains( ROOMS )) {
|
||||
SPECIALS.clear();
|
||||
for (String type : bundle.getStringArray( ROOMS )) {
|
||||
SPECIALS.add( Type.valueOf( type ));
|
||||
}
|
||||
} else {
|
||||
shuffleTypes();
|
||||
}
|
||||
}
|
||||
|
||||
public static void storeRoomsInBundle( Bundle bundle ) {
|
||||
String[] array = new String[SPECIALS.size()];
|
||||
for (int i=0; i < array.length; i++) {
|
||||
array[i] = SPECIALS.get( i ).toString();
|
||||
}
|
||||
bundle.put( ROOMS, array );
|
||||
}
|
||||
|
||||
public static class Door extends Point {
|
||||
|
||||
public static enum Type {
|
||||
EMPTY, TUNNEL, REGULAR, UNLOCKED, HIDDEN, BARRICADE, LOCKED
|
||||
}
|
||||
public Type type = Type.EMPTY;
|
||||
|
||||
public Door( int x, int y ) {
|
||||
super( x, y );
|
||||
}
|
||||
|
||||
public void set( Type type ) {
|
||||
if (type.compareTo( this.type ) > 0) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Bundle;
|
||||
import com.watabou.utils.Graph;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class SewerBossLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
color1 = 0x48763c;
|
||||
color2 = 0x59994a;
|
||||
}
|
||||
|
||||
private int stairs = 0;
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_SEWERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_SEWERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean build() {
|
||||
|
||||
initRooms();
|
||||
|
||||
int distance;
|
||||
int retry = 0;
|
||||
int minDistance = (int)Math.sqrt( rooms.size() );
|
||||
do {
|
||||
int innerRetry = 0;
|
||||
do {
|
||||
if (innerRetry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
roomEntrance = Random.element( rooms );
|
||||
} while (roomEntrance.width() < 4 || roomEntrance.height() < 4);
|
||||
|
||||
innerRetry = 0;
|
||||
do {
|
||||
if (innerRetry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
roomExit = Random.element( rooms );
|
||||
} while (roomExit == roomEntrance || roomExit.width() < 6 || roomExit.height() < 6 || roomExit.top == 0);
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
distance = roomEntrance.distance();
|
||||
|
||||
if (retry++ > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} while (distance < minDistance);
|
||||
|
||||
roomEntrance.type = Type.ENTRANCE;
|
||||
roomExit.type = Type.BOSS_EXIT;
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
List<Room> path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
|
||||
Graph.setPrice( path, roomEntrance.distance );
|
||||
|
||||
Graph.buildDistanceMap( rooms, roomExit );
|
||||
path = Graph.buildPath( rooms, roomEntrance, roomExit );
|
||||
|
||||
Room room = roomEntrance;
|
||||
for (Room next : path) {
|
||||
room.connect( next );
|
||||
room = next;
|
||||
}
|
||||
|
||||
room = (Room)roomExit.connected.keySet().toArray()[0];
|
||||
if (roomExit.top == room.bottom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (Room r : rooms) {
|
||||
if (r.type == Type.NULL && r.connected.size() > 0) {
|
||||
r.type = Type.TUNNEL;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Room> candidates = new ArrayList<Room>();
|
||||
for (Room r : roomExit.neigbours) {
|
||||
if (!roomExit.connected.containsKey( r ) &&
|
||||
(roomExit.left == r.right || roomExit.right == r.left || roomExit.bottom == r.top)) {
|
||||
candidates.add( r );
|
||||
}
|
||||
}
|
||||
if (candidates.size() > 0) {
|
||||
Room kingsRoom = Random.element( candidates );
|
||||
kingsRoom.connect( roomExit );
|
||||
kingsRoom.type = Room.Type.RAT_KING;
|
||||
}
|
||||
|
||||
paint();
|
||||
|
||||
paintWater();
|
||||
paintGrass();
|
||||
|
||||
placeTraps();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( 0.5f, 5 );
|
||||
}
|
||||
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( 0.40f, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
int start = roomExit.top * WIDTH + roomExit.left + 1;
|
||||
int end = start + roomExit.width() - 1;
|
||||
for (int i=start; i < end; i++) {
|
||||
if (i != exit) {
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
map[i + WIDTH] = Terrain.WATER;
|
||||
} else {
|
||||
map[i + WIDTH] = Terrain.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
SewerLevel.addVisuals( this, scene );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
Mob mob = Bestiary.mob( Dungeon.depth );
|
||||
mob.pos = roomExit.random();
|
||||
mobs.add( mob );
|
||||
}
|
||||
|
||||
public Actor respawner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
Item item = Bones.get();
|
||||
if (item != null) {
|
||||
int pos;
|
||||
do {
|
||||
pos = roomEntrance.random();
|
||||
} while (pos == entrance || map[pos] == Terrain.SIGN);
|
||||
drop( item, pos ).type = Heap.Type.SKELETON;
|
||||
}
|
||||
}
|
||||
|
||||
public void seal() {
|
||||
if (entrance != 0) {
|
||||
|
||||
set( entrance, Terrain.WATER_TILES );
|
||||
GameScene.updateMap( entrance );
|
||||
GameScene.ripple( entrance );
|
||||
|
||||
stairs = entrance;
|
||||
entrance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void unseal() {
|
||||
if (stairs != 0) {
|
||||
|
||||
entrance = stairs;
|
||||
stairs = 0;
|
||||
|
||||
set( entrance, Terrain.ENTRANCE );
|
||||
GameScene.updateMap( entrance );
|
||||
}
|
||||
}
|
||||
|
||||
private static final String STAIRS = "stairs";
|
||||
|
||||
@Override
|
||||
public void storeInBundle( Bundle bundle ) {
|
||||
super.storeInBundle( bundle );
|
||||
bundle.put( STAIRS, stairs );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void restoreFromBundle( Bundle bundle ) {
|
||||
super.restoreFromBundle( bundle );
|
||||
stairs = bundle.getInt( STAIRS );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Murky water";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Wet yellowish moss covers the floor.";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.Scene;
|
||||
import com.watabou.noosa.particles.Emitter;
|
||||
import com.watabou.noosa.particles.PixelParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.DungeonTilemap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Ghost;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.DewVial;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.ColorMath;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class SewerLevel extends RegularLevel {
|
||||
|
||||
{
|
||||
color1 = 0x48763c;
|
||||
color2 = 0x59994a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tilesTex() {
|
||||
return Assets.TILES_SEWERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String waterTex() {
|
||||
return Assets.WATER_SEWERS;
|
||||
}
|
||||
|
||||
protected boolean[] water() {
|
||||
return Patch.generate( feeling == Feeling.WATER ? 0.60f : 0.45f, 5 );
|
||||
}
|
||||
|
||||
protected boolean[] grass() {
|
||||
return Patch.generate( feeling == Feeling.GRASS ? 0.60f : 0.40f, 4 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decorate() {
|
||||
|
||||
for (int i=0; i < WIDTH; i++) {
|
||||
if (map[i] == Terrain.WALL &&
|
||||
map[i + WIDTH] == Terrain.WATER &&
|
||||
Random.Int( 4 ) == 0) {
|
||||
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=WIDTH; i < LENGTH - WIDTH; i++) {
|
||||
if (map[i] == Terrain.WALL &&
|
||||
map[i - WIDTH] == Terrain.WALL &&
|
||||
map[i + WIDTH] == Terrain.WATER &&
|
||||
Random.Int( 2 ) == 0) {
|
||||
|
||||
map[i] = Terrain.WALL_DECO;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=WIDTH + 1; i < LENGTH - WIDTH - 1; i++) {
|
||||
if (map[i] == Terrain.EMPTY) {
|
||||
|
||||
int count =
|
||||
(map[i + 1] == Terrain.WALL ? 1 : 0) +
|
||||
(map[i - 1] == Terrain.WALL ? 1 : 0) +
|
||||
(map[i + WIDTH] == Terrain.WALL ? 1 : 0) +
|
||||
(map[i - WIDTH] == Terrain.WALL ? 1 : 0);
|
||||
|
||||
if (Random.Int( 16 ) < count * count) {
|
||||
map[i] = Terrain.EMPTY_DECO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int pos = roomEntrance.random();
|
||||
if (pos != entrance) {
|
||||
map[pos] = Terrain.SIGN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createMobs() {
|
||||
super.createMobs();
|
||||
|
||||
Ghost.Quest.spawn( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createItems() {
|
||||
if (Dungeon.dewVial && Random.Int( 4 - Dungeon.depth ) == 0) {
|
||||
addItemToSpawn( new DewVial() );
|
||||
Dungeon.dewVial = false;
|
||||
}
|
||||
|
||||
super.createItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addVisuals( Scene scene ) {
|
||||
super.addVisuals( scene );
|
||||
addVisuals( this, scene );
|
||||
}
|
||||
|
||||
public static void addVisuals( Level level, Scene scene ) {
|
||||
for (int i=0; i < LENGTH; i++) {
|
||||
if (level.map[i] == Terrain.WALL_DECO) {
|
||||
scene.add( new Sink( i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileName( int tile ) {
|
||||
switch (tile) {
|
||||
case Terrain.WATER:
|
||||
return "Murky water";
|
||||
default:
|
||||
return super.tileName( tile );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tileDesc(int tile) {
|
||||
switch (tile) {
|
||||
case Terrain.EMPTY_DECO:
|
||||
return "Wet yellowish moss covers the floor.";
|
||||
case Terrain.BOOKSHELF:
|
||||
return "The bookshelf is packed with cheap useless books. Might it burn?";
|
||||
default:
|
||||
return super.tileDesc( tile );
|
||||
}
|
||||
}
|
||||
|
||||
private static class Sink extends Emitter {
|
||||
|
||||
private int pos;
|
||||
private float rippleDelay = 0;
|
||||
|
||||
private static final Emitter.Factory factory = new Factory() {
|
||||
|
||||
@Override
|
||||
public void emit( Emitter emitter, int index, float x, float y ) {
|
||||
WaterParticle p = (WaterParticle)emitter.recycle( WaterParticle.class );
|
||||
p.reset( x, y );
|
||||
}
|
||||
};
|
||||
|
||||
public Sink( int pos ) {
|
||||
super();
|
||||
|
||||
this.pos = pos;
|
||||
|
||||
PointF p = DungeonTilemap.tileCenterToWorld( pos );
|
||||
pos( p.x - 2, p.y + 1, 4, 0 );
|
||||
|
||||
pour( factory, 0.05f );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
if (visible = Dungeon.visible[pos]) {
|
||||
|
||||
super.update();
|
||||
|
||||
if ((rippleDelay -= Game.elapsed) <= 0) {
|
||||
GameScene.ripple( pos + WIDTH ).y -= DungeonTilemap.SIZE / 2;
|
||||
rippleDelay = Random.Float( 0.2f, 0.3f );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class WaterParticle extends PixelParticle {
|
||||
|
||||
public WaterParticle() {
|
||||
super();
|
||||
|
||||
acc.y = 50;
|
||||
am = 0.5f;
|
||||
|
||||
color( ColorMath.random( 0xb6ccc2, 0x3b6653 ) );
|
||||
size( 2 );
|
||||
}
|
||||
|
||||
public void reset( float x, float y ) {
|
||||
revive();
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
speed.set( Random.Float( -2, +2 ), 0 );
|
||||
|
||||
left = lifespan = 0.5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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;
|
||||
|
||||
public class Terrain {
|
||||
|
||||
public static final int CHASM = 0;
|
||||
public static final int EMPTY = 1;
|
||||
public static final int GRASS = 2;
|
||||
public static final int EMPTY_WELL = 3;
|
||||
public static final int WALL = 4;
|
||||
public static final int DOOR = 5;
|
||||
public static final int OPEN_DOOR = 6;
|
||||
public static final int ENTRANCE = 7;
|
||||
public static final int EXIT = 8;
|
||||
public static final int EMBERS = 9;
|
||||
public static final int LOCKED_DOOR = 10;
|
||||
public static final int PEDESTAL = 11;
|
||||
public static final int WALL_DECO = 12;
|
||||
public static final int BARRICADE = 13;
|
||||
public static final int EMPTY_SP = 14;
|
||||
public static final int HIGH_GRASS = 15;
|
||||
public static final int EMPTY_DECO = 24;
|
||||
public static final int LOCKED_EXIT = 25;
|
||||
public static final int UNLOCKED_EXIT = 26;
|
||||
public static final int SIGN = 29;
|
||||
public static final int WELL = 34;
|
||||
public static final int STATUE = 35;
|
||||
public static final int STATUE_SP = 36;
|
||||
public static final int BOOKSHELF = 41;
|
||||
public static final int ALCHEMY = 42;
|
||||
public static final int CHASM_FLOOR = 43;
|
||||
public static final int CHASM_FLOOR_SP = 44;
|
||||
public static final int CHASM_WALL = 45;
|
||||
public static final int CHASM_WATER = 46;
|
||||
|
||||
public static final int SECRET_DOOR = 16;
|
||||
public static final int TOXIC_TRAP = 17;
|
||||
public static final int SECRET_TOXIC_TRAP = 18;
|
||||
public static final int FIRE_TRAP = 19;
|
||||
public static final int SECRET_FIRE_TRAP = 20;
|
||||
public static final int PARALYTIC_TRAP = 21;
|
||||
public static final int SECRET_PARALYTIC_TRAP = 22;
|
||||
public static final int INACTIVE_TRAP = 23;
|
||||
public static final int POISON_TRAP = 27;
|
||||
public static final int SECRET_POISON_TRAP = 28;
|
||||
public static final int ALARM_TRAP = 30;
|
||||
public static final int SECRET_ALARM_TRAP = 31;
|
||||
public static final int LIGHTNING_TRAP = 32;
|
||||
public static final int SECRET_LIGHTNING_TRAP = 33;
|
||||
public static final int GRIPPING_TRAP = 37;
|
||||
public static final int SECRET_GRIPPING_TRAP = 38;
|
||||
public static final int SUMMONING_TRAP = 39;
|
||||
public static final int SECRET_SUMMONING_TRAP = 40;
|
||||
|
||||
public static final int WATER_TILES = 48;
|
||||
public static final int WATER = 63;
|
||||
|
||||
public static final int PASSABLE = 0x01;
|
||||
public static final int LOS_BLOCKING = 0x02;
|
||||
public static final int FLAMABLE = 0x04;
|
||||
public static final int SECRET = 0x08;
|
||||
public static final int SOLID = 0x10;
|
||||
public static final int AVOID = 0x20;
|
||||
public static final int LIQUID = 0x40;
|
||||
public static final int PIT = 0x80;
|
||||
|
||||
public static final int UNSTITCHABLE = 0x100;
|
||||
|
||||
public static final int[] flags = new int[256];
|
||||
static {
|
||||
flags[CHASM] = AVOID | PIT | UNSTITCHABLE;
|
||||
flags[EMPTY] = PASSABLE;
|
||||
flags[GRASS] = PASSABLE | FLAMABLE;
|
||||
flags[EMPTY_WELL] = PASSABLE;
|
||||
flags[WATER] = PASSABLE | LIQUID | UNSTITCHABLE;
|
||||
flags[WALL] = LOS_BLOCKING | SOLID | UNSTITCHABLE;
|
||||
flags[DOOR] = PASSABLE | LOS_BLOCKING | FLAMABLE | SOLID | UNSTITCHABLE;
|
||||
flags[OPEN_DOOR] = PASSABLE | FLAMABLE | UNSTITCHABLE;
|
||||
flags[ENTRANCE] = PASSABLE;
|
||||
flags[EXIT] = PASSABLE;
|
||||
flags[EMBERS] = PASSABLE;
|
||||
flags[LOCKED_DOOR] = LOS_BLOCKING | SOLID | UNSTITCHABLE;
|
||||
flags[PEDESTAL] = PASSABLE | UNSTITCHABLE;
|
||||
flags[WALL_DECO] = flags[WALL];
|
||||
flags[BARRICADE] = FLAMABLE | SOLID | LOS_BLOCKING;
|
||||
flags[EMPTY_SP] = flags[EMPTY] | UNSTITCHABLE;
|
||||
flags[HIGH_GRASS] = PASSABLE | LOS_BLOCKING | FLAMABLE;
|
||||
flags[EMPTY_DECO] = flags[EMPTY];
|
||||
flags[LOCKED_EXIT] = SOLID;
|
||||
flags[UNLOCKED_EXIT]= PASSABLE;
|
||||
flags[SIGN] = PASSABLE | FLAMABLE;
|
||||
flags[WELL] = AVOID;
|
||||
flags[STATUE] = SOLID;
|
||||
flags[STATUE_SP] = flags[STATUE] | UNSTITCHABLE;
|
||||
flags[BOOKSHELF] = flags[BARRICADE] | UNSTITCHABLE;
|
||||
flags[ALCHEMY] = PASSABLE;
|
||||
|
||||
flags[CHASM_WALL] = flags[CHASM];
|
||||
flags[CHASM_FLOOR] = flags[CHASM];
|
||||
flags[CHASM_FLOOR_SP] = flags[CHASM];
|
||||
flags[CHASM_WATER] = flags[CHASM];
|
||||
|
||||
flags[SECRET_DOOR] = flags[WALL] | SECRET | UNSTITCHABLE;
|
||||
flags[TOXIC_TRAP] = AVOID;
|
||||
flags[SECRET_TOXIC_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[FIRE_TRAP] = AVOID;
|
||||
flags[SECRET_FIRE_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[PARALYTIC_TRAP] = AVOID;
|
||||
flags[SECRET_PARALYTIC_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[POISON_TRAP] = AVOID;
|
||||
flags[SECRET_POISON_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[ALARM_TRAP] = AVOID;
|
||||
flags[SECRET_ALARM_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[LIGHTNING_TRAP] = AVOID;
|
||||
flags[SECRET_LIGHTNING_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[GRIPPING_TRAP] = AVOID;
|
||||
flags[SECRET_GRIPPING_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[SUMMONING_TRAP] = AVOID;
|
||||
flags[SECRET_SUMMONING_TRAP] = flags[EMPTY] | SECRET;
|
||||
flags[INACTIVE_TRAP] = flags[EMPTY];
|
||||
|
||||
for (int i=WATER_TILES; i < WATER_TILES + 16; i++) {
|
||||
flags[i] = flags[WATER];
|
||||
}
|
||||
};
|
||||
|
||||
public static int discover( int terr ) {
|
||||
switch (terr) {
|
||||
case SECRET_DOOR:
|
||||
return DOOR;
|
||||
case SECRET_FIRE_TRAP:
|
||||
return FIRE_TRAP;
|
||||
case SECRET_PARALYTIC_TRAP:
|
||||
return PARALYTIC_TRAP;
|
||||
case SECRET_TOXIC_TRAP:
|
||||
return TOXIC_TRAP;
|
||||
case SECRET_POISON_TRAP:
|
||||
return POISON_TRAP;
|
||||
case SECRET_ALARM_TRAP:
|
||||
return ALARM_TRAP;
|
||||
case SECRET_LIGHTNING_TRAP:
|
||||
return LIGHTNING_TRAP;
|
||||
case SECRET_GRIPPING_TRAP:
|
||||
return GRIPPING_TRAP;
|
||||
case SECRET_SUMMONING_TRAP:
|
||||
return SUMMONING_TRAP;
|
||||
default:
|
||||
return terr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.features;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndBag;
|
||||
|
||||
public class AlchemyPot {
|
||||
|
||||
private static final String TXT_SELECT_SEED = "Select a seed to throw";
|
||||
|
||||
private static Hero hero;
|
||||
private static int pos;
|
||||
|
||||
public static void operate( Hero hero, int pos ) {
|
||||
|
||||
AlchemyPot.hero = hero;
|
||||
AlchemyPot.pos = pos;
|
||||
|
||||
GameScene.selectItem( itemSelector, WndBag.Mode.SEED, TXT_SELECT_SEED );
|
||||
}
|
||||
|
||||
private static final WndBag.Listener itemSelector = new WndBag.Listener() {
|
||||
@Override
|
||||
public void onSelect( Item item ) {
|
||||
if (item != null) {
|
||||
item.cast( hero, pos );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.features;
|
||||
|
||||
import com.watabou.noosa.Camera;
|
||||
import com.watabou.noosa.Game;
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Badges;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.InterlevelScene;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.sprites.MobSprite;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.windows.WndOptions;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class Chasm {
|
||||
|
||||
private static final String TXT_CHASM = "Chasm";
|
||||
private static final String TXT_YES = "Yes, I know what I'm doing";
|
||||
private static final String TXT_NO = "No, I changed my mind";
|
||||
private static final String TXT_JUMP =
|
||||
"Do you really want to jump into the chasm? You can probably die.";
|
||||
|
||||
public static boolean jumpConfirmed = false;
|
||||
|
||||
public static void heroJump( final Hero hero ) {
|
||||
GameScene.show(
|
||||
new WndOptions( TXT_CHASM, TXT_JUMP, TXT_YES, TXT_NO ) {
|
||||
@Override
|
||||
protected void onSelect( int index ) {
|
||||
if (index == 0) {
|
||||
jumpConfirmed = true;
|
||||
hero.resume();
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static void heroFall( int pos ) {
|
||||
|
||||
jumpConfirmed = false;
|
||||
|
||||
Sample.INSTANCE.play( Assets.SND_FALLING );
|
||||
|
||||
if (Dungeon.hero.isAlive()) {
|
||||
Dungeon.hero.interrupt();
|
||||
InterlevelScene.mode = InterlevelScene.Mode.FALL;
|
||||
if (Dungeon.level instanceof RegularLevel) {
|
||||
Room room = ((RegularLevel)Dungeon.level).room( pos );
|
||||
InterlevelScene.fallIntoPit = room != null && room.type == Room.Type.WEAK_FLOOR;
|
||||
} else {
|
||||
InterlevelScene.fallIntoPit = false;
|
||||
}
|
||||
Game.switchScene( InterlevelScene.class );
|
||||
} else {
|
||||
Dungeon.hero.sprite.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void heroLand() {
|
||||
|
||||
Hero hero = Dungeon.hero;
|
||||
|
||||
hero.sprite.burst( hero.sprite.blood(), 10 );
|
||||
Camera.main.shake( 4, 0.2f );
|
||||
|
||||
Buff.prolong( hero, Cripple.class, Cripple.DURATION );
|
||||
hero.damage( Random.IntRange( hero.HT / 3, hero.HT / 2 ), new Hero.Doom() {
|
||||
@Override
|
||||
public void onDeath() {
|
||||
Badges.validateDeathFromFalling();
|
||||
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.FALL, Dungeon.depth ) );
|
||||
GLog.n( "You fell to death..." );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
public static void mobFall( Mob mob ) {
|
||||
// Destroy instead of kill to prevent dropping loot
|
||||
mob.destroy();
|
||||
|
||||
((MobSprite)mob.sprite).fall();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.features;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class Door {
|
||||
|
||||
public static void enter( int pos ) {
|
||||
Level.set( pos, Terrain.OPEN_DOOR );
|
||||
GameScene.updateMap( pos );
|
||||
Dungeon.observe();
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
Sample.INSTANCE.play( Assets.SND_OPEN );
|
||||
}
|
||||
}
|
||||
|
||||
public static void leave( int pos ) {
|
||||
if (Dungeon.level.heaps.get( pos ) == null) {
|
||||
Level.set( pos, Terrain.DOOR );
|
||||
GameScene.updateMap( pos );
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.features;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Barkskin;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.HeroSubClass;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.LeafParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Dewdrop;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfHerbalism.Herbalism;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class HighGrass {
|
||||
|
||||
public static void trample( Level level, int pos, Char ch ) {
|
||||
|
||||
Level.set( pos, Terrain.GRASS );
|
||||
GameScene.updateMap( pos );
|
||||
|
||||
int herbalismLevel = 0;
|
||||
if (ch != null) {
|
||||
Herbalism herbalism = ch.buff( Herbalism.class );
|
||||
if (herbalism != null) {
|
||||
herbalismLevel = herbalism.level;
|
||||
}
|
||||
}
|
||||
|
||||
// Seed
|
||||
if (herbalismLevel >= 0 && Random.Int( 18 ) <= Random.Int( herbalismLevel + 1 )) {
|
||||
level.drop( Generator.random( Generator.Category.SEED ), pos ).sprite.drop();
|
||||
}
|
||||
|
||||
// Dew
|
||||
if (herbalismLevel >= 0 && Random.Int( 6 ) <= Random.Int( herbalismLevel + 1 )) {
|
||||
level.drop( new Dewdrop(), pos ).sprite.drop();
|
||||
}
|
||||
|
||||
int leaves = 4;
|
||||
|
||||
// Barkskin
|
||||
if (ch instanceof Hero && ((Hero)ch).subClass == HeroSubClass.WARDEN) {
|
||||
Buff.affect( ch, Barkskin.class ).level( ch.HT / 3 );
|
||||
leaves = 8;
|
||||
}
|
||||
|
||||
CellEmitter.get( pos ).burst( LeafParticle.LEVEL_SPECIFIC, leaves );
|
||||
Dungeon.observe();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class ArmoryPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
Room.Door entrance = room.entrance();
|
||||
Point statue = null;
|
||||
if (entrance.x == room.left) {
|
||||
statue = new Point( room.right-1, Random.Int( 2 ) == 0 ? room.top+1 : room.bottom-1 );
|
||||
} else if (entrance.x == room.right) {
|
||||
statue = new Point( room.left+1, Random.Int( 2 ) == 0 ? room.top+1 : room.bottom-1 );
|
||||
} else if (entrance.y == room.top) {
|
||||
statue = new Point( Random.Int( 2 ) == 0 ? room.left+1 : room.right-1, room.bottom-1 );
|
||||
} else if (entrance.y == room.bottom) {
|
||||
statue = new Point( Random.Int( 2 ) == 0 ? room.left+1 : room.right-1, room.top+1 );
|
||||
}
|
||||
if (statue != null) {
|
||||
set( level, statue, Terrain.STATUE );
|
||||
}
|
||||
|
||||
int n = Random.IntRange( 2, 3 );
|
||||
for (int i=0; i < n; i++) {
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (level.map[pos] != Terrain.EMPTY || level.heaps.get( pos ) != null);
|
||||
level.drop( prize( level ), pos );
|
||||
}
|
||||
|
||||
entrance.set( Room.Door.Type.LOCKED );
|
||||
level.addItemToSpawn( new IronKey( Dungeon.depth ) );
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
return Generator.random( Random.oneOf(
|
||||
Generator.Category.ARMOR,
|
||||
Generator.Category.WEAPON
|
||||
) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class BlacksmithPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.FIRE_TRAP );
|
||||
fill( level, room, 2, Terrain.EMPTY_SP );
|
||||
|
||||
for (int i=0; i < 2; i++) {
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (level.map[pos] != Terrain.EMPTY_SP);
|
||||
level.drop(
|
||||
Generator.random( Random.oneOf(
|
||||
Generator.Category.ARMOR,
|
||||
Generator.Category.WEAPON
|
||||
) ), pos );
|
||||
}
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.UNLOCKED );
|
||||
drawInside( level, room, door, 1, Terrain.EMPTY );
|
||||
}
|
||||
|
||||
Blacksmith npc = new Blacksmith();
|
||||
do {
|
||||
npc.pos = room.random( 1 );
|
||||
} while (level.heaps.get( npc.pos ) != null);
|
||||
level.mobs.add( npc );
|
||||
Actor.occupyCell( npc );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
|
||||
public class BossExitPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
}
|
||||
|
||||
level.exit = room.top * Level.WIDTH + (room.left + room.right) / 2;
|
||||
set( level, level.exit, Terrain.LOCKED_EXIT );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
|
||||
public class CryptPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
Point c = room.center();
|
||||
int cx = c.x;
|
||||
int cy = c.y;
|
||||
|
||||
Room.Door entrance = room.entrance();
|
||||
|
||||
entrance.set( Room.Door.Type.LOCKED );
|
||||
level.addItemToSpawn( new IronKey( Dungeon.depth ) );
|
||||
|
||||
if (entrance.x == room.left) {
|
||||
set( level, new Point( room.right-1, room.top+1 ), Terrain.STATUE );
|
||||
set( level, new Point( room.right-1, room.bottom-1 ), Terrain.STATUE );
|
||||
cx = room.right - 2;
|
||||
} else if (entrance.x == room.right) {
|
||||
set( level, new Point( room.left+1, room.top+1 ), Terrain.STATUE );
|
||||
set( level, new Point( room.left+1, room.bottom-1 ), Terrain.STATUE );
|
||||
cx = room.left + 2;
|
||||
} else if (entrance.y == room.top) {
|
||||
set( level, new Point( room.left+1, room.bottom-1 ), Terrain.STATUE );
|
||||
set( level, new Point( room.right-1, room.bottom-1 ), Terrain.STATUE );
|
||||
cy = room.bottom - 2;
|
||||
} else if (entrance.y == room.bottom) {
|
||||
set( level, new Point( room.left+1, room.top+1 ), Terrain.STATUE );
|
||||
set( level, new Point( room.right-1, room.top+1 ), Terrain.STATUE );
|
||||
cy = room.top + 2;
|
||||
}
|
||||
|
||||
level.drop( prize( level ), cx + cy * Level.WIDTH ).type = Type.TOMB;
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
|
||||
Item prize = Generator.random( Generator.Category.ARMOR );
|
||||
|
||||
for (int i=0; i < 3; i++) {
|
||||
Item another = Generator.random( Generator.Category.ARMOR );
|
||||
if (another.level > prize.level) {
|
||||
prize = another;
|
||||
}
|
||||
}
|
||||
|
||||
return prize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
|
||||
public class EntrancePainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
}
|
||||
|
||||
level.entrance = room.random( 1 );
|
||||
set( level, level.entrance, Terrain.ENTRANCE );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
|
||||
public class ExitPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
}
|
||||
|
||||
level.exit = room.random( 1 );
|
||||
set( level, level.exit, Terrain.EXIT );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Foliage;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.plants.Sungrass;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class GardenPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.HIGH_GRASS );
|
||||
fill( level, room, 2, Terrain.GRASS );
|
||||
|
||||
room.entrance().set( Room.Door.Type.REGULAR );
|
||||
|
||||
int bushes = Random.Int( 3 ) == 0 ? (Random.Int( 5 ) == 0 ? 2 : 1) : 0;
|
||||
for (int i=0; i < bushes; i++) {
|
||||
level.plant( new Sungrass.Seed(), room.random() );
|
||||
}
|
||||
|
||||
Foliage light = (Foliage)level.blobs.get( Foliage.class );
|
||||
if (light == null) {
|
||||
light = new Foliage();
|
||||
}
|
||||
for (int i=room.top + 1; i < room.bottom; i++) {
|
||||
for (int j=room.left + 1; j < room.right; j++) {
|
||||
light.seed( j + Level.WIDTH * i, 1 );
|
||||
}
|
||||
}
|
||||
level.blobs.put( Foliage.class, light );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Alchemy;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class LaboratoryPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY_SP );
|
||||
|
||||
Room.Door entrance = room.entrance();
|
||||
|
||||
Point pot = null;
|
||||
if (entrance.x == room.left) {
|
||||
pot = new Point( room.right-1, Random.Int( 2 ) == 0 ? room.top + 1 : room.bottom - 1 );
|
||||
} else if (entrance.x == room.right) {
|
||||
pot = new Point( room.left+1, Random.Int( 2 ) == 0 ? room.top + 1 : room.bottom - 1 );
|
||||
} else if (entrance.y == room.top) {
|
||||
pot = new Point( Random.Int( 2 ) == 0 ? room.left + 1 : room.right - 1, room.bottom-1 );
|
||||
} else if (entrance.y == room.bottom) {
|
||||
pot = new Point( Random.Int( 2 ) == 0 ? room.left + 1 : room.right - 1, room.top+1 );
|
||||
}
|
||||
set( level, pot, Terrain.ALCHEMY );
|
||||
|
||||
Alchemy alchemy = new Alchemy();
|
||||
alchemy.seed( pot.x + Level.WIDTH * pot.y, 1 );
|
||||
level.blobs.put( Alchemy.class, alchemy );
|
||||
|
||||
int n = Random.IntRange( 2, 3 );
|
||||
for (int i=0; i < n; i++) {
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (
|
||||
level.map[pos] != Terrain.EMPTY_SP ||
|
||||
level.heaps.get( pos ) != null);
|
||||
level.drop( prize( level ), pos );
|
||||
}
|
||||
|
||||
entrance.set( Room.Door.Type.LOCKED );
|
||||
level.addItemToSpawn( new IronKey( Dungeon.depth ) );
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
|
||||
Item prize = level.itemToSpanAsPrize();
|
||||
if (prize instanceof Potion) {
|
||||
return prize;
|
||||
} else if (prize != null) {
|
||||
level.addItemToSpawn( prize );
|
||||
}
|
||||
|
||||
return Generator.random( Generator.Category.POTION );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class LibraryPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
Room.Door entrance = room.entrance();
|
||||
Point a = null;
|
||||
Point b = null;
|
||||
|
||||
if (entrance.x == room.left) {
|
||||
a = new Point( room.left+1, entrance.y-1 );
|
||||
b = new Point( room.left+1, entrance.y+1 );
|
||||
fill( level, room.right - 1, room.top + 1, 1, room.height() - 1 , Terrain.BOOKSHELF );
|
||||
} else if (entrance.x == room.right) {
|
||||
a = new Point( room.right-1, entrance.y-1 );
|
||||
b = new Point( room.right-1, entrance.y+1 );
|
||||
fill( level, room.left+1, room.top + 1, 1, room.height() - 1 , Terrain.BOOKSHELF );
|
||||
} else if (entrance.y == room.top) {
|
||||
a = new Point( entrance.x+1, room.top+1 );
|
||||
b = new Point( entrance.x-1, room.top+1 );
|
||||
fill( level, room.left + 1, room.bottom-1, room.width() - 1, 1 , Terrain.BOOKSHELF );
|
||||
} else if (entrance.y == room.bottom) {
|
||||
a = new Point( entrance.x+1, room.bottom-1 );
|
||||
b = new Point( entrance.x-1, room.bottom-1 );
|
||||
fill( level, room.left + 1, room.top+1, room.width() - 1, 1 , Terrain.BOOKSHELF );
|
||||
}
|
||||
if (a != null && level.map[a.x + a.y * Level.WIDTH] == Terrain.EMPTY) {
|
||||
set( level, a, Terrain.STATUE );
|
||||
}
|
||||
if (b != null && level.map[b.x + b.y * Level.WIDTH] == Terrain.EMPTY) {
|
||||
set( level, b, Terrain.STATUE );
|
||||
}
|
||||
|
||||
int n = Random.IntRange( 2, 3 );
|
||||
for (int i=0; i < n; i++) {
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (level.map[pos] != Terrain.EMPTY || level.heaps.get( pos ) != null);
|
||||
level.drop( prize( level), pos );
|
||||
}
|
||||
|
||||
entrance.set( Room.Door.Type.LOCKED );
|
||||
level.addItemToSpawn( new IronKey( Dungeon.depth ) );
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
|
||||
Item prize = level.itemToSpanAsPrize();
|
||||
if (prize instanceof Scroll) {
|
||||
return prize;
|
||||
} else if (prize != null) {
|
||||
level.addItemToSpawn( prize );
|
||||
}
|
||||
|
||||
return Generator.random( Generator.Category.SCROLL );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfAwareness;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfHealth;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfTransmutation;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WellWater;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class MagicWellPainter extends Painter {
|
||||
|
||||
private static final Class<?>[] WATERS =
|
||||
{WaterOfAwareness.class, WaterOfHealth.class, WaterOfTransmutation.class};
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
Point c = room.center();
|
||||
set( level, c.x, c.y, Terrain.WELL );
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<? extends WellWater> waterClass =
|
||||
Dungeon.depth >= Dungeon.transmutation ?
|
||||
WaterOfTransmutation.class :
|
||||
(Class<? extends WellWater>)Random.element( WATERS );
|
||||
|
||||
if (waterClass == WaterOfTransmutation.class) {
|
||||
Dungeon.transmutation = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
WellWater water = (WellWater)level.blobs.get( waterClass );
|
||||
if (water == null) {
|
||||
try {
|
||||
water = waterClass.newInstance();
|
||||
} catch (Exception e) {
|
||||
water = null;
|
||||
}
|
||||
}
|
||||
water.seed( c.x + Level.WIDTH * c.y, 1 );
|
||||
level.blobs.put( waterClass, water );
|
||||
|
||||
room.entrance().set( Room.Door.Type.REGULAR );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Rect;
|
||||
|
||||
public class Painter {
|
||||
|
||||
public static void set( Level level, int cell, int value ) {
|
||||
level.map[cell] = value;
|
||||
}
|
||||
|
||||
public static void set( Level level, int x, int y, int value ) {
|
||||
set( level, x + y * Level.WIDTH, value );
|
||||
}
|
||||
|
||||
public static void set( Level level, Point p, int value ) {
|
||||
set( level, p.x, p.y, value );
|
||||
}
|
||||
|
||||
public static void fill( Level level, int x, int y, int w, int h, int value ) {
|
||||
|
||||
int width = Level.WIDTH;
|
||||
|
||||
int pos = y * width + x;
|
||||
for (int i=y; i < y + h; i++, pos += width) {
|
||||
Arrays.fill( level.map, pos, pos + w, value );
|
||||
}
|
||||
}
|
||||
|
||||
public static void fill( Level level, Rect rect, int value ) {
|
||||
fill( level, rect.left, rect.top, rect.width() + 1, rect.height() + 1, value );
|
||||
}
|
||||
|
||||
public static void fill( Level level, Rect rect, int m, int value ) {
|
||||
fill( level, rect.left + m, rect.top + m, rect.width() + 1 - m*2, rect.height() + 1 - m*2, value );
|
||||
}
|
||||
|
||||
public static void fill( Level level, Rect rect, int l, int t, int r, int b, int value ) {
|
||||
fill( level, rect.left + l, rect.top + t, rect.width() + 1 - (l + r), rect.height() + 1 - (t + b), value );
|
||||
}
|
||||
|
||||
public static Point drawInside( Level level, Room room, Point from, int n, int value ) {
|
||||
|
||||
Point step = new Point();
|
||||
if (from.x == room.left) {
|
||||
step.set( +1, 0 );
|
||||
} else if (from.x == room.right) {
|
||||
step.set( -1, 0 );
|
||||
} else if (from.y == room.top) {
|
||||
step.set( 0, +1 );
|
||||
} else if (from.y == room.bottom) {
|
||||
step.set( 0, -1 );
|
||||
}
|
||||
|
||||
Point p = new Point( from ).offset( step );
|
||||
for (int i=0; i < n; i++) {
|
||||
if (value != -1) {
|
||||
set( level, p, value );
|
||||
}
|
||||
p.offset( step );
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.watabou.utils.Point;
|
||||
|
||||
public class PassagePainter extends Painter {
|
||||
|
||||
private static int pasWidth;
|
||||
private static int pasHeight;
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
pasWidth = room.width() - 2;
|
||||
pasHeight = room.height() - 2;
|
||||
|
||||
int floor = level.tunnelTile();
|
||||
|
||||
ArrayList<Integer> joints = new ArrayList<Integer>();
|
||||
for (Point door : room.connected.values()) {
|
||||
joints.add( xy2p( room, door ) );
|
||||
}
|
||||
Collections.sort( joints );
|
||||
|
||||
int nJoints = joints.size();
|
||||
int perimeter = pasWidth * 2 + pasHeight * 2;
|
||||
|
||||
int start = 0;
|
||||
int maxD = joints.get( 0 ) + perimeter - joints.get( nJoints - 1 );
|
||||
for (int i=1; i < nJoints; i++) {
|
||||
int d = joints.get( i ) - joints.get( i - 1 );
|
||||
if (d > maxD) {
|
||||
maxD = d;
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
|
||||
int end = (start + nJoints - 1) % nJoints;
|
||||
|
||||
int p = joints.get( start );
|
||||
do {
|
||||
set( level, p2xy( room, p ), floor );
|
||||
p = (p + 1) % perimeter;
|
||||
} while (p != joints.get( end ));
|
||||
|
||||
set( level, p2xy( room, p ), floor );
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.TUNNEL );
|
||||
}
|
||||
}
|
||||
|
||||
private static int xy2p( Room room, Point xy ) {
|
||||
if (xy.y == room.top) {
|
||||
|
||||
return (xy.x - room.left - 1);
|
||||
|
||||
} else if (xy.x == room.right) {
|
||||
|
||||
return (xy.y - room.top - 1) + pasWidth;
|
||||
|
||||
} else if (xy.y == room.bottom) {
|
||||
|
||||
return (room.right - xy.x - 1) + pasWidth + pasHeight;
|
||||
|
||||
} else {
|
||||
|
||||
if (xy.y == room.top + 1) {
|
||||
return 0;
|
||||
} else {
|
||||
return (room.bottom - xy.y - 1) + pasWidth * 2 + pasHeight;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static Point p2xy( Room room, int p ) {
|
||||
if (p < pasWidth) {
|
||||
|
||||
return new Point( room.left + 1 + p, room.top + 1);
|
||||
|
||||
} else if (p < pasWidth + pasHeight) {
|
||||
|
||||
return new Point( room.right - 1, room.top + 1 + (p - pasWidth) );
|
||||
|
||||
} else if (p < pasWidth * 2 + pasHeight) {
|
||||
|
||||
return new Point( room.right - 1 - (p - (pasWidth + pasHeight)), room.bottom - 1 );
|
||||
|
||||
} else {
|
||||
|
||||
return new Point( room.left + 1, room.bottom - 1 - (p - (pasWidth * 2 + pasHeight)) );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class PitPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
Room.Door entrance = room.entrance();
|
||||
entrance.set( Room.Door.Type.LOCKED );
|
||||
|
||||
Point well = null;
|
||||
if (entrance.x == room.left) {
|
||||
well = new Point( room.right-1, Random.Int( 2 ) == 0 ? room.top + 1 : room.bottom - 1 );
|
||||
} else if (entrance.x == room.right) {
|
||||
well = new Point( room.left+1, Random.Int( 2 ) == 0 ? room.top + 1 : room.bottom - 1 );
|
||||
} else if (entrance.y == room.top) {
|
||||
well = new Point( Random.Int( 2 ) == 0 ? room.left + 1 : room.right - 1, room.bottom-1 );
|
||||
} else if (entrance.y == room.bottom) {
|
||||
well = new Point( Random.Int( 2 ) == 0 ? room.left + 1 : room.right - 1, room.top+1 );
|
||||
}
|
||||
set( level, well, Terrain.EMPTY_WELL );
|
||||
|
||||
int remains = room.random();
|
||||
while (level.map[remains] == Terrain.EMPTY_WELL) {
|
||||
remains = room.random();
|
||||
}
|
||||
|
||||
level.drop( new IronKey( Dungeon.depth ), remains ).type = Type.SKELETON;
|
||||
|
||||
if (Random.Int( 5 ) == 0) {
|
||||
level.drop( Generator.random( Generator.Category.RING ), remains );
|
||||
} else {
|
||||
level.drop( Generator.random( Random.oneOf(
|
||||
Generator.Category.WEAPON,
|
||||
Generator.Category.ARMOR
|
||||
) ), remains );
|
||||
}
|
||||
|
||||
int n = Random.IntRange( 1, 2 );
|
||||
for (int i=0; i < n; i++) {
|
||||
level.drop( prize( level ), remains );
|
||||
}
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
|
||||
Item prize = level.itemToSpanAsPrize();
|
||||
if (prize != null) {
|
||||
return prize;
|
||||
}
|
||||
|
||||
return Generator.random( Random.oneOf(
|
||||
Generator.Category.POTION,
|
||||
Generator.Category.SCROLL,
|
||||
Generator.Category.FOOD,
|
||||
Generator.Category.GOLD
|
||||
) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Piranha;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfInvisibility;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class PoolPainter extends Painter {
|
||||
|
||||
private static final int NPIRANHAS = 3;
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.WATER );
|
||||
|
||||
Room.Door door = room.entrance();
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
|
||||
int x = -1;
|
||||
int y = -1;
|
||||
if (door.x == room.left) {
|
||||
|
||||
x = room.right - 1;
|
||||
y = room.top + room.height() / 2;
|
||||
|
||||
} else if (door.x == room.right) {
|
||||
|
||||
x = room.left + 1;
|
||||
y = room.top + room.height() / 2;
|
||||
|
||||
} else if (door.y == room.top) {
|
||||
|
||||
x = room.left + room.width() / 2;
|
||||
y = room.bottom - 1;
|
||||
|
||||
} else if (door.y == room.bottom) {
|
||||
|
||||
x = room.left + room.width() / 2;
|
||||
y = room.top + 1;
|
||||
|
||||
}
|
||||
|
||||
int pos = x + y * Level.WIDTH;
|
||||
level.drop( prize( level ), pos ).type =
|
||||
Random.Int( 3 ) == 0 ? Heap.Type.CHEST : Heap.Type.HEAP;
|
||||
set( level, pos, Terrain.PEDESTAL );
|
||||
|
||||
level.addItemToSpawn( new PotionOfInvisibility() );
|
||||
|
||||
for (int i=0; i < NPIRANHAS; i++) {
|
||||
Piranha piranha = new Piranha();
|
||||
do {
|
||||
piranha.pos = room.random();
|
||||
} while (level.map[piranha.pos] != Terrain.WATER|| Actor.findChar( piranha.pos ) != null);
|
||||
level.mobs.add( piranha );
|
||||
Actor.occupyCell( piranha );
|
||||
}
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
|
||||
Item prize = level.itemToSpanAsPrize();
|
||||
if (prize != null) {
|
||||
return prize;
|
||||
}
|
||||
|
||||
prize = Generator.random( Random.oneOf(
|
||||
Generator.Category.WEAPON,
|
||||
Generator.Category.ARMOR
|
||||
) );
|
||||
|
||||
for (int i=0; i < 4; i++) {
|
||||
Item another = Generator.random( Random.oneOf(
|
||||
Generator.Category.WEAPON,
|
||||
Generator.Category.ARMOR
|
||||
) );
|
||||
if (another.level > prize.level) {
|
||||
prize = another;
|
||||
}
|
||||
}
|
||||
|
||||
return prize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.RatKing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.missiles.MissileWeapon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class RatKingPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY_SP );
|
||||
|
||||
Room.Door entrance = room.entrance();
|
||||
entrance.set( Room.Door.Type.HIDDEN );
|
||||
int door = entrance.x + entrance.y * Level.WIDTH;
|
||||
|
||||
for (int i=room.left + 1; i < room.right; i++) {
|
||||
addChest( level, (room.top + 1) * Level.WIDTH + i, door );
|
||||
addChest( level, (room.bottom - 1) * Level.WIDTH + i, door );
|
||||
}
|
||||
|
||||
for (int i=room.top + 2; i < room.bottom - 1; i++) {
|
||||
addChest( level, i * Level.WIDTH + room.left + 1, door );
|
||||
addChest( level, i * Level.WIDTH + room.right - 1, door );
|
||||
}
|
||||
|
||||
RatKing king = new RatKing();
|
||||
king.pos = room.random( 1 );
|
||||
level.mobs.add( king );
|
||||
}
|
||||
|
||||
private static void addChest( Level level, int pos, int door ) {
|
||||
|
||||
if (pos == door - 1 ||
|
||||
pos == door + 1 ||
|
||||
pos == door - Level.WIDTH ||
|
||||
pos == door + Level.WIDTH) {
|
||||
return;
|
||||
}
|
||||
|
||||
Item prize;
|
||||
switch (Random.Int( 10 )) {
|
||||
case 0:
|
||||
prize = Generator.random( Generator.Category.WEAPON );
|
||||
if (prize instanceof MissileWeapon) {
|
||||
prize.quantity( 1 );
|
||||
} else {
|
||||
prize.degrade( Random.Int( 3 ) );
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
prize = Generator.random( Generator.Category.ARMOR ).degrade( Random.Int( 3 ) );
|
||||
break;
|
||||
default:
|
||||
prize = new Gold( Random.IntRange( 1, 5 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
level.drop( prize, pos ).type = Heap.Type.CHEST;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.ImpShopkeeper;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Shopkeeper;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Ankh;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Torch;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.armor.*;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.ScrollHolder;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.SeedPouch;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.bags.WandHolster;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.food.OverpricedRation;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfHealing;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfIdentify;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfMagicMapping;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfRemoveCurse;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.melee.*;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.LastShopLevel;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class ShopPainter extends Painter {
|
||||
|
||||
private static int pasWidth;
|
||||
private static int pasHeight;
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY_SP );
|
||||
|
||||
pasWidth = room.width() - 2;
|
||||
pasHeight = room.height() - 2;
|
||||
int per = pasWidth * 2 + pasHeight * 2;
|
||||
|
||||
Item[] range = range();
|
||||
|
||||
int pos = xy2p( room, room.entrance() ) + (per - range.length) / 2;
|
||||
for (int i=0; i < range.length; i++) {
|
||||
|
||||
Point xy = p2xy( room, (pos + per) % per );
|
||||
int cell = xy.x + xy.y * Level.WIDTH;
|
||||
|
||||
if (level.heaps.get( cell ) != null) {
|
||||
do {
|
||||
cell = room.random();
|
||||
} while (level.heaps.get( cell ) != null);
|
||||
}
|
||||
|
||||
level.drop( range[i], cell ).type = Heap.Type.FOR_SALE;
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
placeShopkeeper( level, room );
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
}
|
||||
}
|
||||
|
||||
private static Item[] range() {
|
||||
|
||||
ArrayList<Item> items = new ArrayList<Item>();
|
||||
|
||||
switch (Dungeon.depth) {
|
||||
|
||||
case 6:
|
||||
items.add( (Random.Int( 2 ) == 0 ? new Quarterstaff() : new Spear()).identify() );
|
||||
items.add( new LeatherArmor().identify() );
|
||||
items.add( new SeedPouch() );
|
||||
break;
|
||||
|
||||
case 11:
|
||||
items.add( (Random.Int( 2 ) == 0 ? new Sword() : new Mace()).identify() );
|
||||
items.add( new MailArmor().identify() );
|
||||
items.add( new ScrollHolder() );
|
||||
break;
|
||||
|
||||
case 16:
|
||||
items.add( (Random.Int( 2 ) == 0 ? new Longsword() : new BattleAxe()).identify() );
|
||||
items.add( new ScaleArmor().identify() );
|
||||
items.add( new WandHolster() );
|
||||
break;
|
||||
|
||||
case 21:
|
||||
switch (Random.Int( 3 )) {
|
||||
case 0:
|
||||
items.add( new Glaive().identify() );
|
||||
break;
|
||||
case 1:
|
||||
items.add( new WarHammer().identify() );
|
||||
break;
|
||||
case 2:
|
||||
items.add( new PlateArmor().identify() );
|
||||
break;
|
||||
}
|
||||
items.add( new Torch() );
|
||||
items.add( new Torch() );
|
||||
break;
|
||||
}
|
||||
|
||||
items.add( new PotionOfHealing() );
|
||||
for (int i=0; i < 3; i++) {
|
||||
items.add( Generator.random( Generator.Category.POTION ) );
|
||||
}
|
||||
|
||||
items.add( new ScrollOfIdentify() );
|
||||
items.add( new ScrollOfRemoveCurse() );
|
||||
items.add( new ScrollOfMagicMapping() );
|
||||
items.add( Generator.random( Generator.Category.SCROLL ) );
|
||||
|
||||
items.add( new OverpricedRation() );
|
||||
items.add( new OverpricedRation() );
|
||||
|
||||
items.add( new Ankh() );
|
||||
|
||||
Item[] range =items.toArray( new Item[0] );
|
||||
Random.shuffle( range );
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
private static void placeShopkeeper( Level level, Room room ) {
|
||||
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (level.heaps.get( pos ) != null);
|
||||
|
||||
Mob shopkeeper = level instanceof LastShopLevel ? new ImpShopkeeper() : new Shopkeeper();
|
||||
shopkeeper.pos = pos;
|
||||
level.mobs.add( shopkeeper );
|
||||
|
||||
if (level instanceof LastShopLevel) {
|
||||
for (int i=0; i < Level.NEIGHBOURS9.length; i++) {
|
||||
int p = shopkeeper.pos + Level.NEIGHBOURS9[i];
|
||||
if (level.map[p] == Terrain.EMPTY_SP) {
|
||||
level.map[p] = Terrain.WATER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int xy2p( Room room, Point xy ) {
|
||||
if (xy.y == room.top) {
|
||||
|
||||
return (xy.x - room.left - 1);
|
||||
|
||||
} else if (xy.x == room.right) {
|
||||
|
||||
return (xy.y - room.top - 1) + pasWidth;
|
||||
|
||||
} else if (xy.y == room.bottom) {
|
||||
|
||||
return (room.right - xy.x - 1) + pasWidth + pasHeight;
|
||||
|
||||
} else {
|
||||
|
||||
if (xy.y == room.top + 1) {
|
||||
return 0;
|
||||
} else {
|
||||
return (room.bottom - xy.y - 1) + pasWidth * 2 + pasHeight;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static Point p2xy( Room room, int p ) {
|
||||
if (p < pasWidth) {
|
||||
|
||||
return new Point( room.left + 1 + p, room.top + 1);
|
||||
|
||||
} else if (p < pasWidth + pasHeight) {
|
||||
|
||||
return new Point( room.right - 1, room.top + 1 + (p - pasWidth) );
|
||||
|
||||
} else if (p < pasWidth * 2 + pasHeight) {
|
||||
|
||||
return new Point( room.right - 1 - (p - (pasWidth + pasHeight)), room.bottom - 1 );
|
||||
|
||||
} else {
|
||||
|
||||
return new Point( room.left + 1, room.bottom - 1 - (p - (pasWidth * 2 + pasHeight)) );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class StandardPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
}
|
||||
|
||||
if (!Dungeon.bossLevel() && Random.Int( 5 ) == 0) {
|
||||
switch (Random.Int( 6 )) {
|
||||
case 0:
|
||||
if (level.feeling != Level.Feeling.GRASS) {
|
||||
if (Math.min( room.width(), room.height() ) >= 4 && Math.max( room.width(), room.height() ) >= 6) {
|
||||
paintGraveyard( level, room );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
// Burned room
|
||||
}
|
||||
case 1:
|
||||
if (Dungeon.depth > 1) {
|
||||
paintBurned( level, room );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (Math.max( room.width(), room.height() ) >= 4) {
|
||||
paintStriped( level, room );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (room.width() >= 6 && room.height() >= 6) {
|
||||
paintStudy( level, room );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (level.feeling != Level.Feeling.WATER) {
|
||||
if (room.connected.size() == 2 && room.width() >= 4 && room.height() >= 4) {
|
||||
paintBridge( level, room );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
// Fissure
|
||||
}
|
||||
case 5:
|
||||
if (!Dungeon.bossLevel() && !Dungeon.bossLevel( Dungeon.depth + 1 ) &&
|
||||
Math.min( room.width(), room.height() ) >= 5) {
|
||||
paintFissure( level, room );
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
}
|
||||
|
||||
private static void paintBurned( Level level, Room room ) {
|
||||
for (int i=room.top + 1; i < room.bottom; i++) {
|
||||
for (int j=room.left + 1; j < room.right; j++) {
|
||||
int t = Terrain.EMBERS;
|
||||
switch (Random.Int( 5 )) {
|
||||
case 0:
|
||||
t = Terrain.EMPTY;
|
||||
break;
|
||||
case 1:
|
||||
t = Terrain.FIRE_TRAP;
|
||||
break;
|
||||
case 2:
|
||||
t = Terrain.SECRET_FIRE_TRAP;
|
||||
break;
|
||||
case 3:
|
||||
t = Terrain.INACTIVE_TRAP;
|
||||
break;
|
||||
}
|
||||
level.map[i * Level.WIDTH + j] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void paintGraveyard( Level level, Room room ) {
|
||||
fill( level, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1 , Terrain.GRASS );
|
||||
|
||||
int w = room.width() - 1;
|
||||
int h = room.height() - 1;
|
||||
int nGraves = Math.max( w, h ) / 2;
|
||||
|
||||
int index = Random.Int( nGraves );
|
||||
|
||||
int shift = Random.Int( 2 );
|
||||
for (int i=0; i < nGraves; i++) {
|
||||
int pos = w > h ?
|
||||
room.left + 1 + shift + i * 2 + (room.top + 2 + Random.Int( h-2 )) * Level.WIDTH :
|
||||
(room.left + 2 + Random.Int( w-2 )) + (room.top + 1 + shift + i * 2) * Level.WIDTH;
|
||||
level.drop( i == index ? Generator.random() : new Gold(), pos ).type = Heap.Type.TOMB;
|
||||
}
|
||||
}
|
||||
|
||||
private static void paintStriped( Level level, Room room ) {
|
||||
fill( level, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1 , Terrain.EMPTY_SP );
|
||||
|
||||
if (room.width() > room.height()) {
|
||||
for (int i=room.left + 2; i < room.right; i += 2) {
|
||||
fill( level, i, room.top + 1, 1, room.height() - 1, Terrain.HIGH_GRASS );
|
||||
}
|
||||
} else {
|
||||
for (int i=room.top + 2; i < room.bottom; i += 2) {
|
||||
fill( level, room.left + 1, i, room.width() - 1, 1, Terrain.HIGH_GRASS );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void paintStudy( Level level, Room room ) {
|
||||
fill( level, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1 , Terrain.BOOKSHELF );
|
||||
fill( level, room.left + 2, room.top + 2, room.width() - 3, room.height() - 3 , Terrain.EMPTY_SP );
|
||||
|
||||
for (Point door : room.connected.values()) {
|
||||
if (door.x == room.left) {
|
||||
set( level, door.x + 1, door.y, Terrain.EMPTY );
|
||||
} else if (door.x == room.right) {
|
||||
set( level, door.x - 1, door.y, Terrain.EMPTY );
|
||||
} else if (door.y == room.top) {
|
||||
set( level, door.x, door.y + 1, Terrain.EMPTY );
|
||||
} else if (door.y == room.bottom) {
|
||||
set( level, door.x , door.y - 1, Terrain.EMPTY );
|
||||
}
|
||||
}
|
||||
|
||||
set( level, room.center(), Terrain.PEDESTAL );
|
||||
}
|
||||
|
||||
private static void paintBridge( Level level, Room room ) {
|
||||
|
||||
fill( level, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1 ,
|
||||
!Dungeon.bossLevel() && !Dungeon.bossLevel( Dungeon.depth + 1 ) && Random.Int( 3 ) == 0 ?
|
||||
Terrain.CHASM :
|
||||
Terrain.WATER );
|
||||
|
||||
Point door1 = null;
|
||||
Point door2 = null;
|
||||
for (Point p : room.connected.values()) {
|
||||
if (door1 == null) {
|
||||
door1 = p;
|
||||
} else {
|
||||
door2 = p;
|
||||
}
|
||||
}
|
||||
|
||||
if ((door1.x == room.left && door2.x == room.right) ||
|
||||
(door1.x == room.right && door2.x == room.left)) {
|
||||
|
||||
int s = room.width() / 2;
|
||||
|
||||
drawInside( level, room, door1, s, Terrain.EMPTY_SP );
|
||||
drawInside( level, room, door2, s, Terrain.EMPTY_SP );
|
||||
fill( level, room.center().x, Math.min( door1.y, door2.y ), 1, Math.abs( door1.y - door2.y ) + 1, Terrain.EMPTY_SP );
|
||||
|
||||
} else
|
||||
if ((door1.y == room.top && door2.y == room.bottom) ||
|
||||
(door1.y == room.bottom && door2.y == room.top)) {
|
||||
|
||||
int s = room.height() / 2;
|
||||
|
||||
drawInside( level, room, door1, s, Terrain.EMPTY_SP );
|
||||
drawInside( level, room, door2, s, Terrain.EMPTY_SP );
|
||||
fill( level, Math.min( door1.x, door2.x ), room.center().y, Math.abs( door1.x - door2.x ) + 1, 1, Terrain.EMPTY_SP );
|
||||
|
||||
} else
|
||||
if (door1.x == door2.x) {
|
||||
|
||||
fill( level, door1.x == room.left ? room.left + 1 : room.right - 1, Math.min( door1.y, door2.y ), 1, Math.abs( door1.y - door2.y ) + 1, Terrain.EMPTY_SP );
|
||||
|
||||
} else
|
||||
if (door1.y == door2.y) {
|
||||
|
||||
fill( level, Math.min( door1.x, door2.x ), door1.y == room.top ? room.top + 1 : room.bottom - 1, Math.abs( door1.x - door2.x ) + 1, 1, Terrain.EMPTY_SP );
|
||||
|
||||
} else
|
||||
if (door1.y == room.top || door1.y == room.bottom) {
|
||||
|
||||
drawInside( level, room, door1, Math.abs( door1.y - door2.y ), Terrain.EMPTY_SP );
|
||||
drawInside( level, room, door2, Math.abs( door1.x - door2.x ), Terrain.EMPTY_SP );
|
||||
|
||||
} else
|
||||
if (door1.x == room.left || door1.x == room.right) {
|
||||
|
||||
drawInside( level, room, door1, Math.abs( door1.x - door2.x ), Terrain.EMPTY_SP );
|
||||
drawInside( level, room, door2, Math.abs( door1.y - door2.y ), Terrain.EMPTY_SP );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static void paintFissure( Level level, Room room ) {
|
||||
fill( level, room.left + 1, room.top + 1, room.width() - 1, room.height() - 1 ,Terrain.EMPTY );
|
||||
|
||||
for (int i=room.top + 2; i < room.bottom - 1; i++) {
|
||||
for (int j=room.left + 2; j < room.right - 1; j++) {
|
||||
int v = Math.min( i - room.top, room.bottom - i );
|
||||
int h = Math.min( j - room.left, room.right - j );
|
||||
if (Math.min( v, h ) > 2 || Random.Int( 2 ) == 0) {
|
||||
set( level, j, i, Terrain.CHASM );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Statue;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
|
||||
public class StatuePainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
Point c = room.center();
|
||||
int cx = c.x;
|
||||
int cy = c.y;
|
||||
|
||||
Room.Door door = room.entrance();
|
||||
|
||||
door.set( Room.Door.Type.LOCKED );
|
||||
level.addItemToSpawn( new IronKey( Dungeon.depth ) );
|
||||
|
||||
if (door.x == room.left) {
|
||||
|
||||
fill( level, room.right - 1, room.top + 1, 1, room.height() - 1 , Terrain.STATUE );
|
||||
cx = room.right - 2;
|
||||
|
||||
} else if (door.x == room.right) {
|
||||
|
||||
fill( level, room.left + 1, room.top + 1, 1, room.height() - 1 , Terrain.STATUE );
|
||||
cx = room.left + 2;
|
||||
|
||||
} else if (door.y == room.top) {
|
||||
|
||||
fill( level, room.left + 1, room.bottom - 1, room.width() - 1, 1 , Terrain.STATUE );
|
||||
cy = room.bottom - 2;
|
||||
|
||||
} else if (door.y == room.bottom) {
|
||||
|
||||
fill( level, room.left + 1, room.top + 1, room.width() - 1, 1 , Terrain.STATUE );
|
||||
cy = room.top + 2;
|
||||
|
||||
}
|
||||
|
||||
Statue statue = new Statue();
|
||||
statue.pos = cx + cy * Level.WIDTH;
|
||||
level.mobs.add( statue );
|
||||
Actor.occupyCell( statue );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLiquidFlame;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class StoragePainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
final int floor = Terrain.EMPTY_SP;
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, floor );
|
||||
|
||||
int n = Random.IntRange( 3, 4 );
|
||||
for (int i=0; i < n; i++) {
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (level.map[pos] != floor);
|
||||
level.drop( prize( level ), pos );
|
||||
}
|
||||
|
||||
room.entrance().set( Room.Door.Type.BARRICADE );
|
||||
level.addItemToSpawn( new PotionOfLiquidFlame() );
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
|
||||
Item prize = level.itemToSpanAsPrize();
|
||||
if (prize != null) {
|
||||
return prize;
|
||||
}
|
||||
|
||||
return Generator.random( Random.oneOf(
|
||||
Generator.Category.POTION,
|
||||
Generator.Category.SCROLL,
|
||||
Generator.Category.FOOD,
|
||||
Generator.Category.GOLD
|
||||
) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.potions.PotionOfLevitation;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class TrapsPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
Integer traps[] = {
|
||||
Terrain.TOXIC_TRAP, Terrain.TOXIC_TRAP, Terrain.TOXIC_TRAP,
|
||||
Terrain.PARALYTIC_TRAP, Terrain.PARALYTIC_TRAP,
|
||||
!Dungeon.bossLevel( Dungeon.depth + 1 ) ? Terrain.CHASM : Terrain.SUMMONING_TRAP };
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Random.element( traps ) );
|
||||
|
||||
Room.Door door = room.entrance();
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
|
||||
int lastRow = level.map[room.left + 1 + (room.top + 1) * Level.WIDTH] == Terrain.CHASM ? Terrain.CHASM : Terrain.EMPTY;
|
||||
|
||||
int x = -1;
|
||||
int y = -1;
|
||||
if (door.x == room.left) {
|
||||
x = room.right - 1;
|
||||
y = room.top + room.height() / 2;
|
||||
fill( level, x, room.top + 1, 1, room.height() - 1 , lastRow );
|
||||
} else if (door.x == room.right) {
|
||||
x = room.left + 1;
|
||||
y = room.top + room.height() / 2;
|
||||
fill( level, x, room.top + 1, 1, room.height() - 1 , lastRow );
|
||||
} else if (door.y == room.top) {
|
||||
x = room.left + room.width() / 2;
|
||||
y = room.bottom - 1;
|
||||
fill( level, room.left + 1, y, room.width() - 1, 1 , lastRow );
|
||||
} else if (door.y == room.bottom) {
|
||||
x = room.left + room.width() / 2;
|
||||
y = room.top + 1;
|
||||
fill( level, room.left + 1, y, room.width() - 1, 1 , lastRow );
|
||||
}
|
||||
|
||||
int pos = x + y * Level.WIDTH;
|
||||
if (Random.Int( 3 ) == 0) {
|
||||
if (lastRow == Terrain.CHASM) {
|
||||
set( level, pos, Terrain.EMPTY );
|
||||
}
|
||||
level.drop( prize( level ), pos ).type = Heap.Type.CHEST;
|
||||
} else {
|
||||
set( level, pos, Terrain.PEDESTAL );
|
||||
level.drop( prize( level ), pos );
|
||||
}
|
||||
|
||||
level.addItemToSpawn( new PotionOfLevitation() );
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
|
||||
Item prize = level.itemToSpanAsPrize();
|
||||
if (prize != null) {
|
||||
return prize;
|
||||
}
|
||||
|
||||
prize = Generator.random( Random.oneOf(
|
||||
Generator.Category.WEAPON,
|
||||
Generator.Category.ARMOR
|
||||
) );
|
||||
|
||||
for (int i=0; i < 3; i++) {
|
||||
Item another = Generator.random( Random.oneOf(
|
||||
Generator.Category.WEAPON,
|
||||
Generator.Category.ARMOR
|
||||
) );
|
||||
if (another.level > prize.level) {
|
||||
prize = another;
|
||||
}
|
||||
}
|
||||
|
||||
return prize;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class TreasuryPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
set( level, room.center(), Terrain.STATUE );
|
||||
|
||||
Heap.Type heapType = Random.Int( 2 ) == 0 ? Heap.Type.CHEST : Heap.Type.HEAP;
|
||||
|
||||
int n = Random.IntRange( 2, 3 );
|
||||
for (int i=0; i < n; i++) {
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (level.map[pos] != Terrain.EMPTY || level.heaps.get( pos ) != null);
|
||||
level.drop( new Gold().random(), pos ).type = heapType;
|
||||
}
|
||||
|
||||
if (heapType == Heap.Type.HEAP) {
|
||||
for (int i=0; i < 6; i++) {
|
||||
int pos;
|
||||
do {
|
||||
pos = room.random();
|
||||
} while (level.map[pos] != Terrain.EMPTY);
|
||||
level.drop( new Gold( Random.IntRange( 1, 3 ) ), pos );
|
||||
}
|
||||
}
|
||||
|
||||
room.entrance().set( Room.Door.Type.LOCKED );
|
||||
level.addItemToSpawn( new IronKey( Dungeon.depth ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class TunnelPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
int floor = level.tunnelTile();
|
||||
|
||||
Point c = room.center();
|
||||
|
||||
if (room.width() > room.height() || (room.width() == room.height() && Random.Int( 2 ) == 0)) {
|
||||
|
||||
int from = room.right - 1;
|
||||
int to = room.left + 1;
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
|
||||
int step = door.y < c.y ? +1 : -1;
|
||||
|
||||
if (door.x == room.left) {
|
||||
|
||||
from = room.left + 1;
|
||||
for (int i=door.y; i != c.y; i += step) {
|
||||
set( level, from, i, floor );
|
||||
}
|
||||
|
||||
} else if (door.x == room.right) {
|
||||
|
||||
to = room.right - 1;
|
||||
for (int i=door.y; i != c.y; i += step) {
|
||||
set( level, to, i, floor );
|
||||
}
|
||||
|
||||
} else {
|
||||
if (door.x < from) {
|
||||
from = door.x;
|
||||
}
|
||||
if (door.x > to) {
|
||||
to = door.x;
|
||||
}
|
||||
|
||||
for (int i=door.y+step; i != c.y; i += step) {
|
||||
set( level, door.x, i, floor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=from; i <= to; i++) {
|
||||
set( level, i, c.y, floor );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
int from = room.bottom - 1;
|
||||
int to = room.top + 1;
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
|
||||
int step = door.x < c.x ? +1 : -1;
|
||||
|
||||
if (door.y == room.top) {
|
||||
|
||||
from = room.top + 1;
|
||||
for (int i=door.x; i != c.x; i += step) {
|
||||
set( level, i, from, floor );
|
||||
}
|
||||
|
||||
} else if (door.y == room.bottom) {
|
||||
|
||||
to = room.bottom - 1;
|
||||
for (int i=door.x; i != c.x; i += step) {
|
||||
set( level, i, to, floor );
|
||||
}
|
||||
|
||||
} else {
|
||||
if (door.y < from) {
|
||||
from = door.y;
|
||||
}
|
||||
if (door.y > to) {
|
||||
to = door.y;
|
||||
}
|
||||
|
||||
for (int i=door.x+step; i != c.x; i += step) {
|
||||
set( level, i, door.y, floor );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=from; i <= to; i++) {
|
||||
set( level, c.x, i, floor );
|
||||
}
|
||||
}
|
||||
|
||||
for (Room.Door door : room.connected.values()) {
|
||||
door.set( Room.Door.Type.TUNNEL );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap.Type;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.GoldenKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.keys.IronKey;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class VaultPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.EMPTY );
|
||||
|
||||
int cx = (room.left + room.right) / 2;
|
||||
int cy = (room.top + room.bottom) / 2;
|
||||
int c = cx + cy * Level.WIDTH;
|
||||
|
||||
switch (Random.Int( 3 )) {
|
||||
|
||||
case 0:
|
||||
level.drop( prize( level ), c ).type = Type.LOCKED_CHEST;
|
||||
level.addItemToSpawn( new GoldenKey( Dungeon.depth ) );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
Item i1, i2;
|
||||
do {
|
||||
i1 = prize( level );
|
||||
i2 = prize( level );
|
||||
} while (i1.getClass() == i2.getClass());
|
||||
level.drop( i1, c ).type = Type.CRYSTAL_CHEST;
|
||||
level.drop( i2, c + Level.NEIGHBOURS8[Random.Int( 8 )]).type = Type.CRYSTAL_CHEST;
|
||||
level.addItemToSpawn( new GoldenKey( Dungeon.depth ) );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
level.drop( prize( level ), c );
|
||||
set( level, c, Terrain.PEDESTAL );
|
||||
break;
|
||||
}
|
||||
|
||||
room.entrance().set( Room.Door.Type.LOCKED );
|
||||
level.addItemToSpawn( new IronKey( Dungeon.depth ) );
|
||||
}
|
||||
|
||||
private static Item prize( Level level ) {
|
||||
return Generator.random( Random.oneOf(
|
||||
Generator.Category.WAND,
|
||||
Generator.Category.RING
|
||||
) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.painters;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.watabou.utils.Point;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class WeakFloorPainter extends Painter {
|
||||
|
||||
public static void paint( Level level, Room room ) {
|
||||
|
||||
fill( level, room, Terrain.WALL );
|
||||
fill( level, room, 1, Terrain.CHASM );
|
||||
|
||||
Room.Door door = room.entrance();
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
|
||||
if (door.x == room.left) {
|
||||
for (int i=room.top + 1; i < room.bottom; i++) {
|
||||
drawInside( level, room, new Point( room.left, i ), Random.IntRange( 1, room.width() - 2 ), Terrain.EMPTY_SP );
|
||||
}
|
||||
} else if (door.x == room.right) {
|
||||
for (int i=room.top + 1; i < room.bottom; i++) {
|
||||
drawInside( level, room, new Point( room.right, i ), Random.IntRange( 1, room.width() - 2 ), Terrain.EMPTY_SP );
|
||||
}
|
||||
} else if (door.y == room.top) {
|
||||
for (int i=room.left + 1; i < room.right; i++) {
|
||||
drawInside( level, room, new Point( i, room.top ), Random.IntRange( 1, room.height() - 2 ), Terrain.EMPTY_SP );
|
||||
}
|
||||
} else if (door.y == room.bottom) {
|
||||
for (int i=room.left + 1; i < room.right; i++) {
|
||||
drawInside( level, room, new Point( i, room.bottom ), Random.IntRange( 1, room.height() - 2 ), Terrain.EMPTY_SP );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import com.watabou.noosa.audio.Sample;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
|
||||
public class AlarmTrap {
|
||||
|
||||
// 0xDD3333
|
||||
|
||||
public static void trigger( int pos, Char ch ) {
|
||||
|
||||
for (Mob mob : Dungeon.level.mobs) {
|
||||
if (mob != ch) {
|
||||
mob.beckon( pos );
|
||||
}
|
||||
}
|
||||
|
||||
if (Dungeon.visible[pos]) {
|
||||
GLog.w( "The trap emits a piercing sound that echoes throughout the dungeon!" );
|
||||
CellEmitter.center( pos ).start( Speck.factory( Speck.SCREAM ), 0.3f, 3 );
|
||||
}
|
||||
|
||||
Sample.INSTANCE.play( Assets.SND_ALERT );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Fire;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class FireTrap {
|
||||
|
||||
// 0xFF7708
|
||||
|
||||
public static void trigger( int pos, Char ch ) {
|
||||
|
||||
GameScene.add( Blob.seed( pos, 2, Fire.class ) );
|
||||
CellEmitter.get( pos ).burst( FlameParticle.FACTORY, 5 );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Bleeding;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Cripple;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Wound;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class GrippingTrap {
|
||||
|
||||
public static void trigger( int pos, Char c ) {
|
||||
|
||||
if (c != null) {
|
||||
int damage = Math.max( 0, (Dungeon.depth + 3) - Random.IntRange( 0, c.dr() / 2 ) );
|
||||
Buff.affect( c, Bleeding.class ).set( damage );
|
||||
Buff.prolong( c, Cripple.class, Cripple.DURATION );
|
||||
Wound.hit( c );
|
||||
} else {
|
||||
Wound.hit( pos );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import com.watabou.noosa.Camera;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.ResultDescriptions;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.Lightning;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SparkParticle;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.utils.Utils;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class LightningTrap {
|
||||
|
||||
private static final String name = "lightning trap";
|
||||
|
||||
// 00x66CCEE
|
||||
|
||||
public static void trigger( int pos, Char ch ) {
|
||||
|
||||
if (ch != null) {
|
||||
ch.damage( Math.max( 1, Random.Int( ch.HP / 3, 2 * ch.HP / 3 ) ), LIGHTNING );
|
||||
if (ch == Dungeon.hero) {
|
||||
|
||||
Camera.main.shake( 2, 0.3f );
|
||||
|
||||
if (!ch.isAlive()) {
|
||||
Dungeon.fail( Utils.format( ResultDescriptions.TRAP, name, Dungeon.depth ) );
|
||||
GLog.n( "You were killed by a discharge of a lightning trap..." );
|
||||
} else {
|
||||
((Hero)ch).belongings.charge( false );
|
||||
}
|
||||
}
|
||||
|
||||
int[] points = new int[2];
|
||||
|
||||
points[0] = pos - Level.WIDTH;
|
||||
points[1] = pos + Level.WIDTH;
|
||||
ch.sprite.parent.add( new Lightning( points, 2, null ) );
|
||||
|
||||
points[0] = pos - 1;
|
||||
points[1] = pos + 1;
|
||||
ch.sprite.parent.add( new Lightning( points, 2, null ) );
|
||||
}
|
||||
|
||||
CellEmitter.center( pos ).burst( SparkParticle.FACTORY, Random.IntRange( 3, 4 ) );
|
||||
|
||||
}
|
||||
|
||||
public static final Electricity LIGHTNING = new Electricity();
|
||||
public static class Electricity {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ParalyticGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class ParalyticTrap {
|
||||
|
||||
// 0xCCCC55
|
||||
|
||||
public static void trigger( int pos, Char ch ) {
|
||||
|
||||
GameScene.add( Blob.seed( pos, 80 + 5 * Dungeon.depth, ParalyticGas.class ) );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Poison;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.PoisonParticle;
|
||||
|
||||
public class PoisonTrap {
|
||||
|
||||
// 0xBB66EE
|
||||
|
||||
public static void trigger( int pos, Char ch ) {
|
||||
|
||||
if (ch != null) {
|
||||
Buff.affect( ch, Poison.class ).set( 5 + Math.min( Dungeon.depth, 15 ) );
|
||||
}
|
||||
|
||||
CellEmitter.center( pos ).burst( PoisonParticle.SPLASH, 3 );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bestiary;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlink;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
public class SummoningTrap {
|
||||
|
||||
private static final float DELAY = 2f;
|
||||
|
||||
private static final Mob DUMMY = new Mob() {};
|
||||
|
||||
// 0x770088
|
||||
|
||||
public static void trigger( int pos, Char c ) {
|
||||
|
||||
if (Dungeon.bossLevel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (c != null) {
|
||||
Actor.occupyCell( c );
|
||||
}
|
||||
|
||||
int nMobs = 1;
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
nMobs++;
|
||||
if (Random.Int( 2 ) == 0) {
|
||||
nMobs++;
|
||||
}
|
||||
}
|
||||
|
||||
// It's complicated here, because these traps can be activated in chain
|
||||
|
||||
ArrayList<Integer> candidates = new ArrayList<Integer>();
|
||||
|
||||
for (int i=0; i < Level.NEIGHBOURS8.length; i++) {
|
||||
int p = pos + Level.NEIGHBOURS8[i];
|
||||
if (Actor.findChar( p ) == null && (Level.passable[p] || Level.avoid[p])) {
|
||||
candidates.add( p );
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<Integer> respawnPoints = new ArrayList<Integer>();
|
||||
|
||||
while (nMobs > 0 && candidates.size() > 0) {
|
||||
int index = Random.index( candidates );
|
||||
|
||||
DUMMY.pos = candidates.get( index );
|
||||
Actor.occupyCell( DUMMY );
|
||||
|
||||
respawnPoints.add( candidates.remove( index ) );
|
||||
nMobs--;
|
||||
}
|
||||
|
||||
for (Integer point : respawnPoints) {
|
||||
Mob mob = Bestiary.mob( Dungeon.depth );
|
||||
mob.state = Mob.State.WANDERING;
|
||||
GameScene.add( mob, DELAY );
|
||||
WandOfBlink.appear( mob, point );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2014 Oleg Dolya
|
||||
*
|
||||
* 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.traps;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.ToxicGas;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
|
||||
public class ToxicTrap {
|
||||
|
||||
// 0x40CC55
|
||||
|
||||
public static void trigger( int pos, Char ch ) {
|
||||
|
||||
GameScene.add( Blob.seed( pos, 300 + 20 * Dungeon.depth, ToxicGas.class ) );
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user