feat: Introduce static Tekton stands with a new manager for strategic, non-adjacent placement and synchronized randomized shapes.

This commit is contained in:
Yogi Wiguna
2026-02-13 13:51:51 +08:00
parent 6472e47edf
commit 98f107893d
3 changed files with 53 additions and 12 deletions
+50 -4
View File
@@ -13,6 +13,8 @@ var camera_context_manager
# Minimal local state
var _connection_check_timer: float = 0.0
var reserved_static_positions: Array[Vector2i] = []
func _ready():
# Initialize scene managers
@@ -356,6 +358,9 @@ func _setup_host_game():
print("Spawning lobby player: ", peer_id)
_spawn_lobby_client_sync(peer_id)
# 1. PVT: Pre-calculate Static Tekton positions so we know where NOT to spawn players
_precalculate_static_positions()
# IMMEDIATELY assign random spawn positions before any player _ready() completes
# Player _ready() has 0.1s await, so we assign before that completes
# IMMEDIATELY assign spawn positions (Fixed or Random)
@@ -540,6 +545,18 @@ func _assign_random_spawn_positions():
var ground = enhanced_gridmap.get_cell_item(Vector3i(x, 0, z))
if ground == 0: # Walkable
var pos = Vector2i(x, z)
# SAFETY CHECK: Is this reserved for a Static Tekton Stand?
# Stand covers [center-1, center+1]
var is_safe = true
for reserved in reserved_static_positions:
if abs(x - reserved.x) <= 1 and abs(z - reserved.y) <= 1:
is_safe = false
break
if not is_safe:
continue
all_spawns.append(pos)
if x < mid_x and z < mid_z:
@@ -648,6 +665,14 @@ func spawn_tekton_npc():
var item_id = enhanced_gridmap.get_cell_item(Vector3i(x, 1, y))
if item_id == 4: continue # Wall/Stand
# Also check RESERVED positions (if they haven't spawned yet or for safety)
var is_safe = true
for reserved in reserved_static_positions:
if abs(x - reserved.x) <= 1 and abs(y - reserved.y) <= 1:
is_safe = false
break
if not is_safe: continue
valid_pos = Vector2i(x, y)
# Generate a consistent ID/Name for sync (add index to ensure uniqueness)
@@ -691,6 +716,23 @@ func _create_tekton(pos: Vector2i, tekton_id: int, is_static: bool = false):
else:
print("[Main] Spawned Tekton at %s (ID: %d)" % [pos, tekton_id])
func _precalculate_static_positions():
"""Calculate and reserve Static Tekton positions early."""
if not multiplayer.is_server(): return
var enhanced_gridmap = $EnhancedGridMap
if not enhanced_gridmap: return
if not static_tekton_manager:
static_tekton_manager = StaticTektonManager.new()
# Calculate 3 spots and STORE them
var points: Array[Vector2i] = []
points = static_tekton_manager.calculate_spawn_points(3, enhanced_gridmap)
reserved_static_positions = points
print("[Main] Pre-calculated Static Tekton Positions: %s" % str(reserved_static_positions))
func spawn_static_tektons():
"""Spawn fixed static tektons using StaticTektonManager."""
if not multiplayer.is_server(): return
@@ -700,11 +742,15 @@ func spawn_static_tektons():
print("[Main] Initializing StaticTektonManager...")
if not static_tekton_manager:
static_tekton_manager = StaticTektonManager.new()
# Keeping manager instance in memory
# Calculate Spawn Points (Server Logic)
var spawn_points = static_tekton_manager.calculate_spawn_points(3, enhanced_gridmap)
print("[Main] Static Tekton Points: %s" % str(spawn_points))
# Use pre-calculated points if available, otherwise calculate new ones
var spawn_points = []
if not reserved_static_positions.is_empty():
spawn_points = reserved_static_positions
else:
spawn_points = static_tekton_manager.calculate_spawn_points(3, enhanced_gridmap)
print("[Main] Spawning Static Tektons at: %s" % str(spawn_points))
for i in range(spawn_points.size()):
var pos = spawn_points[i]
+2 -2
View File
@@ -13,7 +13,7 @@ const STATIC_CONTROLLER_SCRIPT = "res://scripts/static_tekton_controller.gd"
# Mid-Left, Mid-Mid, Mid-Right
# Bot-Left, Bot-Mid, Bot-Right
func calculate_spawn_points(count: int, gridmap: Node) -> Array:
func calculate_spawn_points(count: int, gridmap: Node) -> Array[Vector2i]:
"""
Calculates random spawn positions for static tektons.
Returns an Array of Vector2i positions.
@@ -39,7 +39,7 @@ func calculate_spawn_points(count: int, gridmap: Node) -> Array:
# If count < 5, we prioritize corners then center
# If count > 5, we only return 5 because that's the max safe non-adjacent set in 3x3
var spawn_points = []
var spawn_points: Array[Vector2i] = []
var iterations = min(count, target_indices.size())
for i in range(iterations):
+1 -6
View File
@@ -31,7 +31,6 @@ func _update_mesh_from_index():
var shapes = [
_create_cylinder(),
_create_box(),
_create_prism(),
_create_sphere()
]
@@ -61,11 +60,7 @@ func _create_box() -> BoxMesh:
var mesh = BoxMesh.new()
mesh.size = Vector3(3.2, 0.6, 3.2)
return mesh
func _create_prism() -> PrismMesh:
var mesh = PrismMesh.new()
mesh.size = Vector3(3.2, 0.6, 3.2)
return mesh
func _create_sphere() -> SphereMesh:
# A flattened sphere acting like a dome stand