added blocking doors to paths.
This commit is contained in:
@@ -291,7 +291,15 @@ func can_be_destroyed() -> bool:
|
||||
func on_grabbed(by_player):
|
||||
# Special handling for chests - open instead of grab
|
||||
if object_type == "Chest" and not is_chest_opened:
|
||||
_open_chest()
|
||||
# In multiplayer, send RPC to server if client is opening
|
||||
if multiplayer.has_multiplayer_peer() and not is_multiplayer_authority():
|
||||
# Client - send request to server
|
||||
if by_player and by_player.is_multiplayer_authority():
|
||||
var player_peer_id = by_player.get_multiplayer_authority()
|
||||
_request_chest_open.rpc_id(1, player_peer_id)
|
||||
else:
|
||||
# Server or single player - open directly
|
||||
_open_chest(by_player)
|
||||
return
|
||||
|
||||
is_being_held = true
|
||||
@@ -463,46 +471,120 @@ func setup_pushable_high_box():
|
||||
if sprite_above:
|
||||
sprite_above.frame = top_frames[index]
|
||||
|
||||
func _open_chest():
|
||||
func _open_chest(by_player: Node = null):
|
||||
if is_chest_opened:
|
||||
return
|
||||
|
||||
# Only process on server (authority)
|
||||
if multiplayer.has_multiplayer_peer() and not is_multiplayer_authority():
|
||||
return
|
||||
|
||||
is_chest_opened = true
|
||||
if sprite and chest_opened_frame >= 0:
|
||||
sprite.frame = chest_opened_frame
|
||||
|
||||
# Spawn loot item
|
||||
var loot_scene = preload("res://scenes/loot.tscn")
|
||||
if loot_scene:
|
||||
var loot = loot_scene.instantiate()
|
||||
if loot:
|
||||
# Random loot type
|
||||
var loot_types = loot.LootType.values()
|
||||
loot.loot_type = loot_types[randi() % loot_types.size()]
|
||||
|
||||
# Position above chest with some randomness
|
||||
var spawn_pos = global_position + Vector2(randf_range(-10, 10), randf_range(-20, -10))
|
||||
loot.global_position = spawn_pos
|
||||
|
||||
# Set initial velocity to fly out
|
||||
var random_angle = randf() * PI * 2
|
||||
var random_force = randf_range(80.0, 120.0)
|
||||
loot.velocity = Vector2(cos(random_angle), sin(random_angle)) * random_force
|
||||
loot.velocity_z = randf_range(100.0, 150.0)
|
||||
loot.is_airborne = true
|
||||
loot.velocity_set_by_spawner = true
|
||||
|
||||
get_parent().call_deferred("add_child", loot)
|
||||
|
||||
# Sync to network if multiplayer
|
||||
if multiplayer.has_multiplayer_peer():
|
||||
_sync_chest_open.rpc()
|
||||
|
||||
print(name, " opened! Loot spawned: ", loot_types[loot.loot_type])
|
||||
# Random loot type
|
||||
var loot_types = [
|
||||
{"type": "coin", "name": "Coin", "color": Color(1.0, 0.84, 0.0)},
|
||||
{"type": "apple", "name": "Apple", "color": Color.GREEN},
|
||||
{"type": "banana", "name": "Banana", "color": Color.YELLOW},
|
||||
{"type": "cherry", "name": "Cherry", "color": Color.RED},
|
||||
{"type": "key", "name": "Key", "color": Color.YELLOW}
|
||||
]
|
||||
var selected_loot = loot_types[randi() % loot_types.size()]
|
||||
|
||||
# CRITICAL: Instantly give item to player instead of spawning loot object
|
||||
if by_player and is_instance_valid(by_player) and by_player.is_in_group("player"):
|
||||
# Give item directly to player based on type
|
||||
match selected_loot.type:
|
||||
"coin":
|
||||
if by_player.has_method("add_coins"):
|
||||
by_player.add_coins(1)
|
||||
# Show pickup notification with coin graphic
|
||||
var coin_texture = load("res://assets/gfx/pickups/gold_coin.png")
|
||||
_show_item_pickup_notification(by_player, "+1 coin", selected_loot.color, coin_texture, 6, 1, 0)
|
||||
"apple":
|
||||
var heal_amount = 20.0
|
||||
if by_player.has_method("heal"):
|
||||
by_player.heal(heal_amount)
|
||||
# Show pickup notification with apple graphic
|
||||
var items_texture = load("res://assets/gfx/pickups/items_n_shit.png")
|
||||
_show_item_pickup_notification(by_player, "+" + str(int(heal_amount)) + " hp", selected_loot.color, items_texture, 20, 14, (8 * 20) + 11)
|
||||
"banana":
|
||||
var heal_amount = 20.0
|
||||
if by_player.has_method("heal"):
|
||||
by_player.heal(heal_amount)
|
||||
# Show pickup notification with banana graphic
|
||||
var items_texture = load("res://assets/gfx/pickups/items_n_shit.png")
|
||||
_show_item_pickup_notification(by_player, "+" + str(int(heal_amount)) + " hp", selected_loot.color, items_texture, 20, 14, (8 * 20) + 12)
|
||||
"cherry":
|
||||
var heal_amount = 20.0
|
||||
if by_player.has_method("heal"):
|
||||
by_player.heal(heal_amount)
|
||||
# Show pickup notification with cherry graphic
|
||||
var items_texture = load("res://assets/gfx/pickups/items_n_shit.png")
|
||||
_show_item_pickup_notification(by_player, "+" + str(int(heal_amount)) + " hp", selected_loot.color, items_texture, 20, 14, (8 * 20) + 13)
|
||||
"key":
|
||||
if by_player.has_method("add_key"):
|
||||
by_player.add_key(1)
|
||||
# Show pickup notification with key graphic
|
||||
var items_texture = load("res://assets/gfx/pickups/items_n_shit.png")
|
||||
_show_item_pickup_notification(by_player, "+1 key", selected_loot.color, items_texture, 20, 14, (13 * 20) + 10)
|
||||
|
||||
# Play chest open sound
|
||||
if has_node("SfxChestOpen"):
|
||||
$SfxChestOpen.play()
|
||||
|
||||
print(name, " opened by ", by_player.name, "! Item given: ", selected_loot.name)
|
||||
else:
|
||||
push_error("Chest: ERROR - No valid player to give item to!")
|
||||
|
||||
# Sync chest opening visual to all clients (item already given on server)
|
||||
if multiplayer.has_multiplayer_peer():
|
||||
_sync_chest_open.rpc(selected_loot.type if by_player else "coin")
|
||||
|
||||
@rpc("any_peer", "reliable")
|
||||
func _sync_chest_open():
|
||||
# Sync chest opening to all clients
|
||||
func _request_chest_open(player_peer_id: int):
|
||||
# Server receives chest open request from client
|
||||
if not multiplayer.is_server():
|
||||
return
|
||||
|
||||
if is_chest_opened:
|
||||
return
|
||||
|
||||
# Find the player by peer ID
|
||||
var player = null
|
||||
var players = get_tree().get_nodes_in_group("player")
|
||||
for p in players:
|
||||
if p.get_multiplayer_authority() == player_peer_id:
|
||||
player = p
|
||||
break
|
||||
|
||||
if not player:
|
||||
push_error("Chest: ERROR - Could not find player with peer_id ", player_peer_id, " for chest opening!")
|
||||
return
|
||||
|
||||
# Open chest on server (this will give item to player)
|
||||
_open_chest(player)
|
||||
|
||||
@rpc("any_peer", "reliable")
|
||||
func _sync_chest_open(_loot_type_str: String = "coin"):
|
||||
# Sync chest opening to all clients (only visual - item already given on server)
|
||||
if not is_chest_opened and sprite and chest_opened_frame >= 0:
|
||||
is_chest_opened = true
|
||||
sprite.frame = chest_opened_frame
|
||||
|
||||
# Play chest open sound on clients
|
||||
if has_node("SfxChestOpen"):
|
||||
$SfxChestOpen.play()
|
||||
|
||||
func _show_item_pickup_notification(player: Node, text: String, text_color: Color, item_texture: Texture2D = null, sprite_hframes: int = 1, sprite_vframes: int = 1, sprite_frame: int = 0):
|
||||
# Show item graphic and text above player's head for 0.5s, then fade out over 0.5s
|
||||
var floating_text_scene = preload("res://scenes/floating_text.tscn")
|
||||
if floating_text_scene and player and is_instance_valid(player):
|
||||
var floating_text = floating_text_scene.instantiate()
|
||||
var parent = player.get_parent()
|
||||
if parent:
|
||||
parent.add_child(floating_text)
|
||||
floating_text.global_position = player.global_position + Vector2(0, -20)
|
||||
floating_text.setup(text, text_color, 0.5, 0.5, item_texture, sprite_hframes, sprite_vframes, sprite_frame) # Show for 0.5s, fade over 0.5s
|
||||
|
||||
Reference in New Issue
Block a user