From 09f492d5da97534705f8ae20fcd291f0b4989096 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Sun, 1 Feb 2026 14:16:40 -0500 Subject: [PATCH] v3.3.5: more implementation on vault mobs --- .../actors/mobs/VaultMob.java | 73 +++++++++++++++++-- .../items/wands/WandOfBlastWave.java | 7 ++ 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/VaultMob.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/VaultMob.java index 424c2d429..782753404 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/VaultMob.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/actors/mobs/VaultMob.java @@ -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(); + } } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java index 90c9f5d1f..655038582 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/items/wands/WandOfBlastWave.java @@ -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); + } } }