feat: Implement new Stop 'n' Go game mode with dedicated manager, player logic, and control scripts.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
extends Node
|
||||
|
||||
|
||||
|
||||
# SpecialTilesManager - Handles special effects triggered by holo tile pickups
|
||||
|
||||
# Holo tile indices (11-14) trigger special effects
|
||||
@@ -370,7 +369,7 @@ func _execute_area_freeze(target_pos: Vector2i = Vector2i.ZERO):
|
||||
# Check if it is STILL Freeze Overlay
|
||||
var current_check = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 2, pos.y))
|
||||
if current_check == 5:
|
||||
restore_batch.append({"x": pos.x, "y": 2, "z": pos.y, "item": -1})
|
||||
restore_batch.append({"x": pos.x, "y": 2, "z": pos.y, "item": - 1})
|
||||
|
||||
if not restore_batch.is_empty():
|
||||
main.rpc("sync_grid_items_batch", restore_batch)
|
||||
|
||||
@@ -10,10 +10,8 @@ signal player_penalized(player_id: int)
|
||||
enum Phase {GO, STOP}
|
||||
|
||||
# Dynamic Safe Zone
|
||||
const SAFE_ZONE_PRE_TIME: float = 5.0 # Seconds before STOP to spawn safe zone
|
||||
const SAFE_ZONE_RADIUS: int = 2 # 5x5 area (radius 2 from center)
|
||||
var safe_zone_centers: Array[Vector2i] = []
|
||||
var safe_zone_spawned: bool = false
|
||||
var active_safe_zone_rects: Array[Rect2i] = []
|
||||
var spawned_safe_zones: int = 0
|
||||
|
||||
# Power-Up Tile Spawning
|
||||
const POWERUP_TILES = [11, 14] # Speed, Ghost (Freeze and Wall excluded in this mode)
|
||||
@@ -21,8 +19,7 @@ const POWERUP_SPAWN_COUNT: int = 5 # Number of power-up tiles to spawn
|
||||
var powerups_spawned: bool = false
|
||||
var stop_phase_occurred: bool = false
|
||||
|
||||
var safe_zone_wall_scene = preload("res://scenes/safe_zone_wall.tscn")
|
||||
|
||||
# Safe zone walls removed for fully open dynamic zones
|
||||
const PERMANENT_POWERUP_LOCATIONS: Array[Vector2i] = [
|
||||
Vector2i(4, 1), # Power up 1
|
||||
Vector2i(3, 9), # Power up 2
|
||||
@@ -101,6 +98,15 @@ func _process(delta):
|
||||
phase_timer -= delta
|
||||
|
||||
if multiplayer.is_server():
|
||||
if current_phase == Phase.GO:
|
||||
var int_timer = int(ceil(phase_timer))
|
||||
if int_timer == 3 and spawned_safe_zones == 0 and phase_timer <= 3.0:
|
||||
_spawn_dynamic_safe_zone()
|
||||
elif int_timer == 2 and spawned_safe_zones == 1 and phase_timer <= 2.0:
|
||||
_spawn_dynamic_safe_zone()
|
||||
elif int_timer == 1 and spawned_safe_zones == 2 and phase_timer <= 1.0:
|
||||
_spawn_dynamic_safe_zone()
|
||||
|
||||
if phase_timer <= 0:
|
||||
if current_phase == Phase.GO:
|
||||
_start_phase(Phase.STOP)
|
||||
@@ -247,8 +253,9 @@ func _start_phase(phase: Phase):
|
||||
# Refresh power-ups every STOP phase
|
||||
_spawn_powerup_tiles()
|
||||
|
||||
# If GO phase starts, clear all STOP phase freezes
|
||||
# If GO phase starts, clear all STOP phase freezes and dynamic safe zones
|
||||
if phase == Phase.GO:
|
||||
_clear_dynamic_safe_zones()
|
||||
var all_players = get_tree().get_nodes_in_group("Players")
|
||||
for p in all_players:
|
||||
if p.has_method("sync_stop_freeze"):
|
||||
@@ -347,9 +354,7 @@ func _apply_arena_setup():
|
||||
gridmap.set_cell_item(Vector3i(x, 0, z), tile_id)
|
||||
gridmap.set_cell_item(Vector3i(x, 1, z), -1)
|
||||
|
||||
# Paint Static Safe Zones
|
||||
_paint_static_safe_zone(gridmap, 7, 11, 6, 9, -1, -1, 8, 8)
|
||||
_paint_static_safe_zone(gridmap, 15, 19, 1, 5, -1, 18, 2, 2)
|
||||
# Dynamic Safe Zones are procedural and spawn during GO phase
|
||||
|
||||
# Note: Specific obstacles removed as per user request to replace with random ones.
|
||||
# MISSION TILES: Moved to start_game_mode() to ensure they spawn AFTER walls.
|
||||
@@ -488,40 +493,91 @@ func check_win_condition(player_id: int, position: Vector2i) -> bool:
|
||||
# Static Safe Zone
|
||||
# =============================================================================
|
||||
|
||||
func _paint_static_safe_zone(gridmap: Node, min_x: int, max_x: int, min_z: int, max_z: int, north_door_x: int = -1, south_door_x: int = -1, west_door_z: int = -1, east_door_z: int = -1):
|
||||
# Paint safe floor
|
||||
for x in range(min_x, max_x + 1):
|
||||
for z in range(min_z, max_z + 1):
|
||||
gridmap.set_cell_item(Vector3i(x, 0, z), TILE_SAFE)
|
||||
|
||||
# Get center opening for horizontal walls
|
||||
var center_n_x = north_door_x if north_door_x != -1 else int(float(min_x + max_x) / 2.0)
|
||||
var center_s_x = south_door_x if south_door_x != -1 else int(float(min_x + max_x) / 2.0)
|
||||
|
||||
# Instantiate Top and Bottom horizontal walls
|
||||
for x in range(min_x, max_x + 1):
|
||||
if x != center_n_x:
|
||||
_instantiate_safe_zone_wall(Vector3(x + 0.5, 0.0, min_z), 0) # Bottom/North
|
||||
if x != center_s_x:
|
||||
_instantiate_safe_zone_wall(Vector3(x + 0.5, 0.0, max_z + 1), 0) # Top/South
|
||||
|
||||
# Get center opening for vertical walls
|
||||
var center_w_z = west_door_z if west_door_z != -1 else int(float(min_z + max_z) / 2.0)
|
||||
var center_e_z = east_door_z if east_door_z != -1 else int(float(min_z + max_z) / 2.0)
|
||||
|
||||
for z in range(min_z, max_z + 1):
|
||||
if z != center_w_z:
|
||||
_instantiate_safe_zone_wall(Vector3(min_x, 0.0, z + 0.5), 90) # Left/West
|
||||
if z != center_e_z:
|
||||
_instantiate_safe_zone_wall(Vector3(max_x + 1, 0.0, z + 0.5), 90) # Right/East
|
||||
|
||||
func _is_in_safe_zone(pos: Vector2i) -> bool:
|
||||
"""Check if a position is within ANY of the static safe zones."""
|
||||
# Safe zone 1: [7,6] - [11,9]
|
||||
if pos.x >= 7 and pos.x <= 11 and pos.y >= 6 and pos.y <= 9: return true
|
||||
# Safe zone 2: [15,1] - [19,5]
|
||||
if pos.x >= 15 and pos.x <= 19 and pos.y >= 1 and pos.y <= 5: return true
|
||||
return false
|
||||
var gridmap = get_parent().get_node_or_null("EnhancedGridMap")
|
||||
if not gridmap:
|
||||
gridmap = get_node_or_null("/root/Main/EnhancedGridMap")
|
||||
if not gridmap: return false
|
||||
|
||||
var floor_tile = gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
||||
return floor_tile == TILE_SAFE
|
||||
|
||||
func _spawn_dynamic_safe_zone():
|
||||
if not multiplayer.is_server(): return
|
||||
var gridmap = get_parent().get_node_or_null("EnhancedGridMap")
|
||||
if not gridmap: gridmap = get_node_or_null("/root/Main/EnhancedGridMap")
|
||||
if not gridmap: return
|
||||
|
||||
var main = get_node("/root/Main")
|
||||
var possible_rects = []
|
||||
|
||||
# Check all possible 3x2 and 2x3 areas
|
||||
for x in range(1, gridmap.columns - 3):
|
||||
for z in range(1, gridmap.rows - 2):
|
||||
if _is_valid_safe_zone_area(gridmap, x, z, 3, 2):
|
||||
possible_rects.append(Rect2i(x, z, 3, 2))
|
||||
if _is_valid_safe_zone_area(gridmap, x, z, 2, 3):
|
||||
possible_rects.append(Rect2i(x, z, 2, 3))
|
||||
|
||||
if possible_rects.size() > 0:
|
||||
var rect = possible_rects.pick_random()
|
||||
active_safe_zone_rects.append(rect)
|
||||
spawned_safe_zones += 1
|
||||
|
||||
# Paint floor to TILE_SAFE
|
||||
for rx in range(rect.size.x):
|
||||
for rz in range(rect.size.y):
|
||||
var px = rect.position.x + rx
|
||||
var pz = rect.position.y + rz
|
||||
gridmap.set_cell_item(Vector3i(px, 0, pz), TILE_SAFE)
|
||||
if can_rpc() and main:
|
||||
main.rpc("sync_grid_item", px, 0, pz, TILE_SAFE)
|
||||
|
||||
func _is_valid_safe_zone_area(gridmap: Node, start_x: int, start_z: int, width: int, height: int) -> bool:
|
||||
# Avoid bounds or start/finish cols
|
||||
if start_x < 2 or start_x + width > gridmap.columns - 2: return false
|
||||
if start_z < 1 or start_z + height > gridmap.rows - 1: return false
|
||||
|
||||
var test_rect = Rect2i(start_x, start_z, width, height)
|
||||
for existing in active_safe_zone_rects:
|
||||
if test_rect.intersects(existing):
|
||||
return false
|
||||
|
||||
for x in range(start_x, start_x + width):
|
||||
for z in range(start_z, start_z + height):
|
||||
var floor_0 = gridmap.get_cell_item(Vector3i(x, 0, z))
|
||||
var floor_1 = gridmap.get_cell_item(Vector3i(x, 1, z))
|
||||
|
||||
# Floor must be purely TILE_WALKABLE (0)
|
||||
if floor_0 != TILE_WALKABLE:
|
||||
return false
|
||||
|
||||
# Floor 1 must be empty (-1) - no items or obstacles
|
||||
if floor_1 != -1:
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
func _clear_dynamic_safe_zones():
|
||||
var gridmap = get_parent().get_node_or_null("EnhancedGridMap")
|
||||
if not gridmap: gridmap = get_node_or_null("/root/Main/EnhancedGridMap")
|
||||
if not gridmap: return
|
||||
var main = get_node_or_null("/root/Main")
|
||||
|
||||
for rect in active_safe_zone_rects:
|
||||
for rx in range(rect.size.x):
|
||||
for rz in range(rect.size.y):
|
||||
var px = rect.position.x + rx
|
||||
var pz = rect.position.y + rz
|
||||
|
||||
# Only clear if it is actually still a safe zone
|
||||
if gridmap.get_cell_item(Vector3i(px, 0, pz)) == TILE_SAFE:
|
||||
gridmap.set_cell_item(Vector3i(px, 0, pz), TILE_WALKABLE)
|
||||
if can_rpc() and main:
|
||||
main.rpc("sync_grid_item", px, 0, pz, TILE_WALKABLE)
|
||||
|
||||
active_safe_zone_rects.clear()
|
||||
spawned_safe_zones = 0
|
||||
|
||||
func _scatter_player_tiles(player_node: Node):
|
||||
"""Server: Take all tiles from player's playerboard and scatter them onto nearby grid cells."""
|
||||
@@ -595,16 +651,32 @@ func _scatter_player_tiles(player_node: Node):
|
||||
|
||||
print("[StopNGo] Scattered %d tiles from Player %d" % [tiles_to_scatter.size(), peer_id])
|
||||
|
||||
# Removed dynamic sync methods.
|
||||
# =============================================================================
|
||||
# OLD STATIC SAFE ZONE LOGIC (Retained for Reference)
|
||||
# =============================================================================
|
||||
# var safe_zone_columns: Array[int] = [5, 10, 15]
|
||||
|
||||
func _instantiate_safe_zone_wall(pos: Vector3, rotation_deg: float):
|
||||
if not safe_zone_wall_scene: return
|
||||
|
||||
var wall = safe_zone_wall_scene.instantiate()
|
||||
add_child(wall)
|
||||
wall.add_to_group("SafeZoneWalls")
|
||||
wall.position = pos
|
||||
wall.rotation_degrees.y = rotation_deg
|
||||
# func _is_in_safe_zone_old(pos: Vector2i) -> bool:
|
||||
# return pos.x in safe_zone_columns
|
||||
|
||||
# func _paint_static_safe_zones(gridmap):
|
||||
# for x in safe_zone_columns:
|
||||
# for z in range(gridmap.rows):
|
||||
# gridmap.set_cell_item(Vector3i(x, 0, z), TILE_SAFE)
|
||||
# # Optional: instantiate walls
|
||||
# # _instantiate_safe_zone_wall(gridmap, x, z)
|
||||
|
||||
# func _instantiate_safe_zone_wall(gridmap, x: int, z: int):
|
||||
# var wall_scene = load("res://scenes/environment/safe_zone_wall.tscn")
|
||||
# if wall_scene:
|
||||
# var wall = wall_scene.instantiate()
|
||||
# gridmap.add_child(wall)
|
||||
# wall.global_position = Vector3(
|
||||
# x * gridmap.cell_size.x + gridmap.cell_size.x/2,
|
||||
# 0,
|
||||
# z * gridmap.cell_size.z + gridmap.cell_size.z/2
|
||||
# )
|
||||
# =============================================================================
|
||||
|
||||
# =============================================================================
|
||||
# Power-Up Tile Spawning (Speed & Ghost)
|
||||
|
||||
@@ -160,7 +160,7 @@ func _create_touch_ui():
|
||||
# User Request: "move those button to ActionsBtn children"
|
||||
|
||||
attack_mode_button = _find_or_create_action_button(actions_container, "AttackMode", "⚡", button_positions.attack_mode) # Renamed
|
||||
spawn_boost_button = _find_or_create_action_button(actions_container, "SpawnBoost", "🚀", button_positions.spawn_boost)
|
||||
# spawn_boost_button = _find_or_create_action_button(actions_container, "SpawnBoost", "🚀", button_positions.spawn_boost)
|
||||
grab_button = _find_or_create_action_button(actions_container, "Grab", "👋", button_positions.grab)
|
||||
put_button = _find_or_create_action_button(actions_container, "Put", "📦", button_positions.put)
|
||||
|
||||
@@ -173,10 +173,10 @@ func _create_touch_ui():
|
||||
attack_mode_button.icon = load("res://assets/graphics/touch_control/attack_mode.png")
|
||||
attack_mode_button.expand_icon = true
|
||||
|
||||
if spawn_boost_button:
|
||||
actions_container.move_child(spawn_boost_button, 1)
|
||||
spawn_boost_button.icon = load("res://assets/graphics/touch_control/spawn_tile.png")
|
||||
spawn_boost_button.expand_icon = true
|
||||
# if spawn_boost_button:
|
||||
# actions_container.move_child(spawn_boost_button, 1)
|
||||
# spawn_boost_button.icon = load("res://assets/graphics/touch_control/spawn_tile.png")
|
||||
# spawn_boost_button.expand_icon = true
|
||||
|
||||
if grab_button:
|
||||
actions_container.move_child(grab_button, 2)
|
||||
@@ -308,7 +308,7 @@ func _ensure_shortcut_label(btn: Button, button_name: String):
|
||||
"Grab": existing_lbl.text = SettingsManager.get_control_text("grab")
|
||||
"Put": existing_lbl.text = ""
|
||||
"AttackMode": existing_lbl.text = SettingsManager.get_control_text("attack_mode")
|
||||
"SpawnBoost": existing_lbl.text = SettingsManager.get_control_text("spawn_boost")
|
||||
# "SpawnBoost": existing_lbl.text = SettingsManager.get_control_text("spawn_boost")
|
||||
"TektonGrab": existing_lbl.text = SettingsManager.get_control_text("tekton_grab")
|
||||
|
||||
|
||||
@@ -341,7 +341,7 @@ func _ensure_shortcut_label(btn: Button, button_name: String):
|
||||
"Grab": shortcut_lbl.text = SettingsManager.get_control_text("grab") if SettingsManager else "Space"
|
||||
"Put": shortcut_lbl.text = "" # Disabled shortcut
|
||||
"AttackMode": shortcut_lbl.text = SettingsManager.get_control_text("attack_mode") if SettingsManager else "Q"
|
||||
"SpawnBoost": shortcut_lbl.text = SettingsManager.get_control_text("spawn_boost") if SettingsManager else "E"
|
||||
# "SpawnBoost": shortcut_lbl.text = SettingsManager.get_control_text("spawn_boost") if SettingsManager else "E"
|
||||
"TektonGrab": shortcut_lbl.text = SettingsManager.get_control_text("tekton_grab") if SettingsManager else "G"
|
||||
|
||||
|
||||
@@ -394,13 +394,16 @@ func _on_button_pressed(button_name: String):
|
||||
pass
|
||||
else:
|
||||
print("[TouchControls] PowerUpManager missing on player")
|
||||
"SpawnBoost":
|
||||
if local_player and local_player.is_carrying_tekton:
|
||||
# "SpawnBoost":
|
||||
# if local_player and local_player.is_carrying_tekton:
|
||||
# if local_player.powerup_manager and local_player.powerup_manager.has_method("spawn_boost_reward"):
|
||||
# local_player.powerup_manager.spawn_boost_reward()
|
||||
"TektonGrab":
|
||||
if local_player.is_carrying_tekton:
|
||||
if local_player.powerup_manager and local_player.powerup_manager.has_method("spawn_boost_reward"):
|
||||
local_player.powerup_manager.spawn_boost_reward()
|
||||
"TektonGrab":
|
||||
if not local_player.is_carrying_tekton:
|
||||
if local_player.has_method("grab_tekton"):
|
||||
else:
|
||||
if not local_player.is_carrying_tekton and local_player.has_method("grab_tekton"):
|
||||
local_player.grab_tekton()
|
||||
|
||||
|
||||
@@ -523,13 +526,14 @@ func _apply_settings():
|
||||
attack_mode_button.offset_bottom = button_positions.attack_mode.y + button_size
|
||||
|
||||
if spawn_boost_button:
|
||||
spawn_boost_button.visible = true
|
||||
spawn_boost_button.scale = Vector2(button_scale, button_scale)
|
||||
spawn_boost_button.set_anchors_preset(Control.PRESET_BOTTOM_RIGHT)
|
||||
spawn_boost_button.offset_left = button_positions.spawn_boost.x
|
||||
spawn_boost_button.offset_top = button_positions.spawn_boost.y
|
||||
spawn_boost_button.offset_right = button_positions.spawn_boost.x + button_size
|
||||
spawn_boost_button.offset_bottom = button_positions.spawn_boost.y + button_size
|
||||
# spawn_boost_button.visible = true
|
||||
# spawn_boost_button.scale = Vector2(button_scale, button_scale)
|
||||
# spawn_boost_button.set_anchors_preset(Control.PRESET_BOTTOM_RIGHT)
|
||||
# spawn_boost_button.offset_left = button_positions.spawn_boost.x
|
||||
# spawn_boost_button.offset_top = button_positions.spawn_boost.y
|
||||
# spawn_boost_button.offset_right = button_positions.spawn_boost.x + button_size
|
||||
# spawn_boost_button.offset_bottom = button_positions.spawn_boost.y + button_size
|
||||
spawn_boost_button.visible = false
|
||||
|
||||
if tekton_grab_button:
|
||||
tekton_grab_button.visible = true
|
||||
@@ -598,15 +602,28 @@ func _on_boost_points_changed(current_points: int, max_points: int):
|
||||
_update_boost_button_state(attack_mode_button, can_attack)
|
||||
|
||||
# SpawnBoost depends on carrying a Tekton, not boost points
|
||||
var can_spawn = local_player and local_player.is_carrying_tekton
|
||||
_update_boost_button_state(spawn_boost_button, can_spawn)
|
||||
# var can_spawn = local_player and local_player.is_carrying_tekton
|
||||
# _update_boost_button_state(spawn_boost_button, can_spawn)
|
||||
|
||||
# Tekton Grab (👋) is only enabled if full AND not already carrying one
|
||||
var can_grab = is_full and not (local_player and local_player.is_carrying_tekton)
|
||||
_update_boost_button_state(tekton_grab_button, can_grab)
|
||||
# Now modified: If CARRYING, it is ALWAYS enabled to act as SpawnBoost. If NOT carrying, needs to be full.
|
||||
var can_grab_or_spawn = (local_player and local_player.is_carrying_tekton) or (is_full)
|
||||
_update_boost_button_state(tekton_grab_button, can_grab_or_spawn)
|
||||
|
||||
func _on_tekton_carried_changed(_is_carrying: bool):
|
||||
# Refresh button states when player grabs/throws a tekton
|
||||
if tekton_grab_button:
|
||||
if _is_carrying:
|
||||
# Swapping to Spawn function (Hotkey E)
|
||||
tekton_grab_button.icon = load("res://assets/graphics/touch_control/spawn_tile.png")
|
||||
if SettingsManager:
|
||||
_ensure_shortcut_label(tekton_grab_button, "SpawnBoost")
|
||||
else:
|
||||
# Swapping back to Grab function (Hotkey G)
|
||||
tekton_grab_button.icon = load("res://assets/graphics/touch_control/grab_tekton.png")
|
||||
if SettingsManager:
|
||||
_ensure_shortcut_label(tekton_grab_button, "TektonGrab")
|
||||
|
||||
var powerup_mgr = local_player.get_node_or_null("PowerUpManager")
|
||||
if powerup_mgr:
|
||||
_on_boost_points_changed(powerup_mgr.current_boost, powerup_mgr.MAX_BOOST)
|
||||
|
||||
@@ -38,7 +38,7 @@ func _on_timer_timeout():
|
||||
if not is_multiplayer_authority(): return
|
||||
if not tekton or not enhanced_gridmap: return
|
||||
|
||||
if tekton.get("is_carried") or tekton.get("is_thrown"):
|
||||
if tekton.get("is_carried") or tekton.get("is_thrown"):
|
||||
_start_timer()
|
||||
return
|
||||
|
||||
@@ -59,9 +59,9 @@ func _attempt_throw():
|
||||
var target_world_pos = Vector3(target.x + 0.5, 0, target.y + 0.5)
|
||||
if enhanced_gridmap and "cell_size" in enhanced_gridmap:
|
||||
target_world_pos = Vector3(
|
||||
target.x * enhanced_gridmap.cell_size.x + enhanced_gridmap.cell_size.x/2,
|
||||
0,
|
||||
target.y * enhanced_gridmap.cell_size.z + enhanced_gridmap.cell_size.z/2
|
||||
target.x * enhanced_gridmap.cell_size.x + enhanced_gridmap.cell_size.x / 2,
|
||||
0,
|
||||
target.y * enhanced_gridmap.cell_size.z + enhanced_gridmap.cell_size.z / 2
|
||||
)
|
||||
|
||||
tekton.look_at(Vector3(target_world_pos.x, tekton.global_position.y, target_world_pos.z), Vector3.UP)
|
||||
|
||||
+51
-1
@@ -191,12 +191,62 @@ func _process(delta):
|
||||
global_position = carrier.global_position + Vector3(0, 1.5, 0)
|
||||
rotation = carrier.rotation
|
||||
|
||||
_update_prompt_label()
|
||||
|
||||
var mesh_cache: Array[MeshInstance3D] = []
|
||||
var original_scales: Array[Vector3] = []
|
||||
var prompt_label: Label3D
|
||||
@onready var SettingsManager = get_node_or_null("/root/SettingsManager")
|
||||
|
||||
func _update_prompt_label():
|
||||
if not prompt_label: return
|
||||
|
||||
if is_static_turret or is_carried or is_thrown or is_recovering:
|
||||
prompt_label.visible = false
|
||||
return
|
||||
|
||||
var authority_player = null
|
||||
var players = get_tree().get_nodes_in_group("Players")
|
||||
for p in players:
|
||||
if p.name == str(multiplayer.get_unique_id()):
|
||||
authority_player = p
|
||||
break
|
||||
|
||||
if not authority_player:
|
||||
prompt_label.visible = false
|
||||
return
|
||||
|
||||
# Check distance
|
||||
var player_pos = Vector2(authority_player.current_position.x, authority_player.current_position.y)
|
||||
var tekton_pos = Vector2(current_position.x, current_position.y)
|
||||
if player_pos.distance_to(tekton_pos) > 1.5:
|
||||
prompt_label.visible = false
|
||||
return
|
||||
|
||||
# Check power bar
|
||||
var pw_mgr = authority_player.get_node_or_null("PowerUpManager")
|
||||
if pw_mgr and pw_mgr.current_boost >= (pw_mgr.MAX_BOOST - 1):
|
||||
prompt_label.visible = true
|
||||
else:
|
||||
prompt_label.visible = false
|
||||
|
||||
func _ready():
|
||||
# Cache meshes and their initial scales
|
||||
_cache_meshes(self )
|
||||
_cache_meshes(self)
|
||||
|
||||
prompt_label = Label3D.new()
|
||||
var shortcut_text = "G"
|
||||
if SettingsManager and SettingsManager.has_method("get_control_text"):
|
||||
shortcut_text = SettingsManager.get_control_text("tekton_grab")
|
||||
prompt_label.text = "[ " + str(shortcut_text) + " ]"
|
||||
prompt_label.font_size = 64
|
||||
prompt_label.outline_size = 12
|
||||
prompt_label.billboard = BaseMaterial3D.BILLBOARD_ENABLED
|
||||
prompt_label.no_depth_test = true
|
||||
prompt_label.position = Vector3(0, 1.8, 0)
|
||||
prompt_label.modulate = Color(1.0, 0.9, 0.0) # Yellow text
|
||||
prompt_label.visible = false
|
||||
add_child(prompt_label)
|
||||
|
||||
func _cache_meshes(node: Node):
|
||||
if node is MeshInstance3D:
|
||||
|
||||
Reference in New Issue
Block a user