This commit is contained in:
2026-01-28 02:29:43 +08:00
parent d71f5d67e3
commit 6949e20a1f
13 changed files with 285 additions and 100 deletions
+92 -17
View File
@@ -39,6 +39,61 @@ func _ready():
await get_tree().process_frame
_auto_start_from_lobby()
# Ensure grid is randomized with Scarcity if server
if multiplayer.is_server():
randomize_game_grid()
_setup_tile_respawn_timer()
func _setup_tile_respawn_timer():
# Configure respawn rate based on Scarcity Mode from Lobby
var mode = LobbyManager.get_scarcity_mode()
var interval = 0.0
match mode:
"Aggressive": interval = 5.0
"Chaos": interval = 1.0 # Very fast!
"Normal": interval = 0.0 # No periodic respawn (only refill when empty)
_: interval = 0.0
if interval > 0:
var timer = Timer.new()
timer.name = "TileRespawnTimer"
timer.wait_time = interval
timer.autostart = true
timer.one_shot = false
timer.timeout.connect(_on_tile_respawn_timeout)
add_child(timer)
print("[Main] TileRespawnTimer started with interval: %.1f (Mode: %s)" % [interval, mode])
func _on_tile_respawn_timeout():
if not multiplayer.is_server(): return
var enhanced_gridmap = $EnhancedGridMap
if not enhanced_gridmap: return
# Try to find an empty spot (max 10 retries)
for i in range(10):
var x = randi() % enhanced_gridmap.columns
var z = randi() % enhanced_gridmap.rows
var cell = Vector3i(x, 1, z)
if enhanced_gridmap.get_cell_item(cell) == -1:
# Check floor 0
if enhanced_gridmap.get_cell_item(Vector3i(x, 0, z)) != -1:
# Check player occupancy
var occupied = false
for player in get_tree().get_nodes_in_group("Players"):
if Vector2i(player.current_position.x, player.current_position.y) == Vector2i(x, z):
occupied = true
break
if not occupied:
# Spawn!
var new_item = ScarcityController.get_random_tile_id()
sync_grid_item(x, 1, z, new_item)
rpc("sync_grid_item", x, 1, z, new_item)
return # Spawned one, done for this tick
func _init_managers():
# Create and attach scene managers
ui_manager = load("res://scripts/managers/ui_manager.gd").new()
@@ -148,10 +203,11 @@ func add_message_to_bar(player_name: String, message: String, type: int = Messag
# Powerup gets extra pulse effect
if type == MessageType.POWERUP:
await entrance_tween.finished
var pulse_tween = create_tween()
pulse_tween.set_loops(2)
pulse_tween.tween_property(label, "scale", Vector2(1.1, 1.1), 0.15).set_trans(Tween.TRANS_SINE)
pulse_tween.tween_property(label, "scale", Vector2(1.0, 1.0), 0.15).set_trans(Tween.TRANS_SINE)
if is_instance_valid(label):
var pulse_tween = create_tween()
pulse_tween.set_loops(2)
pulse_tween.tween_property(label, "scale", Vector2(1.1, 1.1), 0.15).set_trans(Tween.TRANS_SINE)
pulse_tween.tween_property(label, "scale", Vector2(1.0, 1.0), 0.15).set_trans(Tween.TRANS_SINE)
# Remove oldest messages if over limit
while message_container.get_child_count() > MAX_MESSAGES:
@@ -913,24 +969,28 @@ func randomize_item_at_position(grid_position: Vector2i):
var current_item = enhanced_gridmap.get_cell_item(cell)
# If current item exists, replace it (scarcity aware)
if current_item != -1:
var scarcity_mgr = load("res://scripts/managers/scarcity_manager.gd")
# If current item exists OR we are forcing a spawn on valid ground
var floor_0_item = enhanced_gridmap.get_cell_item(Vector3i(grid_position.x, 0, grid_position.y))
var is_ground = (floor_0_item != -1) # Simple check, or check specific ground items
# Prevent stacking on players
if is_ground:
for player in get_tree().get_nodes_in_group("Players"):
if Vector2i(player.current_position.x, player.current_position.y) == grid_position:
is_ground = false
break
if is_ground:
var new_item = 7
# Use ScarcityController
new_item = ScarcityController.get_random_tile_id()
if scarcity_mgr:
new_item = scarcity_mgr.get_random_tile_id()
# Try to ensure it changes, but respect scarcity
# If we are replacing an existing item, try to ensure it changes
if current_item != -1:
var max_retries = 3
while new_item == current_item and max_retries > 0:
new_item = scarcity_mgr.get_random_tile_id()
new_item = ScarcityController.get_random_tile_id()
max_retries -= 1
else:
# Fallback
var rng = RandomNumberGenerator.new()
rng.randomize()
new_item = rng.randi_range(7, 10)
while new_item == current_item:
new_item = rng.randi_range(7, 10)
sync_grid_item(cell.x, cell.y, cell.z, new_item)
rpc("sync_grid_item", cell.x, cell.y, cell.z, new_item)
@@ -946,6 +1006,21 @@ func sync_grid_item(x: int, y: int, z: int, item: int):
if enhanced_gridmap:
enhanced_gridmap.set_cell_item(Vector3i(x, y, z), item)
# Sync grid update (no need to sync whole grid if we do it at start, but if we do it late we might need to sync)
# For simplicity, we trust the grid syncs via normal mechanisms or initial state.
func randomize_game_grid():
var enhanced_gridmap = $EnhancedGridMap
if enhanced_gridmap:
# Randomize Floor 1 using ScarcityController
enhanced_gridmap.randomize_floor(1, ScarcityController.get_random_tile_id)
# Sync to clients if needed (usually handled by initial state sync or explicit item syncs)
# Since Main.gd doesn't have a "Sync Floor" RPC, we rely on clients running the same seed or syncing individual cells.
# For now, let's assume server authority + sync on connect handles it, or add sync loop if critical.
pass
# =============================================================================
# Goals Cycle & Leaderboard UI
# =============================================================================