feat(gauntlet): replace Cleanser with Ghost powerup sticky bypass (v2.4.2)
- Remove entire Cleanser system (signal, vars, HUD, input, RPCs, bot AI) - Ghost (Invisible Mode) now bypasses sticky tiles in Gauntlet - Grant Ghost powerup every 2 missions instead of Cleanser charges - Ghost tiles spawn naturally on Gauntlet arena (15% chance) - Bots use Ghost powerup when boxed in by sticky tiles - Players pushed into sticky while Ghost are not slowed - Remove use_cleanser input action from project.godot - Remove CleanserHBox UI from gauntlet_hud.tscn - Bump version to 2.4.2
This commit is contained in:
@@ -17,7 +17,7 @@ const GOAL_TILES = [7, 8, 9, 10] # Heart, Diamond, Star, Coin
|
||||
const HOLO_TILES = [11, 12, 13, 14] # Power-up holo tiles
|
||||
|
||||
# Gauntlet overlay layer (v2 ground-growth model — sticky/telegraph on layer 2).
|
||||
# Bots must avoid these cells or burn a Cleanser charge to cross.
|
||||
# Bots must avoid these cells or use Ghost mode to cross.
|
||||
const GAUNTLET_OVERLAY_LAYER: int = 2
|
||||
const TILE_STICKY: int = 17
|
||||
const TILE_TELEGRAPH: int = 18
|
||||
@@ -61,23 +61,16 @@ func _get_gauntlet_manager() -> Node:
|
||||
return gm2
|
||||
return null
|
||||
|
||||
func _bot_has_cleanser_charge() -> bool:
|
||||
var gm = _get_gauntlet_manager()
|
||||
if not gm or not "player_cleansers" in gm:
|
||||
func _bot_has_ghost_powerup() -> bool:
|
||||
"""Check if the bot has a ghost powerup in its SpecialTilesManager inventory."""
|
||||
var stm = actor.get_node_or_null("SpecialTilesManager")
|
||||
if not stm:
|
||||
return false
|
||||
var pid = actor.get("peer_id") if "peer_id" in actor else actor.name.to_int()
|
||||
if pid == null or pid < 0:
|
||||
return false
|
||||
return gm.player_cleansers.get(pid, 0) > 0
|
||||
return stm.inventory.get(stm.SpecialEffect.INVISIBLE_MODE, false)
|
||||
|
||||
func _is_bot_cleanser_active() -> bool:
|
||||
var gm = _get_gauntlet_manager()
|
||||
if not gm:
|
||||
return false
|
||||
var pid = actor.get("peer_id") if "peer_id" in actor else actor.name.to_int()
|
||||
if pid == null or pid < 0:
|
||||
return false
|
||||
return gm.is_cleanser_active(pid)
|
||||
func _is_bot_ghost_active() -> bool:
|
||||
"""Check if the bot is currently in ghost (invisible) mode."""
|
||||
return actor.get("is_invisible") == true
|
||||
|
||||
func _is_overlay_unsafe(pos: Vector2i) -> bool:
|
||||
"""True if the cell carries a sticky or telegraphed overlay on layer 2."""
|
||||
@@ -88,10 +81,10 @@ func _is_overlay_unsafe(pos: Vector2i) -> bool:
|
||||
|
||||
func _is_cell_unsafe_in_gauntlet(pos: Vector2i) -> bool:
|
||||
"""Cell is unsafe in Gauntlet if it's sticky/telegraphed — unless the bot's
|
||||
Cleanser is active (grants temporary immunity)."""
|
||||
Ghost mode is active (grants sticky bypass)."""
|
||||
if not is_gauntlet_mode():
|
||||
return false
|
||||
if _is_bot_cleanser_active():
|
||||
if _is_bot_ghost_active():
|
||||
return false
|
||||
var gm = _get_gauntlet_manager()
|
||||
if gm and gm.has_method("is_sticky_cell") and gm.is_sticky_cell(pos):
|
||||
@@ -106,13 +99,13 @@ func _count_unsafe_neighbors(pos: Vector2i) -> int:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
func should_activate_cleanser_now() -> bool:
|
||||
"""True if the bot is boxed in / about to be sealed and should burn Cleanser."""
|
||||
func should_activate_ghost_now() -> bool:
|
||||
"""True if the bot is boxed in / about to be sealed and should use Ghost powerup."""
|
||||
if not is_gauntlet_mode():
|
||||
return false
|
||||
if not _bot_has_cleanser_charge():
|
||||
if not _bot_has_ghost_powerup():
|
||||
return false
|
||||
if _is_bot_cleanser_active():
|
||||
if _is_bot_ghost_active():
|
||||
return false
|
||||
var here = actor.current_position if actor and "current_position" in actor else Vector2i(-1, -1)
|
||||
if here == Vector2i(-1, -1):
|
||||
@@ -623,7 +616,7 @@ func _is_valid_move_target(pos: Vector2i, ignore_players: bool = false) -> bool:
|
||||
# Gauntlet mode (#075): reject cells that are sticky or telegraphed —
|
||||
# stepping onto them either traps the bot or strands it within 1s.
|
||||
# Safety applies even when ignore_players is true (a sticky cell is unsafe
|
||||
# regardless of whether another player is on it). Cleanser-active bots are
|
||||
# regardless of whether another player is on it). Ghost-active bots are
|
||||
# exempt via the helper.
|
||||
if _is_cell_unsafe_in_gauntlet(pos):
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user