v3.3.6: added a laser sentry hazard and a room for it

This commit is contained in:
Evan Debenham
2026-02-07 19:07:17 -05:00
parent ac51bfa555
commit 28e1fe139f
4 changed files with 197 additions and 4 deletions

View File

@@ -0,0 +1,122 @@
package com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.effects.Beam;
import com.shatteredpixel.shatteredpixeldungeon.effects.TargetedCell;
import com.shatteredpixel.shatteredpixeldungeon.mechanics.Ballistica;
import com.shatteredpixel.shatteredpixeldungeon.sprites.CharSprite;
import com.shatteredpixel.shatteredpixeldungeon.sprites.WardSprite;
import com.shatteredpixel.shatteredpixeldungeon.tiles.DungeonTilemap;
import com.watabou.utils.Bundle;
public class VaultLaser extends NPC {
{
spriteClass = WardSprite.class;
properties.add(Char.Property.IMMOVABLE);
}
public int[] laserDirs;
public int laserDirIdx;
public int initialLaserCooldown;
public int cooldown;
@Override
protected boolean act() {
cooldown--;
if (cooldown <= 0){
Ballistica beam = new Ballistica(pos, laserDirs[laserDirIdx], Ballistica.STOP_SOLID);
boolean visible = false;
for (int cell : beam.subPath(1, beam.dist)){
if (Dungeon.level.heroFOV[cell]){
visible = true;
}
if (Actor.findChar(cell) == Dungeon.hero){
Dungeon.hero.sprite.showStatus(CharSprite.NEGATIVE, "!!!");
}
}
if (visible){
sprite.parent.add(new Beam.DeathRay(sprite.center(), DungeonTilemap.raisedTileCenterToWorld(beam.collisionPos)));
}
laserDirIdx++;
if (laserDirIdx >= laserDirs.length){
laserDirIdx = 0;
}
cooldown = initialLaserCooldown;
}
if (cooldown == 1){
Ballistica nextBeam = new Ballistica(pos, laserDirs[laserDirIdx], Ballistica.STOP_SOLID);
for (int cell : nextBeam.subPath(1, nextBeam.dist)){
if (Dungeon.level.heroFOV[cell]) {
sprite.parent.add(new TargetedCell(cell, 0xFF0000));
}
}
}
throwItems();
spend(TICK);
return true;
}
@Override
public boolean isImmune(Class effect) {
return true;
}
@Override
public boolean isInvulnerable(Class effect) {
return true;
}
@Override
public boolean reset() {
return true;
}
@Override
public boolean interact(Char c) {
return true;
}
private static final String LASER_DIRS = "laser_dirs";
private static final String LASER_DIR_IDX = "laser_dir_idx";
private static final String INITIAL_COOLDOWN = "initial_cooldown";
private static final String COOLDOWN = "cooldown";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(LASER_DIRS, laserDirs);
bundle.put(LASER_DIR_IDX, laserDirIdx);
bundle.put(INITIAL_COOLDOWN, initialLaserCooldown);
bundle.put(COOLDOWN, cooldown);
}
@Override
public void restoreFromBundle(Bundle bundle) {
super.restoreFromBundle(bundle);
laserDirs = bundle.getIntArray(LASER_DIRS);
laserDirIdx = bundle.getInt(LASER_DIR_IDX);
initialLaserCooldown = bundle.getInt(INITIAL_COOLDOWN);
cooldown = bundle.getInt(COOLDOWN);
}
@Override
public CharSprite sprite() {
WardSprite sprite = (WardSprite) super.sprite();
sprite.linkVisuals(this);
return sprite;
}
}

View File

@@ -44,6 +44,7 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultCr
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultEnemyCenterRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultEntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultFinalRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultLasersRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultLongRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultQuadrantsRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault.VaultRingRoom;
@@ -71,6 +72,7 @@ public class VaultLevel extends CityLevel {
initRooms.add(new VaultRingsRoom());
initRooms.add(new VaultSimpleEnemyTreasureRoom());
initRooms.add(new AlternatingTrapsRoom());
initRooms.add(new VaultLasersRoom());
}
initRooms.add(new VaultLongRoom());

View File

@@ -1,16 +1,13 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.Blob;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.VaultFlameTraps;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.VaultLaser;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.VaultLevel;
import com.shatteredpixel.shatteredpixeldungeon.levels.features.LevelTransition;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.entrance.EntranceRoom;
import com.watabou.utils.Point;
public class VaultEntranceRoom extends StandardRoom {

View File

@@ -0,0 +1,72 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.quest.vault;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.VaultLaser;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.watabou.utils.Random;
public class VaultLasersRoom extends StandardRoom {
@Override
public float[] sizeCatProbs() {
return new float[]{0, 1, 0};
}
@Override
public void paint(Level level) {
Painter.fill(level, this, Terrain.WALL);
Painter.fill(level, this, 2, Terrain.EMPTY);
for (Room.Door door : connected.values()) {
Painter.drawInside(level, this, door, 2, Terrain.EMPTY);
door.set(Room.Door.Type.REGULAR);
}
for (int x = left+2; x <= right-2; x++){
if (level.map[x + (top+1)*level.width()] == Terrain.WALL
&& level.map[x + (bottom-1)*level.width()] == Terrain.WALL){
VaultLaser laser = new VaultLaser();
if (Random.Int(2) == 0){
int cell = x + level.width()*(top+1);
Painter.set(level, cell, Terrain.PEDESTAL);
laser.laserDirs = new int[]{cell+level.width()};
laser.pos = cell;
} else {
int cell = x + level.width()*(bottom-1);
Painter.set(level, cell, Terrain.PEDESTAL);
laser.laserDirs = new int[]{cell-level.width()};
laser.pos = cell;
}
laser.initialLaserCooldown = Random.IntRange(3, 7);
laser.cooldown = Random.IntRange(1, laser.initialLaserCooldown);
level.mobs.add(laser);
}
}
for (int y = top+2; y <= bottom-2; y++){
if (level.map[left+1 + (y)*level.width()] == Terrain.WALL
&& level.map[right-1 + (y)*level.width()] == Terrain.WALL){
VaultLaser laser = new VaultLaser();
if (Random.Int(2) == 0){
int cell = left+1 + level.width()*y;
Painter.set(level, cell, Terrain.PEDESTAL);
laser.laserDirs = new int[]{cell+1};
laser.pos = cell;
} else {
int cell = right-1 + level.width()*y;
Painter.set(level, cell, Terrain.PEDESTAL);
laser.laserDirs = new int[]{cell-1};
laser.pos = cell;
}
laser.initialLaserCooldown = Random.IntRange(3, 7);
laser.cooldown = Random.IntRange(1, laser.initialLaserCooldown);
level.mobs.add(laser);
}
}
}
}