v2.3.0: made a gnoll rockfall trap class, gave them text, nerfed them

This commit is contained in:
Evan Debenham
2023-11-16 14:47:31 -05:00
parent ab8ca6b6fa
commit 7dc73f01f6
5 changed files with 121 additions and 24 deletions

View File

@@ -84,6 +84,9 @@ levels.traps.gatewaytrap.desc=This special teleportation trap can activate an in
levels.traps.geysertrap.name=geyser trap
levels.traps.geysertrap.desc=When triggered, this trap will cause a geyser of water to spew forth, damaging fiery enemies, knocking away all nearby characters, dousing fires, and converting the surrounding terrain to water.
levels.traps.gnollrockfalltrap.name=gnoll rockfall trap
levels.traps.gnollrockfalltrap.desc=This rockfall trap is made with some form of magical assistance. When triggered, it will cause rocks to loosen and immediately fall from above in a 5x5 area around it. It's not been as methodically set up as other rockfall traps, and so isn't quite as dangerous. Rocks also won't fall in locations with am adjacent barricade, as they help hold the ceiling up.\n\n_This trap can't tell friend from foe, and so is just as harmful to the gnolls as it is to you._
levels.traps.grimtrap.name=grim trap
levels.traps.grimtrap.ondeath=You were killed by the blast of a grim trap...
levels.traps.grimtrap.desc=Extremely powerful destructive magic is stored within this trap, enough to instantly kill all but the healthiest of heroes. Triggering it will send a ranged blast of lethal magic towards the nearest character.\n\nThankfully the trigger mechanism isn't hidden.
@@ -233,6 +236,7 @@ levels.mininglevel.crystal_name=Crystal spike
levels.mininglevel.boulder_name=Boulder
levels.mininglevel.crystal_desc=There is a large and colorful crystal outcropping here. These crystals are fragile and can easily be broken with a pickaxe, or will break if something is mined next to it.
levels.mininglevel.boulder_desc=There is a large boulder is blocking the way. It should be fairly easy to break with a pickaxe.
levels.mininglevel.barricade_desc=The wooden barricade is firmly set and acts as a support for the ceiling.\n\nThis was probably constructed by the gnolls to give some protection against falling rocks. _Any adjacent cells will be protected from rockfall traps and attacks._\n\nIt looks like it would burn just as well as any other barricade.
levels.prisonlevel.water_name=Dark cold water
levels.prisonlevel.empty_deco_desc=There are old blood stains on the floor.

View File

@@ -290,6 +290,8 @@ public class MiningLevel extends CavesLevel {
return Messages.get(MiningLevel.class, "crystal_desc");
case Terrain.MINE_BOULDER:
return Messages.get(MiningLevel.class, "boulder_desc");
case Terrain.BARRICADE:
return Messages.get(MiningLevel.class, "barricade_desc");
default:
return super.tileDesc( tile );
}

View File

