v3.3.5: more implementation on vault mobs

This commit is contained in:
Evan Debenham
2026-02-01 14:16:40 -05:00
parent f325c9c557
commit 09f492d5da
2 changed files with 75 additions and 5 deletions

View File

@@ -2,6 +2,9 @@ package com.shatteredpixel.shatteredpixeldungeon.actors.mobs;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Char; import com.shatteredpixel.shatteredpixeldungeon.actors.Char;
import com.shatteredpixel.shatteredpixeldungeon.actors.buffs.Buff;
import com.shatteredpixel.shatteredpixeldungeon.items.artifacts.TalismanOfForesight;
import com.shatteredpixel.shatteredpixeldungeon.items.wands.WandOfBlastWave;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.PointF; import com.watabou.utils.PointF;
@@ -15,23 +18,38 @@ public class VaultMob extends Mob {
state = SLEEPING; state = SLEEPING;
} }
//used to track //used to track movement direction for wandering detection angles
private int previousPos; private int previousPos = -1;
@Override @Override
public void move(int step, boolean travelling) { public void move(int step, boolean travelling) {
previousPos = pos; previousPos = pos;
super.move(step, travelling); super.move(step, travelling);
if (travelling && !sprite.visible && Dungeon.level.distance(pos, Dungeon.hero.pos) <= 6){
if (state == HUNTING){
WandOfBlastWave.BlastWave.blast(pos, 1.5f, 0xFF0000);
} else if (state == INVESTIGATING){
WandOfBlastWave.BlastWave.blast(pos, 1.5f, 0xFF8800);
} else {
WandOfBlastWave.BlastWave.blast(pos, 1.5f);
}
}
} }
private static final String PREV_POS = "prev_pos"; private static final String PREV_POS = "prev_pos";
private static final String INVEST_TURNS = "invest_turns"; private static final String INVEST_TURNS = "invest_turns";
private static final String WANDER_POSITIONS = "wander_positions";
private static final String WANDER_POS_IDX = "wander_pos_idx";
@Override @Override
public void storeInBundle(Bundle bundle) { public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle); super.storeInBundle(bundle);
bundle.put(PREV_POS, previousPos); bundle.put(PREV_POS, previousPos);
bundle.put(INVEST_TURNS, investigatingTurns); bundle.put(INVEST_TURNS, investigatingTurns);
if (wanderPositions != null) {
bundle.put(WANDER_POSITIONS, wanderPositions);
bundle.put(WANDER_POS_IDX, wanderPosIdx);
}
} }
@Override @Override
@@ -39,8 +57,13 @@ public class VaultMob extends Mob {
super.restoreFromBundle(bundle); super.restoreFromBundle(bundle);
previousPos = bundle.getInt(PREV_POS); previousPos = bundle.getInt(PREV_POS);
investigatingTurns = bundle.getInt(INVEST_TURNS); investigatingTurns = bundle.getInt(INVEST_TURNS);
if (bundle.contains(WANDER_POSITIONS)) {
wanderPositions = bundle.getIntArray(WANDER_POSITIONS);
wanderPosIdx = bundle.getInt(WANDER_POS_IDX);
}
} }
//detection chance is lower on the first turn of investigating
private int investigatingTurns; private int investigatingTurns;
public class Investigating extends Mob.Investigating { public class Investigating extends Mob.Investigating {
@@ -67,6 +90,9 @@ public class VaultMob extends Mob {
} }
} }
public int wanderPosIdx = 0;
public int[] wanderPositions;
public class Wandering extends Mob.Wandering { public class Wandering extends Mob.Wandering {
@Override @Override
@@ -83,11 +109,11 @@ public class VaultMob extends Mob {
float movementDir = PointF.angle(Dungeon.level.cellToPoint(previousPos), Dungeon.level.cellToPoint(pos))/PointF.G2R;; float movementDir = PointF.angle(Dungeon.level.cellToPoint(previousPos), Dungeon.level.cellToPoint(pos))/PointF.G2R;;
float enemyDir = PointF.angle(Dungeon.level.cellToPoint(pos), Dungeon.level.cellToPoint(enemy.pos))/PointF.G2R; float enemyDir = PointF.angle(Dungeon.level.cellToPoint(pos), Dungeon.level.cellToPoint(enemy.pos))/PointF.G2R;
//classic wandering detection if enemy is within a 90 degree cone of vision //classic wandering detection if enemy is within (or touching) a 90 degree cone of vision
if (Math.abs(enemyDir - movementDir) <= 45f){ if (Math.abs(enemyDir - movementDir) <= 45f){
return 1 / (distance( enemy ) / 2f + enemy.stealth()); return 1 / (distance( enemy ) / 2f + enemy.stealth());
//classic sleeping (i.e. default) detection if enemy is within a 170 degree vision cone //classic sleeping (i.e. default) detection if enemy is within a 180 degree vision cone
} else if (Math.abs(enemyDir - movementDir) <= 85f){ } else if (Math.abs(enemyDir - movementDir) < 90f){
return 1 / (distance( enemy ) + enemy.stealth()); return 1 / (distance( enemy ) + enemy.stealth());
//otherwise uses very low chance detection (1/8 at 2 tiles, 0% at 3+) //otherwise uses very low chance detection (1/8 at 2 tiles, 0% at 3+)
} else { } else {
@@ -108,19 +134,56 @@ public class VaultMob extends Mob {
investigatingTurns = 0; investigatingTurns = 0;
sprite.showInvestigate(); sprite.showInvestigate();
spend(TICK); spend(TICK);
//hero must know if they are detected
if (!Dungeon.level.heroFOV[pos]){
Buff.affect(Dungeon.hero, TalismanOfForesight.CharAwareness.class, 1f).charID = id();
}
return true; return true;
} }
@Override
protected int randomDestination() {
//stay still by default if given no other wandering behaviour
if (wanderPositions == null){
wanderPositions = new int[1];
wanderPositions[0] = pos;
}
int wanderPos = wanderPositions[wanderPosIdx];
if (wanderPos == pos) {
if (wanderPositions.length > 1) {
wanderPosIdx++;
if (wanderPosIdx == wanderPositions.length) {
wanderPosIdx = 0;
}
wanderPos = wanderPositions[wanderPosIdx];
} else {
//reset this, representing the mob looking around in place
previousPos = pos;
}
}
return wanderPos;
}
} }
public class Sleeping extends Mob.Sleeping{ public class Sleeping extends Mob.Sleeping{
protected void awaken(boolean enemyInFOV) { protected void awaken(boolean enemyInFOV) {
super.awaken(enemyInFOV); super.awaken(enemyInFOV);
//stay still by default if given no other wandering behaviour
if (wanderPositions == null){
wanderPositions = new int[1];
wanderPositions[0] = pos;
}
if (state == HUNTING){ if (state == HUNTING){
alerted = false; alerted = false;
state = INVESTIGATING; state = INVESTIGATING;
investigatingTurns = 0; investigatingTurns = 0;
sprite.showInvestigate(); sprite.showInvestigate();
//hero must know if they are detected
if (!Dungeon.level.heroFOV[pos]){
Buff.affect(Dungeon.hero, TalismanOfForesight.CharAwareness.class, 1f).charID = id();
}
} }
} }

View File

@@ -273,10 +273,17 @@ public class WandOfBlastWave extends DamageWand {
} }
public static void blast(int pos, float radius) { public static void blast(int pos, float radius) {
blast(pos, radius, -1);
}
public static void blast(int pos, float radius, int hardLight){
Group parent = Dungeon.hero.sprite.parent; Group parent = Dungeon.hero.sprite.parent;
BlastWave b = (BlastWave) parent.recycle(BlastWave.class); BlastWave b = (BlastWave) parent.recycle(BlastWave.class);
parent.bringToFront(b); parent.bringToFront(b);
b.reset(pos, radius); b.reset(pos, radius);
if (hardLight != -1){
b.hardlight(hardLight);
}
} }
} }