feat: Introduce Tekton roaming NPC with grid movement, player interaction, tile spawning, and visual effects.
This commit is contained in:
+3
-1
@@ -155,6 +155,8 @@ var _selected_character: String = "Masbro"
|
|||||||
var selected_character: String:
|
var selected_character: String:
|
||||||
get: return _selected_character
|
get: return _selected_character
|
||||||
set(value):
|
set(value):
|
||||||
|
if _selected_character == value:
|
||||||
|
return
|
||||||
_selected_character = value
|
_selected_character = value
|
||||||
if is_inside_tree():
|
if is_inside_tree():
|
||||||
set_character(value)
|
set_character(value)
|
||||||
@@ -368,7 +370,7 @@ func set_character(character_name: String) -> void:
|
|||||||
push_warning("Invalid character name: %s" % character_name)
|
push_warning("Invalid character name: %s" % character_name)
|
||||||
return
|
return
|
||||||
|
|
||||||
selected_character = character_name
|
_selected_character = character_name
|
||||||
|
|
||||||
# Hide all character models
|
# Hide all character models
|
||||||
if character_bob: character_bob.visible = false
|
if character_bob: character_bob.visible = false
|
||||||
|
|||||||
@@ -392,7 +392,7 @@ func _execute_block_floor(target_pos: Vector2i = Vector2i.ZERO):
|
|||||||
if "immutable_items" in enhanced_gridmap:
|
if "immutable_items" in enhanced_gridmap:
|
||||||
if original_item in enhanced_gridmap.immutable_items:
|
if original_item in enhanced_gridmap.immutable_items:
|
||||||
is_immutable = true
|
is_immutable = true
|
||||||
if original_item in [1, 2, 3, 4, 16] or is_immutable: continue
|
if original_item in [1, 2, 3, 4, 15, 16] or is_immutable: continue
|
||||||
|
|
||||||
batch_data.append({"x": block_pos.x, "y": 0, "z": block_pos.z, "item": 4})
|
batch_data.append({"x": block_pos.x, "y": 0, "z": block_pos.z, "item": 4})
|
||||||
|
|
||||||
@@ -442,6 +442,11 @@ func spawn_powerups_around(center: Vector2i, force_powerups: bool = true, only_c
|
|||||||
# PROTECTED FLOOR CHECK: Don't spawn on existing walls or void
|
# PROTECTED FLOOR CHECK: Don't spawn on existing walls or void
|
||||||
var f0 = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
var f0 = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
||||||
var f1 = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 1, pos.y))
|
var f1 = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 1, pos.y))
|
||||||
|
|
||||||
|
# Stop n Go: Don't overwrite static powerup spawns (ID 15 floor)
|
||||||
|
if LobbyManager.is_game_mode(GameMode.Mode.STOP_N_GO) and f0 == 15:
|
||||||
|
continue
|
||||||
|
|
||||||
if f0 in [4, -1] or f1 in [4, 16]:
|
if f0 in [4, -1] or f1 in [4, 16]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -449,16 +454,16 @@ func spawn_powerups_around(center: Vector2i, force_powerups: bool = true, only_c
|
|||||||
var mode = LobbyManager.get_game_mode()
|
var mode = LobbyManager.get_game_mode()
|
||||||
|
|
||||||
if only_common or LobbyManager.is_game_mode(GameMode.Mode.STOP_N_GO):
|
if only_common or LobbyManager.is_game_mode(GameMode.Mode.STOP_N_GO):
|
||||||
# Spawn ONLY common tiles (7-10) for Stop n Go or if forced
|
# Spawn ONLY common tiles (7-10) in Stop n Go mode (User Request)
|
||||||
item_id = rng.randi_range(7, 10)
|
item_id = rng.randi_range(7, 10)
|
||||||
else:
|
else:
|
||||||
# Free mode: 80% Chance for Common Tile (7-10), 20% for PowerUp
|
# Other modes: 80% Chance for Common Tile (7-10), 20% for PowerUp
|
||||||
if rng.randf() < 0.8:
|
if rng.randf() < 0.8:
|
||||||
item_id = rng.randi_range(7, 10)
|
item_id = rng.randi_range(7, 10)
|
||||||
else:
|
else:
|
||||||
# 20% Chance for PowerUp
|
# 20% Chance for PowerUp
|
||||||
var is_restricted = GameMode.is_restricted(mode)
|
if LobbyManager.is_game_mode(GameMode.Mode.TEKTON_DOORS):
|
||||||
if is_restricted:
|
# Restrict to Speed (11) and Ghost (14) for Tekton Doors
|
||||||
item_id = [11, 14].pick_random()
|
item_id = [11, 14].pick_random()
|
||||||
else:
|
else:
|
||||||
item_id = rng.randi_range(11, 14)
|
item_id = rng.randi_range(11, 14)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ var safe_zone_centers: Array[Vector2i] = []
|
|||||||
var safe_zone_spawned: bool = false
|
var safe_zone_spawned: bool = false
|
||||||
|
|
||||||
# Power-Up Tile Spawning
|
# Power-Up Tile Spawning
|
||||||
const POWERUP_TILES = [11, 12, 13, 14] # Speed, Freeze, Wall, Ghost
|
const POWERUP_TILES = [11, 14] # Speed, Ghost (Freeze and Wall excluded in this mode)
|
||||||
const POWERUP_SPAWN_COUNT: int = 5 # Number of power-up tiles to spawn
|
const POWERUP_SPAWN_COUNT: int = 5 # Number of power-up tiles to spawn
|
||||||
var powerups_spawned: bool = false
|
var powerups_spawned: bool = false
|
||||||
var stop_phase_occurred: bool = false
|
var stop_phase_occurred: bool = false
|
||||||
@@ -360,8 +360,8 @@ func _spawn_mission_tiles():
|
|||||||
var base_tile = gridmap.get_cell_item(Vector3i(x, 0, z))
|
var base_tile = gridmap.get_cell_item(Vector3i(x, 0, z))
|
||||||
var current_item = gridmap.get_cell_item(Vector3i(x, 1, z))
|
var current_item = gridmap.get_cell_item(Vector3i(x, 1, z))
|
||||||
|
|
||||||
# PROTECTED FLOOR CHECK: Don't spawn on walls or void
|
# PROTECTED FLOOR CHECK: Don't spawn on walls, void, or static powerup pods
|
||||||
if base_tile in [TILE_OBSTACLE, -1] or current_item == TILE_OBSTACLE:
|
if base_tile in [TILE_OBSTACLE, -1, TILE_LIGHTNING_STONE] or current_item == TILE_OBSTACLE:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Spawn tiles with 60% density
|
# Spawn tiles with 60% density
|
||||||
@@ -593,9 +593,9 @@ func _scatter_player_tiles(player_node: Node):
|
|||||||
# Bounds check
|
# Bounds check
|
||||||
if pos.x < 0 or pos.x >= gridmap.columns or pos.y < 0 or pos.y >= gridmap.rows:
|
if pos.x < 0 or pos.x >= gridmap.columns or pos.y < 0 or pos.y >= gridmap.rows:
|
||||||
continue
|
continue
|
||||||
# Check floor is walkable (not void, not obstacle)
|
# Check floor is walkable (not void, not obstacle, not static powerup spawn)
|
||||||
var floor_tile = gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
var floor_tile = gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
||||||
if floor_tile == -1 or floor_tile == TILE_OBSTACLE:
|
if floor_tile == -1 or floor_tile == TILE_OBSTACLE or floor_tile == TILE_LIGHTNING_STONE:
|
||||||
continue
|
continue
|
||||||
# Check floor 1 is empty (no existing item)
|
# Check floor 1 is empty (no existing item)
|
||||||
var existing_item = gridmap.get_cell_item(Vector3i(pos.x, 1, pos.y))
|
var existing_item = gridmap.get_cell_item(Vector3i(pos.x, 1, pos.y))
|
||||||
@@ -750,8 +750,8 @@ func _spawn_powerup_tiles():
|
|||||||
# Set Floor 0 beneath power-up to ID 15 (Ancient Lightning Stone)
|
# Set Floor 0 beneath power-up to ID 15 (Ancient Lightning Stone)
|
||||||
gridmap.set_cell_item(Vector3i(pos.x, 0, pos.y), TILE_LIGHTNING_STONE)
|
gridmap.set_cell_item(Vector3i(pos.x, 0, pos.y), TILE_LIGHTNING_STONE)
|
||||||
|
|
||||||
# Cycle through the available power-up types
|
# Select a random power-up type (User Request: ensure all types can spawn)
|
||||||
var tile_id = POWERUP_TILES[i % POWERUP_TILES.size()]
|
var tile_id = POWERUP_TILES.pick_random()
|
||||||
|
|
||||||
# Place on Floor 1
|
# Place on Floor 1
|
||||||
gridmap.set_cell_item(Vector3i(pos.x, 1, pos.y), tile_id)
|
gridmap.set_cell_item(Vector3i(pos.x, 1, pos.y), tile_id)
|
||||||
|
|||||||
+28
-18
@@ -298,9 +298,8 @@ func temporarily_change_floor(center: Vector2i, radius: int, new_id: int, durati
|
|||||||
var cell_3d = Vector3i(pos.x, 0, pos.y)
|
var cell_3d = Vector3i(pos.x, 0, pos.y)
|
||||||
var original = enhanced_gridmap.get_cell_item(cell_3d)
|
var original = enhanced_gridmap.get_cell_item(cell_3d)
|
||||||
|
|
||||||
# Only change if not already the new ID (avoid redundant updates or overriding existing freeze)
|
# PROTECTED FLOOR CHECK: avoid overwriting Start (1), Safe (2), Finish (3), Wall (4), or PowerUp Stand (15)
|
||||||
# PROTECTED FLOOR CHECK: avoid overwriting Start (1), Safe (2), Finish (3), or Wall (4)
|
if original != new_id and not original in [1, 2, 3, 4, 15]:
|
||||||
if original != new_id and not original in [1, 2, 3, 4]:
|
|
||||||
# PRE-FIX: If we capture a "Hole" (Void or Pickup 7-14) here, we must record it as Floor (0)
|
# PRE-FIX: If we capture a "Hole" (Void or Pickup 7-14) here, we must record it as Floor (0)
|
||||||
# so that we restore a valid floor later.
|
# so that we restore a valid floor later.
|
||||||
if original == -1 or (original >= 7 and original <= 14):
|
if original == -1 or (original >= 7 and original <= 14):
|
||||||
@@ -371,24 +370,35 @@ func spawn_tiles_around(count: int = 4):
|
|||||||
if _is_position_blocked_by_stand(pos):
|
if _is_position_blocked_by_stand(pos):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# EXTRA CHECK: Do not spawn tiles on walls (ID 4) or empty void (ID -1) on Floor 0
|
# EXTRA CHECK: Do not spawn tiles on walls (ID 4), empty void (ID -1), or static powerup spawns (ID 15)
|
||||||
# Note: We allow spawning on Safe Zones, Start, and Finish as it's on Layer 1.
|
var floor_0_item = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
||||||
var floor_0_item = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
|
||||||
if floor_0_item in [4, -1]:
|
# Stop n Go: Don't overwrite static powerup spawns
|
||||||
continue
|
if LobbyManager and LobbyManager.game_mode == "Stop n Go" and floor_0_item == 15:
|
||||||
|
continue
|
||||||
# 50% chance to spawn something
|
|
||||||
if rng.randf() > 0.5: continue
|
|
||||||
|
|
||||||
# Determine Type
|
if floor_0_item in [4, -1]:
|
||||||
var item_id: int
|
continue
|
||||||
var roll = rng.randf()
|
|
||||||
|
|
||||||
if roll < 0.6:
|
# 50% chance to spawn something
|
||||||
# 60% Normal Tile (7-10)
|
if rng.randf() > 0.5: continue
|
||||||
item_id = rng.randi_range(7, 10)
|
|
||||||
|
# Determine Type
|
||||||
|
var item_id: int
|
||||||
|
var roll = rng.randf()
|
||||||
|
|
||||||
|
if roll < 0.6 or (LobbyManager and LobbyManager.game_mode == "Stop n Go"):
|
||||||
|
# 60% Normal Tile (7-10) OR 100% if Stop n Go (User Request)
|
||||||
|
item_id = rng.randi_range(7, 10)
|
||||||
|
else:
|
||||||
|
# 40% PowerUp (11-14)
|
||||||
|
var mode = GameMode.Mode.FREEMODE
|
||||||
|
if LobbyManager:
|
||||||
|
mode = LobbyManager.get_game_mode()
|
||||||
|
|
||||||
|
if mode == GameMode.Mode.TEKTON_DOORS:
|
||||||
|
item_id = [11, 14].pick_random()
|
||||||
else:
|
else:
|
||||||
# 40% PowerUp (11-14)
|
|
||||||
item_id = rng.randi_range(11, 14)
|
item_id = rng.randi_range(11, 14)
|
||||||
|
|
||||||
if item_id != -1:
|
if item_id != -1:
|
||||||
|
|||||||
Reference in New Issue
Block a user