added nice smoke puffs to interactible objects

This commit is contained in:
2026-01-11 12:27:02 +01:00
parent 3adf6660bb
commit 37b0d61566
13 changed files with 566 additions and 30 deletions

View File

@@ -24,6 +24,9 @@ var level_coins_collected: int = 0
# Client ready tracking (server only)
var clients_ready: Dictionary = {} # peer_id -> bool
# Level complete tracking
var level_complete_triggered: bool = false # Prevent multiple level complete triggers
func _ready():
# Add to group for easy access
add_to_group("game_world")
@@ -376,6 +379,31 @@ func _request_loot_pickup(loot_id: int, loot_position: Vector2, player_peer_id:
else:
print("GameWorld: Could not find loot for pickup request: id=", loot_id, " pos=", loot_position)
@rpc("authority", "reliable")
func _sync_player_exit_stairs(player_peer_id: int):
# Client receives notification that a player reached exit stairs
if multiplayer.is_server():
return # Server ignores this (it's the sender)
# Find the player by peer ID
var players = get_tree().get_nodes_in_group("player")
var target_player = null
for p in players:
if p.has_method("get_multiplayer_authority") and p.get_multiplayer_authority() == player_peer_id:
target_player = p
break
# Only disable controls/collision if this is our local player
if target_player:
var my_peer_id = multiplayer.get_unique_id()
if player_peer_id == my_peer_id:
# This is our local player - disable controls and collision
target_player.controls_disabled = true
target_player.set_collision_layer_value(1, false)
print("GameWorld: Client disabled controls and collision for local player ", target_player.name)
# Show black fade overlay for this player
_show_black_fade_overlay()
@rpc("authority", "reliable")
func _sync_show_level_complete(level_time: float):
# Clients receive level complete UI sync from server
@@ -400,6 +428,30 @@ func _sync_hide_level_complete():
if level_complete_ui:
level_complete_ui.visible = false
@rpc("authority", "reliable")
func _sync_restore_player_controls():
# Clients receive restore controls/collision sync from server
if multiplayer.is_server():
return # Server ignores this (it's the sender)
# Restore controls and collision for local player
var my_peer_id = multiplayer.get_unique_id()
var players = get_tree().get_nodes_in_group("player")
for player in players:
if player.has_method("get_multiplayer_authority") and player.get_multiplayer_authority() == my_peer_id:
player.controls_disabled = false
player.set_collision_layer_value(1, true)
print("GameWorld: Client restored controls and collision for local player ", player.name)
break
@rpc("authority", "reliable")
func _sync_remove_black_fade():
# Clients receive remove black fade sync from server
if multiplayer.is_server():
return # Server ignores this (it's the sender)
_remove_black_fade_overlay()
@rpc("authority", "reliable")
func _sync_show_level_number(level: int):
# Clients receive level number UI sync from server
@@ -478,6 +530,9 @@ func _generate_dungeon():
print("GameWorld: Not server, skipping dungeon generation")
return
# Reset level complete flag for new level
level_complete_triggered = false
print("GameWorld: Generating dungeon level ", current_level)
# Generate seed (deterministic for level 1, can be random for future levels)
@@ -1555,8 +1610,32 @@ func _on_player_reached_stairs(player: Node):
if not multiplayer.is_server() and multiplayer.has_multiplayer_peer():
return # Only server handles this
# Prevent multiple triggers - if already triggered, ignore
if level_complete_triggered:
print("GameWorld: Level complete already triggered, ignoring duplicate trigger")
return
print("GameWorld: Player ", player.name, " reached stairs!")
# Mark as triggered to prevent re-triggering
level_complete_triggered = true
# Disable controls and collision for the player who reached stairs
var player_peer_id = player.get_multiplayer_authority() if player.has_method("get_multiplayer_authority") else 0
player.controls_disabled = true
# Remove collision layer (layer 1 = players)
player.set_collision_layer_value(1, false)
print("GameWorld: Disabled controls and collision for player ", player.name)
# Show black fade overlay for server's local player if this is the server's player
var my_peer_id = multiplayer.get_unique_id() if multiplayer.has_multiplayer_peer() else 1
if player_peer_id == my_peer_id:
_show_black_fade_overlay()
# Sync controls disabled and collision removal to clients
if multiplayer.has_multiplayer_peer() and player_peer_id > 0:
_sync_player_exit_stairs.rpc(player_peer_id)
# Drop any held objects for all players before level completion
var entities_node = get_node_or_null("Entities")
if entities_node:
@@ -1629,6 +1708,18 @@ func _on_player_reached_stairs(player: Node):
if hud and hud.has_method("start_timer"):
hud.start_timer()
# Restore controls and collision for all players (server side)
_restore_player_controls_and_collision()
# Sync restore to all clients
if multiplayer.has_multiplayer_peer():
_sync_restore_player_controls.rpc()
# Remove black fade overlay (server and clients)
_remove_black_fade_overlay()
if multiplayer.has_multiplayer_peer():
_sync_remove_black_fade.rpc()
# Move all players to start room (server side)
_move_all_players_to_start_room()
@@ -1665,9 +1756,10 @@ func _get_local_player_stats() -> Dictionary:
var local_player = null
if multiplayer.has_multiplayer_peer():
# Multiplayer: find player with matching authority
# Multiplayer: find player with matching authority (client's own player)
var my_peer_id = multiplayer.get_unique_id()
for player in players:
if player.has_method("is_multiplayer_authority") and player.is_multiplayer_authority():
if player.has_method("get_multiplayer_authority") and player.get_multiplayer_authority() == my_peer_id:
local_player = player
break
else:
@@ -1759,6 +1851,54 @@ func _fade_in_player(player: Node):
sprite_layer.modulate.a = 0.0 # Start invisible
fade_tween.tween_property(sprite_layer, "modulate:a", 1.0, 1.0)
func _show_black_fade_overlay():
# Create black fade overlay for player who reached exit
# Remove existing fade if any
var existing_fade = get_node_or_null("BlackFadeOverlay")
if existing_fade:
existing_fade.queue_free()
# Create CanvasLayer with z_index 999 (below level complete UI which is 1000)
var fade_layer = CanvasLayer.new()
fade_layer.name = "BlackFadeOverlay"
fade_layer.layer = 999 # Below level complete UI (1000) but above gameplay
add_child(fade_layer)
# Create ColorRect that fills the screen
var fade_rect = ColorRect.new()
fade_rect.name = "FadeRect"
fade_rect.color = Color(0, 0, 0, 1) # Black, fully opaque
fade_rect.set_anchors_preset(Control.PRESET_FULL_RECT) # Fill entire screen
fade_layer.add_child(fade_rect)
# Fade in from transparent to black
fade_rect.modulate.a = 0.0 # Start transparent
var fade_tween = create_tween()
fade_tween.tween_property(fade_rect, "modulate:a", 1.0, 0.5) # Fade in over 0.5 seconds
print("GameWorld: Created black fade overlay for player who reached exit")
func _remove_black_fade_overlay():
# Remove black fade overlay when new level starts
var existing_fade = get_node_or_null("BlackFadeOverlay")
if existing_fade:
# Fade out quickly before removing
var fade_rect = existing_fade.get_node_or_null("FadeRect")
if fade_rect:
var fade_tween = create_tween()
fade_tween.tween_property(fade_rect, "modulate:a", 0.0, 0.2) # Fade out over 0.2 seconds
await fade_tween.finished
existing_fade.queue_free()
print("GameWorld: Removed black fade overlay")
func _restore_player_controls_and_collision():
# Restore controls and collision for all players when new level starts
var players = get_tree().get_nodes_in_group("player")
for player in players:
player.controls_disabled = false
# Restore collision layer (layer 1 = players)
player.set_collision_layer_value(1, true)
print("GameWorld: Restored controls and collision for player ", player.name)
func _show_level_complete_ui(level_time: float = 0.0):
# Create or show level complete UI
var level_complete_ui = get_node_or_null("LevelCompleteUI")
@@ -1894,6 +2034,7 @@ func _create_level_complete_ui_programmatically() -> Node:
# Create level complete UI programmatically
var canvas_layer = CanvasLayer.new()
canvas_layer.name = "LevelCompleteUI"
canvas_layer.layer = 1000 # Very high z_index so it appears above black fade
add_child(canvas_layer)
# Load standard font (as FontFile)