feat: Initialize the main game scene with core managers, UI, networking, and a new message bar system.
This commit is contained in:
+43
-2
@@ -611,7 +611,10 @@ func spawn_tekton_npc():
|
|||||||
var enhanced_gridmap = $EnhancedGridMap
|
var enhanced_gridmap = $EnhancedGridMap
|
||||||
if not enhanced_gridmap: return
|
if not enhanced_gridmap: return
|
||||||
|
|
||||||
# Spawn 3 Tektons
|
# Spawn Static Tektons (Bottom Right, Mid Right)
|
||||||
|
spawn_static_tektons()
|
||||||
|
|
||||||
|
# Spawn 3 Roaming Tektons
|
||||||
var spawned_count = 0
|
var spawned_count = 0
|
||||||
var attempts = 0
|
var attempts = 0
|
||||||
|
|
||||||
@@ -640,7 +643,7 @@ func spawn_tekton_npc():
|
|||||||
func sync_spawn_tekton(pos: Vector2i, tekton_id: int):
|
func sync_spawn_tekton(pos: Vector2i, tekton_id: int):
|
||||||
_create_tekton(pos, tekton_id)
|
_create_tekton(pos, tekton_id)
|
||||||
|
|
||||||
func _create_tekton(pos: Vector2i, tekton_id: int):
|
func _create_tekton(pos: Vector2i, tekton_id: int, is_static: bool = false):
|
||||||
var node_name = "Tekton_%d" % tekton_id
|
var node_name = "Tekton_%d" % tekton_id
|
||||||
if has_node(node_name): return
|
if has_node(node_name): return
|
||||||
|
|
||||||
@@ -654,8 +657,46 @@ func _create_tekton(pos: Vector2i, tekton_id: int):
|
|||||||
if has_node("EnhancedGridMap"):
|
if has_node("EnhancedGridMap"):
|
||||||
tekton.initialize(pos, $EnhancedGridMap)
|
tekton.initialize(pos, $EnhancedGridMap)
|
||||||
|
|
||||||
|
# If Static, swap controller
|
||||||
|
if is_static:
|
||||||
|
var old_controller = tekton.get_node_or_null("TektonController")
|
||||||
|
if old_controller:
|
||||||
|
old_controller.queue_free()
|
||||||
|
|
||||||
|
var static_controller = load("res://scripts/static_tekton_controller.gd").new()
|
||||||
|
static_controller.name = "StaticTektonController"
|
||||||
|
tekton.add_child(static_controller)
|
||||||
|
print("[Main] Spawned STATIC Tekton at %s (ID: %d)" % [pos, tekton_id])
|
||||||
|
else:
|
||||||
print("[Main] Spawned Tekton at %s (ID: %d)" % [pos, tekton_id])
|
print("[Main] Spawned Tekton at %s (ID: %d)" % [pos, tekton_id])
|
||||||
|
|
||||||
|
func spawn_static_tektons():
|
||||||
|
"""Spawn fixed static tektons (Bottom Right, Mid Right)."""
|
||||||
|
if not multiplayer.is_server(): return
|
||||||
|
var enhanced_gridmap = $EnhancedGridMap
|
||||||
|
if not enhanced_gridmap: return
|
||||||
|
|
||||||
|
# Bottom Right (Max X, Max Y)
|
||||||
|
if "columns" in enhanced_gridmap and "rows" in enhanced_gridmap:
|
||||||
|
var cols = enhanced_gridmap.columns
|
||||||
|
var rows = enhanced_gridmap.rows
|
||||||
|
|
||||||
|
# Bottom Right (Corner - 1)
|
||||||
|
var pos_br = Vector2i(cols - 2, rows - 2)
|
||||||
|
var id_br = 99001
|
||||||
|
_create_tekton(pos_br, id_br, true)
|
||||||
|
rpc("sync_spawn_static_tekton", pos_br, id_br)
|
||||||
|
|
||||||
|
# Mid Right
|
||||||
|
var pos_mr = Vector2i(cols - 2, rows / 2)
|
||||||
|
var id_mr = 99002
|
||||||
|
_create_tekton(pos_mr, id_mr, true)
|
||||||
|
rpc("sync_spawn_static_tekton", pos_mr, id_mr)
|
||||||
|
|
||||||
|
@rpc("call_remote", "reliable")
|
||||||
|
func sync_spawn_static_tekton(pos: Vector2i, tekton_id: int):
|
||||||
|
_create_tekton(pos, tekton_id, true)
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Player Management
|
# Player Management
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
@export var throw_interval_min: float = 4.0
|
||||||
|
@export var throw_interval_max: float = 7.0
|
||||||
|
@export var throw_range: int = 6
|
||||||
|
|
||||||
|
var tekton: Node3D
|
||||||
|
var enhanced_gridmap: Node
|
||||||
|
var timer: Timer
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
tekton = get_parent()
|
||||||
|
if not tekton:
|
||||||
|
set_physics_process(false)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Wait for gridmap
|
||||||
|
await get_tree().process_frame
|
||||||
|
var main = tekton.get_tree().get_root().get_node_or_null("Main")
|
||||||
|
if main:
|
||||||
|
enhanced_gridmap = main.get_node_or_null("EnhancedGridMap")
|
||||||
|
|
||||||
|
# Initial State
|
||||||
|
if tekton.has_method("play_animation"):
|
||||||
|
tekton.play_animation("tekton_idle")
|
||||||
|
|
||||||
|
# Setup Timer
|
||||||
|
timer = Timer.new()
|
||||||
|
timer.one_shot = true
|
||||||
|
timer.timeout.connect(_on_timer_timeout)
|
||||||
|
add_child(timer)
|
||||||
|
_start_timer()
|
||||||
|
|
||||||
|
func _start_timer():
|
||||||
|
timer.wait_time = randf_range(throw_interval_min, throw_interval_max)
|
||||||
|
timer.start()
|
||||||
|
|
||||||
|
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"):
|
||||||
|
_start_timer()
|
||||||
|
return
|
||||||
|
|
||||||
|
print("[StaticTekton] Timer timeout. Attempting throw...")
|
||||||
|
_attempt_throw()
|
||||||
|
|
||||||
|
func _attempt_throw():
|
||||||
|
# Find target
|
||||||
|
var target = _find_empty_tile()
|
||||||
|
if target == Vector2i(-1, -1):
|
||||||
|
print("[StaticTekton] No valid target found.")
|
||||||
|
_start_timer()
|
||||||
|
return
|
||||||
|
|
||||||
|
print("[StaticTekton] Target found: %s" % target)
|
||||||
|
# Execute Throw
|
||||||
|
# 1. Face target
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
tekton.look_at(Vector3(target_world_pos.x, tekton.global_position.y, target_world_pos.z), Vector3.UP)
|
||||||
|
|
||||||
|
# 2. Play Animation
|
||||||
|
if tekton.has_method("play_animation_rpc"):
|
||||||
|
tekton.rpc("play_animation_rpc", "tekton_throw_tile")
|
||||||
|
|
||||||
|
# 3. Sync projectile/effect (Delay for animation sync?)
|
||||||
|
# Assuming animation takes ~1.0s, throw happens at ~0.5s?
|
||||||
|
await get_tree().create_timer(0.5).timeout
|
||||||
|
|
||||||
|
var main = tekton.get_tree().get_root().get_node_or_null("Main")
|
||||||
|
if main:
|
||||||
|
# Spawn Item (Random ID 7-10)
|
||||||
|
var item_id = randi_range(7, 10)
|
||||||
|
main.rpc("sync_grid_item", target.x, 1, target.y, item_id)
|
||||||
|
|
||||||
|
# Optional: Spawn Projectile Visual?
|
||||||
|
# For now, instant spawn is safest, or we can add a projectile RPC later.
|
||||||
|
|
||||||
|
# 4. Resume Idle
|
||||||
|
await get_tree().create_timer(1.0).timeout
|
||||||
|
if tekton.has_method("play_animation_rpc"):
|
||||||
|
tekton.rpc("play_animation_rpc", "tekton_idle")
|
||||||
|
|
||||||
|
_start_timer()
|
||||||
|
|
||||||
|
func _find_empty_tile() -> Vector2i:
|
||||||
|
if not enhanced_gridmap or not "rows" in enhanced_gridmap: return Vector2i(-1, -1)
|
||||||
|
|
||||||
|
var center = Vector2i(tekton.global_position.x, tekton.global_position.z) # Approx grid pos
|
||||||
|
# Better: use tekton.current_position if available
|
||||||
|
if "current_position" in tekton:
|
||||||
|
center = tekton.current_position
|
||||||
|
|
||||||
|
var candidates = []
|
||||||
|
for x in range(center.x - throw_range, center.x + throw_range + 1):
|
||||||
|
for y in range(center.y - throw_range, center.y + throw_range + 1):
|
||||||
|
if x < 0 or y < 0 or x >= enhanced_gridmap.columns or y >= enhanced_gridmap.rows: continue
|
||||||
|
|
||||||
|
# Check range logic (Euclidean or Manhattan?)
|
||||||
|
if Vector2(x, y).distance_to(Vector2(center.x, center.y)) > throw_range: continue
|
||||||
|
|
||||||
|
# Check if empty (Layer 1 has no item)
|
||||||
|
if enhanced_gridmap.get_cell_item(Vector3i(x, 1, y)) == -1:
|
||||||
|
# Also check floor exist? (Layer 0)
|
||||||
|
if enhanced_gridmap.get_cell_item(Vector3i(x, 0, y)) != -1:
|
||||||
|
candidates.append(Vector2i(x, y))
|
||||||
|
|
||||||
|
if candidates.is_empty(): return Vector2i(-1, -1)
|
||||||
|
return candidates.pick_random()
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://dj1rb4wa8wxeu
|
||||||
@@ -295,6 +295,15 @@ func spawn_tiles_around(count: int = 4):
|
|||||||
"""Spawns a mix of normal and special tiles in a radius."""
|
"""Spawns a mix of normal and special tiles in a radius."""
|
||||||
if not enhanced_gridmap: return
|
if not enhanced_gridmap: return
|
||||||
|
|
||||||
|
# Play throw animation
|
||||||
|
if not is_carried and not is_thrown:
|
||||||
|
play_animation("tekton_throw_tile")
|
||||||
|
# Queue idle after animation finishes (approx 1.0s)
|
||||||
|
get_tree().create_timer(1.0).timeout.connect(func():
|
||||||
|
if not is_moving and not is_carried and not is_thrown:
|
||||||
|
play_animation("tekton_idle")
|
||||||
|
)
|
||||||
|
|
||||||
var radius = 2
|
var radius = 2
|
||||||
var rng = RandomNumberGenerator.new()
|
var rng = RandomNumberGenerator.new()
|
||||||
rng.randomize()
|
rng.randomize()
|
||||||
@@ -338,6 +347,10 @@ func spawn_tiles_around(count: int = 4):
|
|||||||
main.rpc("sync_grid_item", pos.x, 1, pos.y, item_id)
|
main.rpc("sync_grid_item", pos.x, 1, pos.y, item_id)
|
||||||
spawned += 1
|
spawned += 1
|
||||||
|
|
||||||
|
@rpc("call_local", "reliable")
|
||||||
|
func play_animation_rpc(anim_name: String):
|
||||||
|
play_animation(anim_name)
|
||||||
|
|
||||||
func play_animation(anim_name: String):
|
func play_animation(anim_name: String):
|
||||||
# Try specific user path first
|
# Try specific user path first
|
||||||
var anim_player = get_node_or_null("Visuals/tekton/Armature/AnimationPlayer")
|
var anim_player = get_node_or_null("Visuals/tekton/Armature/AnimationPlayer")
|
||||||
|
|||||||
Reference in New Issue
Block a user