v1.2.0: implemented sacrifice rooms
This commit is contained in:
parent
adfaa59cc8
commit
5ebca6dcca
|
@ -19,6 +19,11 @@ actors.blobs.inferno.desc=An inferno is raging here.
|
||||||
|
|
||||||
actors.blobs.paralyticgas.desc=A cloud of paralytic gas is swirling here.
|
actors.blobs.paralyticgas.desc=A cloud of paralytic gas is swirling here.
|
||||||
|
|
||||||
|
actors.blobs.sacrificialfire.desc=There is an altar here with a sacrificial fire burning atop it. Any creature that's killed here will be consumed as an offering to the spirits of the dungeon.\n\nPerhaps a reward will be given if enough sacrifices are mede?
|
||||||
|
actors.blobs.sacrificialfire.worthy=The fire consumes your offering and grows stronger.
|
||||||
|
actors.blobs.sacrificialfire.unworthy=The fire consumes your offering, but doesn't change.
|
||||||
|
actors.blobs.sacrificialfire.reward=The fire flares and then dissipates, leaving a reward behind!
|
||||||
|
|
||||||
actors.blobs.smokescreen.desc=A cloud of thick black smoke is swirling here.
|
actors.blobs.smokescreen.desc=A cloud of thick black smoke is swirling here.
|
||||||
|
|
||||||
actors.blobs.stenchgas.desc=A cloud of fetid stench is swirling here.
|
actors.blobs.stenchgas.desc=A cloud of fetid stench is swirling here.
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* Pixel Dungeon
|
||||||
|
* Copyright (C) 2012-2015 Oleg Dolya
|
||||||
|
*
|
||||||
|
* Shattered Pixel Dungeon
|
||||||
|
* Copyright (C) 2014-2022 Evan Debenham
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.actors.blobs;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Assets;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.FlavourBuff;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.hero.Hero;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Bee;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mimic;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Piranha;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Statue;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Wraith;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.BlobEmitter;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.SacrificialParticle;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SacrificeRoom;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
|
||||||
|
import com.watabou.noosa.audio.Sample;
|
||||||
|
import com.watabou.utils.PathFinder;
|
||||||
|
import com.watabou.utils.Random;
|
||||||
|
|
||||||
|
public class SacrificialFire extends Blob {
|
||||||
|
|
||||||
|
BlobEmitter curEmitter;
|
||||||
|
|
||||||
|
{
|
||||||
|
//acts after mobs, so they can get marked as they move
|
||||||
|
actPriority = MOB_PRIO-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void evolve() {
|
||||||
|
int cell;
|
||||||
|
for (int i=area.top-1; i <= area.bottom; i++) {
|
||||||
|
for (int j = area.left-1; j <= area.right; j++) {
|
||||||
|
cell = j + i* Dungeon.level.width();
|
||||||
|
if (Dungeon.level.insideMap(cell)) {
|
||||||
|
off[cell] = cur[cell];
|
||||||
|
volume += off[cell];
|
||||||
|
|
||||||
|
Char ch = Actor.findChar( cell );
|
||||||
|
if (ch != null && off[cell] > 0){
|
||||||
|
if (Dungeon.level.heroFOV[cell] && ch.buff( Marked.class ) == null) {
|
||||||
|
CellEmitter.get(cell).burst( SacrificialParticle.FACTORY, 5 );
|
||||||
|
}
|
||||||
|
Buff.prolong( ch, Marked.class, Marked.DURATION );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//a bit brittle, assumes only one tile of sacrificial fire can exist per floor
|
||||||
|
int max = 5 + Dungeon.depth * 5;
|
||||||
|
curEmitter.pour( SacrificialParticle.FACTORY, 0.01f + ((volume / (float)max) * 0.09f) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void use( BlobEmitter emitter ) {
|
||||||
|
super.use( emitter );
|
||||||
|
curEmitter = emitter;
|
||||||
|
|
||||||
|
//a bit brittle, assumes only one tile of sacrificial fire can exist per floor
|
||||||
|
int max = 5 + Dungeon.depth * 5;
|
||||||
|
curEmitter.pour( SacrificialParticle.FACTORY, 0.01f + ((volume / (float)max) * 0.09f) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String tileDesc() {
|
||||||
|
return Messages.get(this, "desc");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sacrifice( Char ch ) {
|
||||||
|
|
||||||
|
SacrificialFire fire = (SacrificialFire)Dungeon.level.blobs.get( SacrificialFire.class );
|
||||||
|
|
||||||
|
if (fire != null && fire.cur[ch.pos] > 0) {
|
||||||
|
|
||||||
|
int exp = 0;
|
||||||
|
if (ch instanceof Mob) {
|
||||||
|
//same rates as used in wand of corruption
|
||||||
|
if (ch instanceof Statue || ch instanceof Mimic){
|
||||||
|
exp = 1 + Dungeon.depth;
|
||||||
|
} else if (ch instanceof Piranha || ch instanceof Bee) {
|
||||||
|
exp = 1 + Dungeon.depth/2;
|
||||||
|
} else if (ch instanceof Wraith) {
|
||||||
|
exp = 1 + Dungeon.depth/3;
|
||||||
|
} else {
|
||||||
|
exp = ((Mob)ch).EXP;
|
||||||
|
}
|
||||||
|
exp *= Random.IntRange( 2, 3 );
|
||||||
|
} else if (ch instanceof Hero) {
|
||||||
|
exp = 1_000_000; //always enough to activate the reward, if you can somehow get it
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp > 0) {
|
||||||
|
|
||||||
|
int volume = fire.cur[ch.pos] - exp;
|
||||||
|
if (volume > 0) {
|
||||||
|
fire.cur[ch.pos] -= exp;
|
||||||
|
fire.volume -= exp;
|
||||||
|
CellEmitter.get(ch.pos).burst( SacrificialParticle.FACTORY, 20 );
|
||||||
|
Sample.INSTANCE.play(Assets.Sounds.BURNING );
|
||||||
|
GLog.w( Messages.get(SacrificialFire.class, "worthy"));
|
||||||
|
} else {
|
||||||
|
fire.clear(ch.pos);
|
||||||
|
|
||||||
|
for (int i : PathFinder.NEIGHBOURS9){
|
||||||
|
CellEmitter.get(ch.pos+i).burst( SacrificialParticle.FACTORY, 20 );
|
||||||
|
}
|
||||||
|
Sample.INSTANCE.play(Assets.Sounds.BURNING );
|
||||||
|
Sample.INSTANCE.play(Assets.Sounds.BURNING );
|
||||||
|
Sample.INSTANCE.play(Assets.Sounds.BURNING );
|
||||||
|
GLog.w( Messages.get(SacrificialFire.class, "reward"));
|
||||||
|
Dungeon.level.drop( SacrificeRoom.prize( Dungeon.level ), ch.pos ).sprite.drop();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
GLog.w( Messages.get(SacrificialFire.class, "unworthy"));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Marked extends FlavourBuff {
|
||||||
|
|
||||||
|
public static final float DURATION = 2f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detach() {
|
||||||
|
if (!target.isAlive()) {
|
||||||
|
sacrifice( target );
|
||||||
|
}
|
||||||
|
super.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* Pixel Dungeon
|
||||||
|
* Copyright (C) 2012-2015 Oleg Dolya
|
||||||
|
*
|
||||||
|
* Shattered Pixel Dungeon
|
||||||
|
* Copyright (C) 2014-2022 Evan Debenham
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
|
||||||
|
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.SacrificialFire;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.Gold;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.items.weapon.Weapon;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||||
|
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||||
|
import com.watabou.utils.Point;
|
||||||
|
|
||||||
|
public class SacrificeRoom extends SpecialRoom {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(Level level) {
|
||||||
|
Painter.fill( level, this, Terrain.WALL );
|
||||||
|
Painter.fill( level, this, 1, Terrain.CHASM );
|
||||||
|
|
||||||
|
Point c = center();
|
||||||
|
Door door = entrance();
|
||||||
|
if (door.x == left || door.x == right) {
|
||||||
|
Point p = Painter.drawInside( level, this, door, Math.abs( door.x - c.x ) - 2, Terrain.EMPTY_SP );
|
||||||
|
for (; p.y != c.y; p.y += p.y < c.y ? +1 : -1) {
|
||||||
|
Painter.set( level, p, Terrain.EMPTY_SP );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Point p = Painter.drawInside( level, this, door, Math.abs( door.y - c.y ) - 2, Terrain.EMPTY_SP );
|
||||||
|
for (; p.x != c.x; p.x += p.x < c.x ? +1 : -1) {
|
||||||
|
Painter.set( level, p, Terrain.EMPTY_SP );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Painter.fill( level, c.x - 1, c.y - 1, 3, 3, Terrain.EMBERS );
|
||||||
|
Painter.set( level, c, Terrain.PEDESTAL );
|
||||||
|
|
||||||
|
Blob.seed( level.pointToCell(c), 5 + Dungeon.depth * 5, SacrificialFire.class, level );
|
||||||
|
|
||||||
|
door.set( Door.Type.EMPTY );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Item prize( Level level ) {
|
||||||
|
|
||||||
|
//1 floor set higher than normal
|
||||||
|
Weapon prize = Generator.randomWeapon( (Dungeon.depth / 5) + 1);
|
||||||
|
|
||||||
|
if (Challenges.isItemBlocked(prize)){
|
||||||
|
return new Gold().random();
|
||||||
|
}
|
||||||
|
|
||||||
|
//if it isn't already cursed, give it a free upgrade
|
||||||
|
if (!prize.cursed){
|
||||||
|
prize.upgrade();
|
||||||
|
//curse the weapon, unless it has a glyph
|
||||||
|
if (!prize.hasGoodEnchant()){
|
||||||
|
prize.enchant(Weapon.Enchantment.randomCurse());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prize.cursed = prize.cursedKnown = true;
|
||||||
|
|
||||||
|
return prize;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -119,8 +119,6 @@ public abstract class SpecialRoom extends Room {
|
||||||
if (!runConsSpecials.isEmpty()) runSpecials.add(runConsSpecials.remove(0));
|
if (!runConsSpecials.isEmpty()) runSpecials.add(runConsSpecials.remove(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
runSpecials.add(0, WeakFloorRoom.class);
|
|
||||||
|
|
||||||
pitNeededDepth = -1;
|
pitNeededDepth = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user