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