feat(gauntlet): shrink arena per phase 20x20 -> 18x18 -> 7x7; sticky cells block movement
CI / Export Linux (push) Failing after 4s
CI / Export Windows (push) Failing after 36s
CI / Export Android (push) Failing after 38s
Test Suite / Unit Tests (GUT) (push) Failing after 26s
Test Suite / Integration Tests (push) Failing after 29s
Test Suite / Code Style Check (push) Failing after 38s
CI / Create Release (push) Has been skipped
Test Suite / Security Scan (push) Failing after 51s
CI / Export Linux (push) Failing after 4s
CI / Export Windows (push) Failing after 36s
CI / Export Android (push) Failing after 38s
Test Suite / Unit Tests (GUT) (push) Failing after 26s
Test Suite / Integration Tests (push) Failing after 29s
Test Suite / Code Style Check (push) Failing after 38s
CI / Create Release (push) Has been skipped
Test Suite / Security Scan (push) Failing after 51s
This commit is contained in:
@@ -340,9 +340,12 @@ func _start_phase(phase: Phase) -> void:
|
||||
var phase_name = _phase_to_string(phase)
|
||||
print("[Gauntlet] Phase changed to: ", phase_name)
|
||||
|
||||
if _can_rpc():
|
||||
if _can_rpc() and multiplayer.is_server():
|
||||
rpc("sync_phase", int(phase), phase_name)
|
||||
|
||||
# Update phase explicitly with setup_arena
|
||||
_shrink_arena()
|
||||
|
||||
emit_signal("phase_changed", int(phase), phase_name)
|
||||
|
||||
func _phase_to_string(phase: Phase) -> String:
|
||||
@@ -361,6 +364,14 @@ func sync_phase(phase_index: int, phase_name: String) -> void:
|
||||
if not is_active:
|
||||
activate_client_side()
|
||||
current_phase = phase_index as Phase
|
||||
if not multiplayer.is_server():
|
||||
var bounds = get_arena_bounds()
|
||||
for x in range(ARENA_COLUMNS):
|
||||
for z in range(ARENA_ROWS):
|
||||
var pos = Vector2i(x, z)
|
||||
if pos.x <= bounds.min or pos.x >= bounds.max or pos.y <= bounds.min or pos.y >= bounds.max:
|
||||
if not sticky_cells.has(pos):
|
||||
sticky_cells[pos] = true
|
||||
_update_hud_phase(phase_name)
|
||||
|
||||
# =============================================================================
|
||||
@@ -419,11 +430,12 @@ func _apply_arena_setup() -> void:
|
||||
continue
|
||||
|
||||
# Boundary walls: perimeter (row 0, row 19, col 0, col 19)
|
||||
if x == 0 or x == ARENA_COLUMNS - 1 or z == 0 or z == ARENA_ROWS - 1:
|
||||
if pos.x <= 0 or pos.x >= 19 or pos.y <= 0 or pos.y >= 19:
|
||||
# Also make border walls visually walkable floors instead of red blocks
|
||||
gridmap.set_cell_item(Vector3i(x, 0, z), TILE_WALKABLE)
|
||||
gridmap.set_cell_item(Vector3i(x, 1, z), -1)
|
||||
gridmap.set_cell_item(Vector3i(x, 2, z), -1)
|
||||
gridmap.set_cell_item(Vector3i(x, 2, z), TILE_STICKY)
|
||||
sticky_cells[pos] = true
|
||||
continue
|
||||
|
||||
# Interior: walkable floor
|
||||
@@ -1065,9 +1077,12 @@ func is_cleansed_cell(pos: Vector2i) -> bool:
|
||||
|
||||
func cell_state(pos: Vector2i) -> CellState:
|
||||
"""Logical state of a playable cell (v2 ground-growth model)."""
|
||||
var b = get_arena_bounds()
|
||||
if pos.x <= b.min or pos.x >= b.max or pos.y <= b.min or pos.y >= b.max:
|
||||
return CellState.STICKY
|
||||
if _is_npc_zone(pos) or _is_boundary(pos):
|
||||
return CellState.BLOCKED
|
||||
if sticky_cells.has(pos):
|
||||
if is_sticky_cell(pos):
|
||||
return CellState.STICKY
|
||||
if cleansed_cells.has(pos):
|
||||
return CellState.CLEANSED
|
||||
@@ -1091,8 +1106,37 @@ func _tick_cleansed_cells(delta: float) -> void:
|
||||
for pos in expired:
|
||||
cleansed_cells.erase(pos)
|
||||
|
||||
func get_arena_bounds() -> Dictionary:
|
||||
match current_phase:
|
||||
Phase.OPEN_ARENA:
|
||||
return {"min": 0, "max": 19} # 20x20
|
||||
Phase.ROUTE_PRESSURE:
|
||||
return {"min": 1, "max": 18} # 18x18
|
||||
Phase.SURVIVAL_ENDGAME:
|
||||
return {"min": 6, "max": 12} # 7x7
|
||||
return {"min": 0, "max": 19}
|
||||
|
||||
func _shrink_arena() -> void:
|
||||
if not multiplayer.is_server(): return
|
||||
var b = get_arena_bounds()
|
||||
var new_sticky = []
|
||||
for x in range(ARENA_COLUMNS):
|
||||
for z in range(ARENA_ROWS):
|
||||
var pos = Vector2i(x, z)
|
||||
if _is_npc_zone(pos) or _is_boundary(pos):
|
||||
continue
|
||||
if pos.x <= b.min or pos.x >= b.max or pos.y <= b.min or pos.y >= b.max:
|
||||
if not sticky_cells.has(pos):
|
||||
new_sticky.append(pos)
|
||||
|
||||
if new_sticky.size() > 0:
|
||||
if _can_rpc() and multiplayer.is_server():
|
||||
rpc("sync_growth_apply", new_sticky)
|
||||
else:
|
||||
sync_growth_apply(new_sticky)
|
||||
|
||||
func _is_boundary(pos: Vector2i) -> bool:
|
||||
return pos.x == 0 or pos.x == ARENA_COLUMNS - 1 or pos.y == 0 or pos.y == ARENA_ROWS - 1
|
||||
return pos.x <= 0 or pos.x >= ARENA_COLUMNS - 1 or pos.y <= 0 or pos.y >= ARENA_ROWS - 1
|
||||
|
||||
# =============================================================================
|
||||
# Coverage tracking (v2 target: 70-75%, down from v1's 80%)
|
||||
@@ -1103,12 +1147,15 @@ const COVERAGE_TARGET_MAX: float = 0.75
|
||||
|
||||
func playable_cell_count() -> int:
|
||||
"""Number of cells that can ever become sticky (interior, minus NPC zone)."""
|
||||
var b = get_arena_bounds()
|
||||
var count := 0
|
||||
for x in range(ARENA_COLUMNS):
|
||||
for z in range(ARENA_ROWS):
|
||||
var pos := Vector2i(x, z)
|
||||
if _is_boundary(pos) or _is_npc_zone(pos):
|
||||
continue
|
||||
if pos.x <= b.min or pos.x >= b.max or pos.y <= b.min or pos.y >= b.max:
|
||||
continue
|
||||
count += 1
|
||||
return count
|
||||
|
||||
@@ -1132,6 +1179,9 @@ const FORCED_TRAP_WINDOW: float = 30.0 # final seconds where trapping is allowed
|
||||
|
||||
func _is_cell_passable(pos: Vector2i, extra_sticky: Dictionary = {}) -> bool:
|
||||
"""Can a player stand on / move through this cell, given a hypothetical sticky set?"""
|
||||
var b = get_arena_bounds()
|
||||
if pos.x <= b.min or pos.x >= b.max or pos.y <= b.min or pos.y >= b.max:
|
||||
return false
|
||||
if _is_boundary(pos) or _is_npc_zone(pos):
|
||||
return false
|
||||
if sticky_cells.has(pos) or extra_sticky.has(pos):
|
||||
@@ -1390,15 +1440,21 @@ func _bubble_score_unfair_trap(pos: Vector2i) -> float:
|
||||
func _bubble_blast_cells(center: Vector2i) -> Array:
|
||||
"""The 3x3 (radius 1) sticky cells a bubble at `center` would create,
|
||||
clipped to passable/playable cells."""
|
||||
var b = get_arena_bounds()
|
||||
var cells: Array = []
|
||||
for dx in range(-BUBBLE_EXPLOSION_RADIUS, BUBBLE_EXPLOSION_RADIUS + 1):
|
||||
for dz in range(-BUBBLE_EXPLOSION_RADIUS, BUBBLE_EXPLOSION_RADIUS + 1):
|
||||
var c := center + Vector2i(dx, dz)
|
||||
if _is_boundary(c) or _is_npc_zone(c):
|
||||
continue
|
||||
if c.x <= b.min or c.x >= b.max or c.y <= b.min or c.y >= b.max:
|
||||
continue
|
||||
cells.append(c)
|
||||
return cells
|
||||
|
||||
func _bubble_footprint(center: Vector2i) -> Array:
|
||||
return _bubble_blast_cells(center)
|
||||
|
||||
func _any_cleanser_holder_near(pos: Vector2i) -> bool:
|
||||
"""True if a player holding a Cleanser charge is within the camping region."""
|
||||
for player in get_tree().get_nodes_in_group("Players"):
|
||||
|
||||
@@ -165,9 +165,8 @@ func simple_move_to(grid_position: Vector2i) -> bool:
|
||||
gm.use_cleanser_cell(pid)
|
||||
print("[Move] Cleanser cleared sticky cell at %s (%d cells left)" % [grid_position, gm.cleanser_cells_left.get(pid, 0)])
|
||||
else:
|
||||
print("[Move] Player stepping into sticky cell at %s — slowed" % grid_position)
|
||||
if player.is_multiplayer_authority() or multiplayer.is_server():
|
||||
gm.apply_sticky_slow(player)
|
||||
print("[Move] Failed: Blocked by Gauntlet Sticky cell at %s" % grid_position)
|
||||
return false
|
||||
|
||||
rotate_towards_target(grid_position)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user