@@ -31,7 +31,7 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.SecretRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.CaveRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.RockfallTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.GnollRockfallTrap;
import com.watabou.utils.GameMath;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Point;
@@ -158,7 +158,7 @@ public class MineLargeRoom extends CaveRoom {
|| level.pointToCell(r) == sapperPos
|| level.pointToCell(r) == guardPos);
Painter.set(level, r, Terrain.TRAP);
level.setTrap(new RockfallTrap().reveal(), level.pointToCell(r));
level.setTrap(new GnollRockfallTrap().reveal(), level.pointToCell(r));
}
for (Point p : getPoints()){

View File

@@ -0,0 +1,110 @@
/*
* Pixel Dungeon
* Copyright (C) 2012-2015 Oleg Dolya
*
* Shattered Pixel Dungeon
* Copyright (C) 2014-2023 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.traps;
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.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.GnollGuard;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.MiningLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.BArray;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random;
import java.util.ArrayList;
public class GnollRockfallTrap extends RockfallTrap {
@Override
public void activate() {
ArrayList<Integer> rockCells = new ArrayList<>();
//drop rocks in a 5x5 grid, ignoring cells next to barricades
PathFinder.buildDistanceMap( pos, BArray.not( Dungeon.level.solid, null ), 2 );
for (int i = 0; i < PathFinder.distance.length; i++) {
if (PathFinder.distance[i] < Integer.MAX_VALUE) {
if (Dungeon.level instanceof MiningLevel){
boolean barricade = false;
for (int j : PathFinder.NEIGHBOURS9){
if (Dungeon.level.map[i+j] == Terrain.BARRICADE){
barricade = true;
}
}
if (barricade) continue;
}
rockCells.add(i);
}
}
boolean seen = false;
for (int cell : rockCells){
if (Dungeon.level.heroFOV[ cell ]){
CellEmitter.get( cell - Dungeon.level.width() ).start(Speck.factory(Speck.ROCK), 0.07f, 10);
seen = true;
}
Char ch = Actor.findChar( cell );
if (ch != null && ch.isAlive()){
//5-10 less damage than normal rockfall traps
int damage = Random.NormalIntRange(scalingDepth(), scalingDepth()*2);
damage -= ch.drRoll();
ch.damage( Math.max(damage, 0) , this);
//guards take full paralysis, otherwise just a little
Buff.prolong(ch, Paralysis.class, ch instanceof GnollGuard ? 10 : 3);
if (!ch.isAlive() && ch == Dungeon.hero){
Dungeon.fail( this );
GLog.n( Messages.get(this, "ondeath") );
}
} else if (Dungeon.level instanceof MiningLevel
&& Dungeon.level.traps.get(cell) == null
&& Dungeon.level.plants.get(cell) == null
&& Random.Int(2) == 0){
Level.set( cell, Terrain.MINE_BOULDER );
GameScene.updateMap(cell);
}
}
if (seen){
PixelScene.shake(3, 0.7f);
Sample.INSTANCE.play(Assets.Sounds.ROCKS);
}
}
}

View File

@@ -27,20 +27,15 @@ 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.Paralysis;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.effects.CellEmitter;
import com.shatteredpixel.shatteredpixeldungeon.effects.Speck;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.MiningLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.RegularLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.scenes.PixelScene;
import com.watabou.utils.BArray;
import com.shatteredpixel.shatteredpixeldungeon.utils.GLog;
import com.watabou.noosa.audio.Sample;
import com.watabou.utils.BArray;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Point;
import com.watabou.utils.Random;
@@ -69,7 +64,7 @@ public class RockfallTrap extends Trap {
r = ((RegularLevel) Dungeon.level).room(pos);
}
if (onGround && r != null && !(Dungeon.level instanceof MiningLevel)){
if (onGround && r != null){
int cell;
for (Point p : r.getPoints()){
cell = Dungeon.level.pointToCell(p);
@@ -78,20 +73,11 @@ public class RockfallTrap extends Trap {
}
}
//do 5x5 if we don't have a room, or are in the mining level
//if we don't have a room, then just do 5x5
} else {
PathFinder.buildDistanceMap( pos, BArray.not( Dungeon.level.solid, null ), 2 );
for (int i = 0; i < PathFinder.distance.length; i++) {
if (PathFinder.distance[i] < Integer.MAX_VALUE) {
if (Dungeon.level instanceof MiningLevel){
boolean barricade = false;
for (int j : PathFinder.NEIGHBOURS9){
if (Dungeon.level.map[i+j] == Terrain.BARRICADE){
barricade = true;
}
}
if (barricade) continue;
}
rockCells.add(i);
}
}
@@ -118,11 +104,6 @@ public class RockfallTrap extends Trap {
Dungeon.fail( this );
GLog.n( Messages.get(this, "ondeath") );
}
} else if (Dungeon.level instanceof MiningLevel
&& Blacksmith.Quest.Type() == Blacksmith.Quest.GNOLL
&& Random.Int(2) == 0){
Level.set( cell, Terrain.MINE_BOULDER );
GameScene.updateMap(cell);
}
}