fix: hardcode NPC zone coordinates to strictly prevent tiles spawning underneath candy cannon

This commit is contained in:
2026-06-30 01:59:59 +08:00
parent 3ca2ff3c0f
commit cc584c3251
+48 -45
View File
@@ -412,22 +412,20 @@ func _apply_arena_setup() -> void:
var pos = Vector2i(x, z)
# Center 3x3 block: NPC obstacle (Candy Pump)
if _is_npc_zone(pos):
# Make the floor empty (-1) beneath the Candy Pump
# We need to clear all possible layers just in case
gridmap.set_cell_item(Vector3i(x, 0, z), -1)
if x >= 8 and x <= 10 and z >= 8 and z <= 10:
# Hardcode clear all possible layers beneath the Candy Pump
for layer in range(5):
gridmap.set_cell_item(Vector3i(x, layer, z), -1)
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:
# 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)
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:
# 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)
continue
# Interior: walkable floor
gridmap.set_cell_item(Vector3i(x, 0, z), TILE_WALKABLE)
gridmap.set_cell_item(Vector3i(x, 1, z), -1)
@@ -451,10 +449,7 @@ func _apply_arena_setup() -> void:
func _is_npc_zone(pos: Vector2i) -> bool:
"""Check if a position is within the center 3x3 NPC zone."""
var half = NPC_SIZE / 2 # integer division = 1
var min_coord = NPC_CENTER - Vector2i(half, half) # (8, 8)
var max_coord = NPC_CENTER + Vector2i(half, half) # (10, 10)
return pos.x >= min_coord.x and pos.x <= max_coord.x and pos.y >= min_coord.y and pos.y <= max_coord.y
return pos.x >= 8 and pos.x <= 10 and pos.y >= 8 and pos.y <= 10
func get_spawn_points(player_count: int) -> Array[Vector2i]:
"""Return spawn positions based on player count. Inside boundary walls."""
@@ -509,35 +504,35 @@ func _spawn_mission_tiles() -> void:
var goal_items = [7, 8, 9, 10]
var tiles_spawned: int = 0
for x in range(ARENA_COLUMNS):
for z in range(ARENA_ROWS):
var pos = Vector2i(x, z)
# Skip NPC pump zone (center 3x3)
if _is_npc_zone(pos):
continue
# Check base floor — don't spawn on void (or walls if they were still obstacles)
var base_tile = gridmap.get_cell_item(Vector3i(x, 0, z))
if base_tile == -1:
continue
# Ensure we don't spawn powerups on the perimeter walls even though they look like floors
if x == 0 or x == ARENA_COLUMNS - 1 or z == 0 or z == ARENA_ROWS - 1:
continue
# Skip if something already exists on Layer 1
var current_item = gridmap.get_cell_item(Vector3i(x, 1, z))
if current_item != -1:
continue
# Spawn tiles with 60% density (40% chance to skip)
if randf() > 0.6:
continue
var tile_type = goal_items[randi() % goal_items.size()]
gridmap.set_cell_item(Vector3i(x, 1, z), tile_type)
tiles_spawned += 1
for x in range(ARENA_COLUMNS):
for z in range(ARENA_ROWS):
var pos = Vector2i(x, z)
# Skip NPC pump zone (center 3x3)
if x >= 8 and x <= 10 and z >= 8 and z <= 10:
continue
# Check base floor — don't spawn on void (or walls if they were still obstacles)
var base_tile = gridmap.get_cell_item(Vector3i(x, 0, z))
if base_tile == -1:
continue
# Ensure we don't spawn powerups on the perimeter walls even though they look like floors
if x == 0 or x == ARENA_COLUMNS - 1 or z == 0 or z == ARENA_ROWS - 1:
continue
# Skip if something already exists on Layer 1
var current_item = gridmap.get_cell_item(Vector3i(x, 1, z))
if current_item != -1:
continue
# Spawn tiles with 60% density (40% chance to skip)
if randf() > 0.6:
continue
var tile_type = goal_items[randi() % goal_items.size()]
gridmap.set_cell_item(Vector3i(x, 1, z), tile_type)
tiles_spawned += 1
# Sync to clients
var main = get_node("/root/Main")
@@ -858,6 +853,8 @@ func sync_growth_telegraph(cells: Array) -> void:
for cell in cells:
var pos = cell as Vector2i
if pos.x >= 8 and pos.x <= 10 and pos.y >= 8 and pos.y <= 10: continue
# Telegraph overlay tile on Layer 2 (still passable).
gridmap.set_cell_item(Vector3i(pos.x, 2, pos.y), TILE_TELEGRAPH)
_spawn_telegraph_highlight(pos)
@@ -929,6 +926,8 @@ func sync_growth_apply(cells: Array) -> void:
if not gridmap: return
for cell in cells:
var pos = cell as Vector2i
if pos.x >= 8 and pos.x <= 10 and pos.y >= 8 and pos.y <= 10: continue
gridmap.set_cell_item(Vector3i(pos.x, 2, pos.y), TILE_STICKY)
sticky_cells[pos] = true
@@ -1518,6 +1517,8 @@ func sync_bubble_spawn(center: Vector2i, cells: Array) -> void:
# Telegraph-style warning overlay on the footprint (still passable).
for c in cells:
var pos = c as Vector2i
if pos.x >= 8 and pos.x <= 10 and pos.y >= 8 and pos.y <= 10: continue
gridmap.set_cell_item(Vector3i(pos.x, 2, pos.y), TILE_TELEGRAPH)
_spawn_bubble_visual(center)
if SfxManager:
@@ -1539,6 +1540,8 @@ func sync_bubble_explode(center: Vector2i, cells: Array) -> void:
return
for c in cells:
var pos = c as Vector2i
if pos.x >= 8 and pos.x <= 10 and pos.y >= 8 and pos.y <= 10: continue
gridmap.set_cell_item(Vector3i(pos.x, 2, pos.y), TILE_STICKY)
sticky_cells[pos] = true
# Medium shake — bubbles hit harder than a normal growth tick.