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.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.PointF;
@@ -15,23 +18,38 @@ public class VaultMob extends Mob {
state = SLEEPING;
}
//used to track
private int previousPos;
//used to track movement direction for wandering detection angles
private int previousPos = -1;
@Override
public void move(int step, boolean travelling) {
previousPos = pos;
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 INVEST_TURNS = "invest_turns";
private static final String WANDER_POSITIONS = "wander_positions";
private static final String WANDER_POS_IDX = "wander_pos_idx";
@Override
public void storeInBundle(Bundle bundle) {
super.storeInBundle(bundle);
bundle.put(PREV_POS, previousPos);
bundle.put(INVEST_TURNS, investigatingTurns);
if (wanderPositions != null) {
bundle.put(WANDER_POSITIONS, wanderPositions);
bundle.put(WANDER_POS_IDX, wanderPosIdx);
}
}
@Override
@@ -39,8 +57,13 @@ public class VaultMob extends Mob {
super.restoreFromBundle(bundle);
previousPos = bundle.getInt(PREV_POS);
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;
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 {
@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 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){
return 1 / (distance( enemy ) / 2f + enemy.stealth());
//classic sleeping (i.e. default) detection if enemy is within a 170 degree vision cone
} else if (Math.abs(enemyDir - movementDir) <= 85f){
//classic sleeping (i.e. default) detection if enemy is within a 180 degree vision cone
} else if (Math.abs(enemyDir - movementDir) < 90f){
return 1 / (distance( enemy ) + enemy.stealth());
//otherwise uses very low chance detection (1/8 at 2 tiles, 0% at 3+)
} else {
@@ -108,19 +134,56 @@ public class VaultMob extends Mob {
investigatingTurns = 0;
sprite.showInvestigate();
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;
}
@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{
protected void awaken(boolean 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){
alerted = false;
state = INVESTIGATING;
investigatingTurns = 0;
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) {
blast(pos, radius, -1);
}
public static void blast(int pos, float radius, int hardLight){
Group parent = Dungeon.hero.sprite.parent;
BlastWave b = (BlastWave) parent.recycle(BlastWave.class);
parent.bringToFront(b);
b.reset(pos, radius);
if (hardLight != -1){
b.hardlight(hardLight);
}
}
}