diff --git a/src/scripts/Autoloads/console.gd b/src/scripts/Autoloads/console.gd index 2585ffc..ffb1c93 100644 --- a/src/scripts/Autoloads/console.gd +++ b/src/scripts/Autoloads/console.gd @@ -10,7 +10,7 @@ func _ready() -> void: pass # Replace with function body. # Called every frame. 'delta' is the elapsed time since the previous frame. -func _process(delta: float) -> void: +func _process(_delta: float) -> void: if (Input.is_action_just_pressed("Console")): var tween = create_tween() var target_y = 0 diff --git a/src/scripts/Autoloads/multiplayer_manager.gd b/src/scripts/Autoloads/multiplayer_manager.gd index 517d758..ed8cf4f 100644 --- a/src/scripts/Autoloads/multiplayer_manager.gd +++ b/src/scripts/Autoloads/multiplayer_manager.gd @@ -78,7 +78,6 @@ func _physics_process(_delta: float) -> void: pass func host(): - print("hosting") #var server_peer = ENetMultiplayerPeer.new() var server_peer = WebSocketMultiplayerPeer.new() @@ -95,7 +94,6 @@ func host(): pass func join(): - print("joining") #var client_peer = ENetMultiplayerPeer.new() #client_peer.create_client(SERVER_HOST, 443) var client_peer = WebSocketMultiplayerPeer.new() @@ -117,16 +115,13 @@ func join(): while client_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTING: attempts += 1 - print("Connection attempt ", attempts, " - Status: ", client_peer.get_connection_status()) if attempts >= max_attempts: - print("Connection timed out after", max_attempts, "attempts") #_cleanup_connections() connectionFailed.emit() return await get_tree().create_timer(1.0).timeout if client_peer.get_connection_status() == MultiplayerPeer.CONNECTION_CONNECTED: - print("Connected to game server!") connectionSucceeded.emit() @@ -134,19 +129,16 @@ func join(): pass func _add_player_to_game(id: int): - print("Player %d joined the game!", id) emit_signal("addPlayerSignal", id) pass func _del_player(id: int): - print("Player %d left the game!", id) emit_signal("delPlayerSignal", id) pass @rpc("any_peer", "reliable") func notify_client_ready(peer_id: int): if multiplayer.is_server(): - print("Client ", peer_id, " is ready for sync") peers_ready_for_sync[peer_id] = true client_ready_for_players.emit(peer_id) @@ -158,12 +150,10 @@ func notify_client_ready(peer_id: int): sync_character_data.rpc_id(peer_id, other_peer_id, peers_character_data[other_peer_id]) else: # Client sends its character data to server - print("Sending character data to server") sync_character_data.rpc_id(1, multiplayer.get_unique_id(), character_data.save()) @rpc("any_peer", "reliable") func sync_character_data(peer_id: int, char_data: Dictionary): - print("Received character data for peer: ", peer_id) if multiplayer.is_server(): # Store the character data peers_character_data[peer_id] = char_data @@ -178,13 +168,11 @@ func sync_character_data(peer_id: int, char_data: Dictionary): if player: player.stats.load(char_data) player.initStats(player.stats) - print("Updated character stats for player: ", peer_id, " with name: ", player.stats.character_name) updateScore(true) func _on_peer_connected(_peer_id: int): #add_chat_message("Player " + str(peer_id) + " connected", "connection") - print("WE SUCCESSFUNYL CONNECT!") add_chat_message("Player " + str(_peer_id) + " connected", "connection") $CanvasLayer/BottomLeftCorner/VBoxContainer/LabelPlayerConnect.text = "Player " + str(_peer_id) + " connected" $CanvasLayer/BottomLeftCorner/VBoxContainer/LabelPlayerConnect.modulate.a = 1.0 @@ -244,17 +232,10 @@ func broadcast_chat_message(message: String): @rpc("any_peer", "reliable") func request_lift_pot(pot_path: NodePath, peer_id: int): - Console.print("=== RPC RECEIVED ===") - Console.print("MultiplayerManager received request_lift_pot from peer ", peer_id, " for pot at ", pot_path) - Console.print("Current peer ID: ", multiplayer.get_unique_id()) - Console.print("Is server: ", multiplayer.is_server()) - Console.print("===================") if multiplayer.is_server(): var pot = get_node_or_null(pot_path) var player = get_tree().get_current_scene().get_node("SpawnRoot").get_node_or_null(str(peer_id)) - Console.print("MultiplayerManager found pot: ", pot, " player: ", player) if pot and "lift" in pot and pot.liftable and player: - Console.print("MultiplayerManager authorizing lift for peer ", peer_id) # Clear grabbed entity if it's not the pot we're lifting if player.grabbed_entity != null and player.grabbed_entity != pot and "release" in player.grabbed_entity: player.grabbed_entity.release() @@ -288,39 +269,29 @@ func request_lift_pot(pot_path: NodePath, peer_id: int): #p.sync_animation.rpc("LIFT") #p.sync_held_entity.rpc(str(pot.get_path())) #p.sync_grabbed_entity.rpc("") - else: - Console.print("MultiplayerManager denied lift request - pot: ", pot, " liftable: ", pot.liftable if pot else "null", " player: ", player) @rpc("any_peer", "reliable") func request_put_down_pot(pot_path: NodePath, peer_id: int): - Console.print("MultiplayerManager received request_put_down_pot from peer ", peer_id, " for pot at ", pot_path) if multiplayer.is_server(): var pot = get_node_or_null(pot_path) var player = get_tree().get_current_scene().get_node("SpawnRoot").get_node_or_null(str(peer_id)) - Console.print("MultiplayerManager found pot: ", pot, " player: ", player) if pot and player: # Check if the pot is being held by this player if pot.holder_peer_id == peer_id or (pot.holder != null and pot.holder.get_multiplayer_authority() == peer_id): - Console.print("MultiplayerManager authorizing put_down for peer ", peer_id) if pot.put_down(): player.held_entity = null # Use RPC to clear held_entity_path on all players player.set_held_entity_path_rpc.rpc("") player.is_lifting = false - else: - Console.print("MultiplayerManager denied put_down - holder_peer_id mismatch or holder not found") @rpc("any_peer", "reliable") func request_throw_pot(pot_path: NodePath, peer_id: int, direction: Vector2): - Console.print("MultiplayerManager received request_throw_pot from peer ", peer_id, " for pot at ", pot_path) if multiplayer.is_server(): var pot = get_node_or_null(pot_path) var player = get_tree().get_current_scene().get_node("SpawnRoot").get_node_or_null(str(peer_id)) - Console.print("MultiplayerManager found pot: ", pot, " player: ", player) if pot and player: # Check if the pot is being held by this player if pot.holder_peer_id == peer_id or (pot.holder != null and pot.holder.get_multiplayer_authority() == peer_id): - Console.print("MultiplayerManager authorizing throw for peer ", peer_id) pot.throw(direction) # Use RPC to clear held_entity_path on all players (including server) player.set_held_entity_path_rpc.rpc("") @@ -332,8 +303,6 @@ func request_throw_pot(pot_path: NodePath, peer_id: int, direction: Vector2): for p in all_players: if p.has_method("sync_animation") and p.get_multiplayer_authority() != 1: p.sync_animation.rpc("THROW") - else: - Console.print("MultiplayerManager denied throw - holder_peer_id mismatch or holder not found") func sortScoreArr(a, b): if a.kills > b.kills: diff --git a/src/scripts/dungeon_generator.gd b/src/scripts/dungeon_generator.gd index faeb56c..8ebf198 100644 --- a/src/scripts/dungeon_generator.gd +++ b/src/scripts/dungeon_generator.gd @@ -102,7 +102,6 @@ func generate_dungeon(map_size: Vector2, _num_rooms: int, min_room_size: int, ma attempts -= 1 if attempts <= 0: - print("Dungeon generator:Reached maximum attempts") nrOfRoomErrors += 1 break @@ -147,21 +146,18 @@ func generate_dungeon(map_size: Vector2, _num_rooms: int, min_room_size: int, ma # Find an unreachable room and try to connect it for room in all_rooms: if not reachable.has(room): - print("Found unreachable room at ", room.x, ",", room.y) var connected = false # Try to connect to each reachable room until success for target_room in reachable: var door = create_corridor_between_rooms(room, target_room, grid) if door.size() > 0: - print("Connected unreachable room") set_door(door, grid) all_doors.append(door) connected = true break if not connected: - print("Failed to connect room directly, trying intermediate room") # Try creating intermediate room with multiple positions for offset_x in [-2, 0, 2]: for offset_y in [-2, 0, 2]: @@ -188,7 +184,6 @@ func generate_dungeon(map_size: Vector2, _num_rooms: int, min_room_size: int, ma attempts2 -= 1 if attempts2 <= 0: - print("Failed to connect all rooms after maximum attempts") nrOfDoorErrors += 1 break @@ -562,7 +557,6 @@ func set_door(door: Dictionary, grid: Array) -> void: match door.dir: "N", "S": if door.h > 4: - print("ns - larger door", door.h) # Set 2x4 corridor for dx in range(2): for dy in range(door.h): @@ -570,7 +564,6 @@ func set_door(door: Dictionary, grid: Array) -> void: grid[door.x + dx][door.y + dy] = 2 "E", "W": if door.w > 4: - print("ew - larger door", door.w) # Set 4x2 corridor for dx in range(door.w): for dy in range(2): diff --git a/src/scripts/entities/character_stats.gd b/src/scripts/entities/character_stats.gd index f29158c..32523bb 100644 --- a/src/scripts/entities/character_stats.gd +++ b/src/scripts/entities/character_stats.gd @@ -418,7 +418,6 @@ func drop_equipment(iItem:Item): pass func add_item(iItem:Item): - print("Adding item to player:", character_name, " item being added:", iItem) self.inventory.push_back(iItem) emit_signal("character_changed", self) pass @@ -547,13 +546,11 @@ func setHair(iType:int): if iType >= 5: # male hairstyles hairstyle = "res://assets/gfx/Puny-Characters/Layer 4 - Hairstyle/Hairstyles/MHairstyle" + str(iType-4) hairstyle += "White.png" - print("resulting hairstyle should be:", hairstyle) emit_signal("character_changed", self) pass func setEyeLashes(iEyeLashes: int): if iEyeLashes < 0 or iEyeLashes > 8: - print("Eye lash value out of range 0 to 9", iEyeLashes) return if iEyeLashes == 0: eye_lashes = "" @@ -588,7 +585,6 @@ func setEyeLashes(iEyeLashes: int): func setEyes(iEyes: int): if iEyes < 0 or iEyes > 14: - print("Eye color value out of range 0 to 14", iEyes) return if iEyes == 0: eyes = "" @@ -641,7 +637,6 @@ func setEyes(iEyes: int): func setEars(iEars: int): if iEars < 0 or iEars > 7: - print("Ear value out of range 0 to 7", iEars) return if iEars == 0: add_on = "" diff --git a/src/scripts/entities/pickups/loot.gd b/src/scripts/entities/pickups/loot.gd index 0c343c7..9b5f7b6 100644 --- a/src/scripts/entities/pickups/loot.gd +++ b/src/scripts/entities/pickups/loot.gd @@ -40,7 +40,6 @@ func _process(delta: float) -> void: velocity = velocity.lerp(Vector2.ZERO, 1.0 - exp(-friction * delta)) # only slow down if on floor positionZ = 0 if abs(velocityZ) > minBounceVelocity: - print(velocityZ) #Bounce sound here for items: #$SfxCoinBounce.volume_db = -1 + (-10-(velocityZ*0.1)) #$SfxCoinBounce.play() @@ -92,10 +91,8 @@ func setItem(iItem: Item = null) -> void: pass @rpc("any_peer", "reliable", "call_local") -func request_pickup(player_id: int): - print("[NETWORK] request_pickup called on ", "SERVER" if multiplayer.is_server() else "CLIENT", " for player: ", player_id) +func request_pickup(_player_id: int): if multiplayer.is_server(): - print("WE are server... do stuff:") sync_has_been_picked_up = true visible = false # Tell all clients to remove the loot @@ -109,16 +106,13 @@ func request_pickup(player_id: int): func pick_up_local(player_id: int): if sync_has_been_picked_up: return - print("[LOCAL] Picking up item for player: ", player_id) var player = MultiplayerManager.playersNode.get_node(str(player_id)) if player: - print("[LOCAL] we have the player here") sync_has_been_picked_up = true visible = false # Add item to local inventory player.stats.add_item(it) # Tell server about pickup - print("we are telling server about pickup", player_id) if not multiplayer.is_server(): request_pickup.rpc_id(1, player_id) else: @@ -133,7 +127,6 @@ func pick_up_local(player_id: int): func remove_loot(): visible = false sync_has_been_picked_up = true - print("[NETWORK] Removing loot from scene") $SfxPickup.play() await $SfxPickup.finished diff --git a/src/scripts/entities/player/player.gd b/src/scripts/entities/player/player.gd index 7f28d20..fe50f5d 100644 --- a/src/scripts/entities/player/player.gd +++ b/src/scripts/entities/player/player.gd @@ -25,35 +25,28 @@ var held_entity = null var grabbed_entity = null @export var held_entity_path: String = "": set(value): - Console.print("Running player set held_entity_path") if value != "": self.held_entity = get_node_or_null(value) - if self.held_entity != null: - Console.print("Client ", multiplayer.get_unique_id(), " synced held_entity to: ", held_entity.name) - else: - Console.print("Client ", multiplayer.get_unique_id(), " failed to find held_entity at path: ", value) else: if self.held_entity != null: - Console.print("Client ", multiplayer.get_unique_id(), " about to release held_entity: ", self.held_entity.name) self.held_entity.release() self.held_entity = null - Console.print("Client ", multiplayer.get_unique_id(), " cleared held_entity via sync") held_entity_path = value @export var grabbed_entity_path: String = "": set(value): - Console.print("Running player set grabbed_entity_path") if value != "": self.grabbed_entity = get_node_or_null(value) if self.grabbed_entity != null: self.grabbed_entity.grab(self) - Console.print("Client ", multiplayer.get_unique_id(), " synced grabbed_entity to: ", self.grabbed_entity.name) - else: - Console.print("Client ", multiplayer.get_unique_id(), " failed to find grabbed_entity at path: ", value) + # Lock direction when grabbing - use current last_direction + if locked_grab_direction == Vector2.ZERO: + locked_grab_direction = last_direction else: if self.grabbed_entity != null: self.grabbed_entity.release() self.grabbed_entity = null + locked_grab_direction = Vector2.ZERO # Clear locked direction when releasing var is_player = true @export var direction_vector = Vector2(0, 0) @@ -176,13 +169,13 @@ enum Direction { @export var direction = Vector2(0, 0) # default down @export var last_direction = Vector2(0, 1) +var locked_grab_direction: Vector2 = Vector2.ZERO # Direction locked when grabbing a pot @export var current_direction = Direction.DOWN var current_frame = 0 var time_since_last_frame = 0.0 @export var current_animation: String = "IDLE": set(iAnimation): if current_animation != iAnimation: - Console.print("Animation changed from ", current_animation, " to: ", iAnimation) current_frame = 0 time_since_last_frame = 0 current_animation = iAnimation @@ -242,7 +235,6 @@ func _enter_tree() -> void: #set_multiplayer_authority(player_id) if !isDemoCharacter: set_multiplayer_authority(int(str(name))) - print("we are setting multiplayer auth to:", name) pass func _handleInput() -> void: @@ -308,11 +300,6 @@ func _apply_movement_from_input(_delta: float) -> void: time_since_last_frame = 0 current_frame = 0 current_animation = "RUN" + extraString - if grabbed_entity == null and held_entity == null: - last_direction = direction - elif held_entity != null: - # Update last_direction when holding a pot for synchronization - last_direction = direction is_moving = true else: if current_animation != "IDLE" + extraString: @@ -341,13 +328,25 @@ func _apply_movement_from_input(_delta: float) -> void: # Only restrict movement when grabbing/pushing entities, not when lifting/holding if grabbed_entity != null and held_entity == null: grabMultiplier = 0.3 - # set direction to only be last_direction or inverse last_direction + # CRITICAL: Lock direction to locked_grab_direction (set when grabbing) + # If locked_grab_direction is not set, set it now (fallback for edge cases) + if locked_grab_direction == Vector2.ZERO: + locked_grab_direction = last_direction + # set direction to only be locked_grab_direction or inverse locked_grab_direction if direction != Vector2.ZERO: - var inverseLastDirection = last_direction * -1 - if abs(direction.angle_to(last_direction)) > abs(direction.angle_to(inverseLastDirection)): - direction = inverseLastDirection + var inverseLockedDir = locked_grab_direction * -1 + if abs(direction.angle_to(locked_grab_direction)) > abs(direction.angle_to(inverseLockedDir)): + direction = inverseLockedDir else: - direction = last_direction + direction = locked_grab_direction + # DO NOT update last_direction when pushing/pulling - keep it locked! + # This ensures the locked direction stays the same + else: + # Only update last_direction when NOT pushing/pulling + # This ensures direction syncs correctly when holding pots or doing nothing + if direction != Vector2.ZERO: + last_direction = direction + movespeed *= grabMultiplier @@ -360,8 +359,8 @@ func _apply_movement_from_input(_delta: float) -> void: else: velocity.y = move_toward(velocity.y, 0, SPEED) - if grabbed_entity != null: - grabbed_entity.velocity = velocity + # Note: Pot now follows holder's position directly instead of using velocity + # This ensures push/pull works correctly even when velocity isn't synced if is_lifting: if held_entity == null: @@ -370,14 +369,11 @@ func _apply_movement_from_input(_delta: float) -> void: pass if is_attacking: - print("Player ", multiplayer.get_unique_id(), " is attacking, held_entity: ", held_entity) if grabbed_entity == null and held_entity == null and current_animation != "THROW" and current_animation != "DAMAGE" and current_animation != "DIE": current_frame = 0 time_since_last_frame = 0 current_animation = "SWORD" if held_entity != null: - print("Player ", multiplayer.get_unique_id(), " throwing held_entity, is_server: ", multiplayer.is_server()) - Console.print("Player ", multiplayer.get_unique_id(), " throwing held_entity, is_server: ", multiplayer.is_server()) # throw it: if multiplayer.is_server(): # Server can throw directly @@ -387,12 +383,7 @@ func _apply_movement_from_input(_delta: float) -> void: held_entity_path = "" else: # Client requests throw from server - print("Player ", multiplayer.get_unique_id(), " requesting throw via RPC") - Console.print("Player ", multiplayer.get_unique_id(), " requesting throw via RPC") MultiplayerManager.request_throw_pot.rpc_id(1, held_entity.get_path(), multiplayer.get_unique_id(), last_direction) - else: - print("Player ", multiplayer.get_unique_id(), " tried to throw but held_entity is null!") - Console.print("Player ", multiplayer.get_unique_id(), " tried to throw but held_entity is null!") is_releasing = false is_grabbing = false is_lifting = false @@ -428,7 +419,10 @@ func _apply_movement_from_input(_delta: float) -> void: MultiplayerManager.request_put_down_pot.rpc_id(1, held_entity.get_path(), multiplayer.get_unique_id()) if grabbed_entity != null and "release" in grabbed_entity: grabbed_entity.release() + # Clear grabbed_entity_path first so the setter clears the entity properly + grabbed_entity_path = "" grabbed_entity = null + locked_grab_direction = Vector2.ZERO # Clear locked direction when releasing is_releasing = false is_grabbing = false if held_entity == null: @@ -451,6 +445,11 @@ func _apply_movement_from_input(_delta: float) -> void: grabbed_entity = pot grabbed_entity_path = str(pot.get_path()) current_animation = "IDLE_PUSH" + # Lock direction to current last_direction when grabbing + locked_grab_direction = last_direction + # Sync to all clients + set_grabbed_entity_path_rpc.rpc(str(pot.get_path())) + sync_animation.rpc("IDLE_PUSH") else: # Client uses RPC to request from server if "request_grab_pot" in pot: @@ -470,9 +469,13 @@ func _apply_movement_from_input(_delta: float) -> void: # make sure we are looking in direction of the entity var player_to_pot = (a.get_parent().global_position - self.global_position).normalized() if player_to_pot.dot(self.last_direction) > 0.78: + # Release grabbed entity before lifting if grabbed_entity != null and "release" in grabbed_entity: grabbed_entity.release() + var _old_grabbed = grabbed_entity grabbed_entity = null + grabbed_entity_path = "" + locked_grab_direction = Vector2.ZERO is_grabbing = false var pot = a.get_parent() @@ -489,13 +492,7 @@ func _apply_movement_from_input(_delta: float) -> void: #current_animation = "LIFT" else: # Client uses RPC to request from server - Console.print("Client ", multiplayer.get_unique_id(), " calling request_lift_pot RPC for pot at: ", pot.get_path()) - Console.print("Client ", multiplayer.get_unique_id(), " pot object: ", pot) - Console.print("Client ", multiplayer.get_unique_id(), " is_server: ", multiplayer.is_server()) - Console.print("Client ", multiplayer.get_unique_id(), " about to call RPC to server (peer 1)") - MultiplayerManager.request_lift_pot.rpc_id(1, pot.get_path(), multiplayer.get_unique_id()) - Console.print("Client ", multiplayer.get_unique_id(), " RPC call completed") break # only allow 1 at a time :) pass pass @@ -536,23 +533,31 @@ func _apply_movement_from_input(_delta: float) -> void: pass func _apply_animations(delta: float): - if grabbed_entity == null: - if last_direction.y < 0 and last_direction.x > 0: - current_direction = Direction.UP_RIGHT - elif last_direction.y < 0 and last_direction.x < 0: - current_direction = Direction.UP_LEFT - elif last_direction.y > 0 and last_direction.x > 0: - current_direction = Direction.DOWN_RIGHT - elif last_direction.y > 0 and last_direction.x < 0: - current_direction = Direction.DOWN_LEFT - elif last_direction.y < 0: - current_direction = Direction.UP - elif last_direction.x > 0: - current_direction = Direction.RIGHT - elif last_direction.y > 0: - current_direction = Direction.DOWN - elif last_direction.x < 0: - current_direction = Direction.LEFT + # Always calculate current_direction from last_direction, regardless of grabbed_entity + # This ensures direction is correct when pushing/pulling pots, holding pots, or doing nothing + if last_direction.y < 0 and last_direction.x > 0: + current_direction = Direction.UP_RIGHT + elif last_direction.y < 0 and last_direction.x < 0: + current_direction = Direction.UP_LEFT + elif last_direction.y > 0 and last_direction.x > 0: + current_direction = Direction.DOWN_RIGHT + elif last_direction.y > 0 and last_direction.x < 0: + current_direction = Direction.DOWN_LEFT + elif last_direction.y < 0: + current_direction = Direction.UP + elif last_direction.x > 0: + current_direction = Direction.RIGHT + elif last_direction.y > 0: + current_direction = Direction.DOWN + elif last_direction.x < 0: + current_direction = Direction.LEFT + + # Update label to show animation and direction + if has_node("LabelCurrentAnimation"): + var dir_names = ["DOWN", "DOWN_RIGHT", "RIGHT", "UP_RIGHT", "UP", "UP_LEFT", "LEFT", "DOWN_LEFT"] + var dir_name = dir_names[current_direction] if current_direction < dir_names.size() else "UNKNOWN" + var dir_str = "%.1f,%.1f" % [last_direction.x, last_direction.y] + $LabelCurrentAnimation.text = current_animation + "\nDir:" + dir_name + "\nVec:" + dir_str $Sprite2DBody.frame = current_direction * $Sprite2DBody.hframes + ANIMATIONS[current_animation]["frames"][current_frame] $Sprite2DBoots.frame = $Sprite2DBody.frame @@ -593,7 +598,6 @@ func _stats_changed(iStats: CharacterStats): if iStats.equipment["armour"] == null: armour_sprite.visible = false else: - print("armour is:", iStats.equipment["armour"]) if armour_sprite.texture == null or (armour_sprite.texture as Texture2D).resource_path != iStats.equipment["armour"].equipmentPath: armour_sprite.texture = load(iStats.equipment["armour"].equipmentPath) armour_sprite.visible = true @@ -866,8 +870,7 @@ func _on_died(): stats.is_invulnerable = false stats.forceUpdate() if current_animation != "IDLE": - Console.print("Animation changed from ", current_animation, " to: ", "IDLE") - current_animation = "IDLE" + current_animation = "IDLE" self.set_collision_layer_value(10, true) pass @@ -894,6 +897,8 @@ func set_held_entity_path_rpc(entity_path: String): @rpc("any_peer", "reliable") func set_grabbed_entity_path_rpc(entity_path: String): + # Set grabbed_entity_path - the setter will handle finding the entity and locking direction + # This ensures locked_grab_direction is set correctly via the setter grabbed_entity_path = entity_path diff --git a/src/scripts/entities/player/player.tscn b/src/scripts/entities/player/player.tscn index 0066941..d1301f1 100644 --- a/src/scripts/entities/player/player.tscn +++ b/src/scripts/entities/player/player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=44 format=3 uid="uid://dgtfy455abe1t"] +[gd_scene format=3 uid="uid://dgtfy455abe1t"] [ext_resource type="Script" uid="uid://cvvy2s6620mcw" path="res://scripts/entities/player/player.gd" id="1_sgemx"] [ext_resource type="Texture2D" uid="uid://bkninujaqqvb1" path="res://assets/gfx/Puny-Characters/Layer 0 - Skins/Human1_1.png" id="3_0818e"] @@ -82,6 +82,9 @@ properties/12/replication_mode = 2 properties/13/path = NodePath(".:grabbed_entity_path") properties/13/spawn = true properties/13/replication_mode = 2 +properties/14/path = NodePath(".:current_direction") +properties/14/spawn = true +properties/14/replication_mode = 2 [sub_resource type="Gradient" id="Gradient_hsjxb"] offsets = PackedFloat32Array(0.847255, 0.861575) @@ -172,126 +175,126 @@ stream_4/stream = ExtResource("27_1sdav") stream_5/stream = ExtResource("28_x7koh") stream_6/stream = ExtResource("29_jl8uc") -[node name="Player" type="CharacterBody2D"] +[node name="Player" type="CharacterBody2D" unique_id=642482055] collision_layer = 512 collision_mask = 704 script = ExtResource("1_sgemx") -[node name="PlayerLight" type="PointLight2D" parent="."] +[node name="PlayerLight" type="PointLight2D" parent="." unique_id=98233177] z_index = 10 position = Vector2(-1, -6) blend_mode = 2 range_layer_max = 2 texture = SubResource("GradientTexture2D_n1hb6") -[node name="PlayerSynchronizer" type="MultiplayerSynchronizer" parent="."] +[node name="PlayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=1561958126] replication_config = SubResource("SceneReplicationConfig_fgrik") -[node name="Sprite2DShadow" type="Sprite2D" parent="."] +[node name="Sprite2DShadow" type="Sprite2D" parent="." unique_id=1430953243] position = Vector2(0, 2) texture = SubResource("GradientTexture2D_0818e") -[node name="Sprite2DBody" type="Sprite2D" parent="."] +[node name="Sprite2DBody" type="Sprite2D" parent="." unique_id=36949699] material = SubResource("ShaderMaterial_2bw0v") position = Vector2(0, -5) texture = ExtResource("3_0818e") hframes = 35 vframes = 8 -[node name="Sprite2DBoots" type="Sprite2D" parent="."] +[node name="Sprite2DBoots" type="Sprite2D" parent="." unique_id=1502518208] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("5_2bw0v") hframes = 35 vframes = 8 -[node name="Sprite2DArmour" type="Sprite2D" parent="."] +[node name="Sprite2DArmour" type="Sprite2D" parent="." unique_id=1239356181] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("5_7drg4") hframes = 35 vframes = 8 -[node name="Sprite2DFacialHair" type="Sprite2D" parent="."] +[node name="Sprite2DFacialHair" type="Sprite2D" parent="." unique_id=973907314] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("7_2bw0v") hframes = 35 vframes = 8 -[node name="Sprite2DHair" type="Sprite2D" parent="."] +[node name="Sprite2DHair" type="Sprite2D" parent="." unique_id=1924405266] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("8_pyh4g") hframes = 35 vframes = 8 -[node name="Sprite2DEyes" type="Sprite2D" parent="."] +[node name="Sprite2DEyes" type="Sprite2D" parent="." unique_id=1443066557] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("8_68eso") hframes = 35 vframes = 8 -[node name="Sprite2DEyeLashes" type="Sprite2D" parent="."] +[node name="Sprite2DEyeLashes" type="Sprite2D" parent="." unique_id=691771626] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("9_cvm1n") hframes = 35 vframes = 8 -[node name="Sprite2DAddons" type="Sprite2D" parent="."] +[node name="Sprite2DAddons" type="Sprite2D" parent="." unique_id=647154359] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("10_o8aek") hframes = 35 vframes = 8 -[node name="Sprite2DHeadgear" type="Sprite2D" parent="."] +[node name="Sprite2DHeadgear" type="Sprite2D" parent="." unique_id=831310279] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("11_idlgo") hframes = 35 vframes = 8 -[node name="Sprite2DWeapon" type="Sprite2D" parent="."] +[node name="Sprite2DWeapon" type="Sprite2D" parent="." unique_id=2021209530] material = SubResource("ShaderMaterial_8ugno") position = Vector2(0, -5) texture = ExtResource("12_0818e") hframes = 35 vframes = 8 -[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=131165090] position = Vector2(0, -1) shape = SubResource("RectangleShape2D_sgemx") -[node name="Camera2D" type="Camera2D" parent="."] +[node name="Camera2D" type="Camera2D" parent="." unique_id=643763897] zoom = Vector2(3, 3) position_smoothing_enabled = true script = ExtResource("4_n1hb6") -[node name="Timer" type="Timer" parent="Camera2D"] +[node name="Timer" type="Timer" parent="Camera2D" unique_id=880082893] -[node name="SfxWalk" type="AudioStreamPlayer2D" parent="."] +[node name="SfxWalk" type="AudioStreamPlayer2D" parent="." unique_id=568890407] stream = SubResource("AudioStreamRandomizer_40ewq") volume_db = -12.0 attenuation = 8.28211 bus = &"Sfx" -[node name="TimerWalk" type="Timer" parent="SfxWalk"] +[node name="TimerWalk" type="Timer" parent="SfxWalk" unique_id=1285633304] wait_time = 0.3 one_shot = true -[node name="Area2DPickup" type="Area2D" parent="."] +[node name="Area2DPickup" type="Area2D" parent="." unique_id=1858677050] collision_layer = 0 collision_mask = 1536 -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"] +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup" unique_id=1519370124] position = Vector2(0, -1) shape = SubResource("RectangleShape2D_0818e") debug_color = Color(0.7, 0.495943, 0.135446, 0.42) -[node name="LabelPlayerName" type="Label" parent="."] +[node name="LabelPlayerName" type="Label" parent="." unique_id=900440685] z_index = 18 z_as_relative = false offset_left = -29.82 @@ -306,7 +309,8 @@ theme_override_font_sizes/font_size = 6 text = "Playername" horizontal_alignment = 1 -[node name="LabelCurrentAnimation" type="Label" parent="."] +[node name="LabelCurrentAnimation" type="Label" parent="." unique_id=2024783119] +visible = false z_index = 18 z_as_relative = false offset_left = -29.82 @@ -321,10 +325,10 @@ theme_override_font_sizes/font_size = 6 text = "CurAnim" horizontal_alignment = 1 -[node name="CanvasLayer" type="CanvasLayer" parent="."] +[node name="CanvasLayer" type="CanvasLayer" parent="." unique_id=1694102436] follow_viewport_enabled = true -[node name="TextureProgressBarHealth" type="TextureProgressBar" parent="."] +[node name="TextureProgressBarHealth" type="TextureProgressBar" parent="." unique_id=1783325028] anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 @@ -338,15 +342,15 @@ value = 100.0 texture_under = SubResource("GradientTexture1D_pyh4g") texture_progress = SubResource("GradientTexture1D_fj670") -[node name="SfxDie" type="AudioStreamPlayer2D" parent="."] +[node name="SfxDie" type="AudioStreamPlayer2D" parent="." unique_id=1749167232] stream = ExtResource("22_jfw4q") bus = &"Sfx" -[node name="SfxTakeDamage" type="AudioStreamPlayer2D" parent="."] +[node name="SfxTakeDamage" type="AudioStreamPlayer2D" parent="." unique_id=956824742] stream = SubResource("AudioStreamRandomizer_hnhes") bus = &"Sfx" -[node name="TimerGrab" type="Timer" parent="."] +[node name="TimerGrab" type="Timer" parent="." unique_id=129649929] wait_time = 0.2 one_shot = true diff --git a/src/scripts/entities/world/bomb.gd b/src/scripts/entities/world/bomb.gd index 11cdb5d..9c32250 100644 --- a/src/scripts/entities/world/bomb.gd +++ b/src/scripts/entities/world/bomb.gd @@ -326,7 +326,6 @@ func put_down() -> bool: var results = space_state.intersect_point(params) if results.size() > 0: # Found overlapping walls at target position - print("Cannot place pot: Wall in the way") return false # Second check: Line of sight between player and target position @@ -341,7 +340,6 @@ func put_down() -> bool: var result = space_state.intersect_ray(query) if result: # Hit something between player and target position - print("Cannot place pot: Path blocked") return false # Third check: Make sure we're not placing on top of another pot or object @@ -349,7 +347,6 @@ func put_down() -> bool: results = space_state.intersect_point(params) if results.size() > 0: # Found overlapping objects at target position - print("Cannot place pot: Object in the way") return false $Area2DCollision.set_deferred("monitoring", false) @@ -450,7 +447,6 @@ func _on_area_2d_collision_body_entered(body: Node2D) -> void: elif collider != self and "breakPot" in collider: collider.take_damage(self, thrown_by) # create particles from pot: - print("ye body is:", body) take_damage.rpc(null, null) pass diff --git a/src/scripts/entities/world/pot.gd b/src/scripts/entities/world/pot.gd index c80696b..4e76766 100644 --- a/src/scripts/entities/world/pot.gd +++ b/src/scripts/entities/world/pot.gd @@ -11,11 +11,9 @@ var object_name = "bomb" @export var is_being_lifted = false: set(value): is_being_lifted = value - Console.print("Pot is_being_lifted changed to: ", value, " on peer: ", multiplayer.get_unique_id()) @export var is_being_put_down = false: set(value): is_being_put_down = value - Console.print("Pot is_being_put_down changed to: ", value, " on peer: ", multiplayer.get_unique_id()) @export var is_being_grabbed = false @export var is_moving = false @export var is_spawning = false @@ -49,24 +47,26 @@ var re_enable_collision_after_time = 0.0 var re_enable_time = 0.17 var previousFrameVel = Vector2.ZERO var hasShownSmokePuffs = false +var grab_follow_speed = 15.0 # Speed at which pot follows holder when grabbed +var previous_holder_position = Vector2.ZERO # Track previous holder position to calculate movement delta +var previous_client_position = Vector2.ZERO # Track previous position on client for movement detection +var push_lead_factor = 1.1 # When pushing, pot moves slightly ahead (110% of player movement) +var min_push_distance = 12.0 # Minimum distance pot should maintain from player when pushing to avoid blocking @export var holder_peer_id: int = 0: set(value): holder_peer_id = value - Console.print("Pot holder_peer_id changed to: ", value, " on peer: ", multiplayer.get_unique_id()) - # Clear lifting state when holder is cleared, but only if we're not in the middle of lifting - if value == 0 and !is_being_lifted: - is_being_lifted = false + # Clear state when holder is cleared + if value == 0: holder = null + # Always clear grabbed and lifted states when holder is cleared + is_being_grabbed = false + is_being_lifted = false elif value != 0: # Find the holder by peer ID var spawn_root = get_tree().get_current_scene().get_node("SpawnRoot") if spawn_root: holder = spawn_root.get_node_or_null(str(value)) - if holder: - Console.print("Pot found holder: ", holder.name, " for peer ID: ", value) - else: - Console.print("Pot failed to find holder for peer ID: ", value) func _ready() -> void: if is_spawning: @@ -83,21 +83,21 @@ func _ready() -> void: func _physics_process(delta: float) -> void: # Update holder based on holder_peer_id for network sync + # CRITICAL: holder_peer_id is the source of truth - if it's 0, there's no holder if holder_peer_id != 0: var player = get_tree().get_current_scene().get_node("SpawnRoot").get_node_or_null(str(holder_peer_id)) if player and holder != player: - Console.print("Pot updating holder from ", holder, " to ", player.name) holder = player - # Ensure lifting state is synced when holder changes - if !is_being_lifted and !is_being_grabbed: - is_being_lifted = true - lift_progress = 0.0 - elif !player: - Console.print("Pot could not find player with peer_id: ", holder_peer_id) - elif holder_peer_id == 0 and holder != null: - Console.print("Pot clearing holder (holder_peer_id is 0)") - holder = null - is_being_lifted = false + elif holder_peer_id == 0: + # No holder - clear everything + if holder != null: + holder = null + if is_being_grabbed: + is_being_grabbed = false + if is_being_lifted: + is_being_lifted = false + if velocity != Vector2.ZERO: + velocity = Vector2.ZERO # Handle lifted pot position on ALL clients for smooth following if is_being_lifted and holder: @@ -118,7 +118,6 @@ func _physics_process(delta: float) -> void: else: # Debug: Check why pot is not following if is_being_lifted and !holder: - Console.print("Pot is_being_lifted but holder is null! holder_peer_id: ", holder_peer_id) # Fix inconsistent state if holder_peer_id == 0: is_being_lifted = false @@ -128,7 +127,21 @@ func _physics_process(delta: float) -> void: update_sprite_scale() if multiplayer.is_server(): - if is_being_thrown: + # CRITICAL: If holder_peer_id is 0, ALWAYS clear grab state immediately + # This must happen before ANY logic runs to prevent movement after release + if holder_peer_id == 0: + is_being_grabbed = false + if holder != null: + holder = null + if velocity != Vector2.ZERO: + velocity = Vector2.ZERO + if is_moving: + is_moving = false + if $SfxDrag2.playing: + $SfxDrag2.stop() + # Skip all grab logic if holder_peer_id is 0 + pass + elif is_being_thrown: re_enable_collision_after_time -= delta if re_enable_collision_after_time <= 0.0: # enable collisions again @@ -187,23 +200,96 @@ func _physics_process(delta: float) -> void: positionZ = lift_height * lift_progress update_sprite_scale() - elif is_being_grabbed: - #if velocity != Vector2.ZERO and velocity != previousFrameVel and hasShownSmokePuffs == false: - if velocity != Vector2.ZERO: - is_moving = true - #hasShownSmokePuffs = true - $GPUParticles2D.emitting = true - $GPUParticles2D/TimerSmokeParticles.start() - if !$SfxDrag2.playing: - $SfxDrag2.play() + # CRITICAL: Only follow if holder_peer_id is NOT 0 (this is the source of truth) + # Check holder_peer_id FIRST before is_being_grabbed to ensure we never follow when released + # ONLY run this on server (pot has authority 1 = server) + # DOUBLE CHECK: holder_peer_id must be non-zero AND holder must exist AND match + if holder_peer_id != 0 and is_being_grabbed and holder != null: + # Only follow if holder's authority matches holder_peer_id + if holder.get_multiplayer_authority() == holder_peer_id: + # Calculate how much the player has moved since last frame + var player_movement = holder.global_position - previous_holder_position + + # Only move pot if player has moved + if player_movement.length() > 0.01: + # Get the locked grab direction to determine push/pull axis + var locked_dir = Vector2.ZERO + if "locked_grab_direction" in holder and holder.locked_grab_direction != Vector2.ZERO: + locked_dir = holder.locked_grab_direction.normalized() + + if locked_dir != Vector2.ZERO: + # Project player's movement onto the push/pull direction + var movement_along_axis = player_movement.project(locked_dir) + + # Determine if pushing (moving in locked_dir direction) or pulling (moving opposite) + var is_pushing = movement_along_axis.dot(locked_dir) > 0 + + if is_pushing: + # PUSHING: Pot moves first, ahead of player + # Move pot by slightly more than player movement so it leads (moves first) + var push_movement = movement_along_axis * push_lead_factor + global_position += push_movement + velocity = push_movement / delta if delta > 0 else Vector2.ZERO + else: + # PULLING: Player moves first, pot follows behind + # Move pot by the exact same amount as player (pot follows immediately) + global_position += movement_along_axis + velocity = movement_along_axis / delta if delta > 0 else Vector2.ZERO + else: + # No locked direction, just move pot by player's movement + global_position += player_movement + velocity = player_movement / delta if delta > 0 else Vector2.ZERO + + # Update previous position for next frame + previous_holder_position = holder.global_position + + if velocity.length() > 1.0: + is_moving = true + $GPUParticles2D.emitting = true + $GPUParticles2D/TimerSmokeParticles.start() + if !$SfxDrag2.playing: + $SfxDrag2.play() + else: + is_moving = false + if $SfxDrag2.playing: + $SfxDrag2.stop() + previousFrameVel = velocity + else: + # Player hasn't moved - keep pot at current position + velocity = Vector2.ZERO + is_moving = false + if $SfxDrag2.playing: + $SfxDrag2.stop() + # Still update previous position even if not moving + previous_holder_position = holder.global_position else: + # No valid holder, clear grab state and stop movement immediately + is_being_grabbed = false is_moving = false if $SfxDrag2.playing: $SfxDrag2.stop() - move_and_collide(velocity * delta) - previousFrameVel = velocity + velocity = Vector2.ZERO + holder = null + holder_peer_id = 0 # Force clear to ensure no following pass - elif !is_being_lifted: # it just spawned or is free-falling: + + # CRITICAL FINAL CHECK: If holder_peer_id is 0, STOP ALL MOVEMENT immediately + # This must run AFTER all grab logic to catch any cases where holder_peer_id was set to 0 + # but the pot is still trying to move + if holder_peer_id == 0: + if is_being_grabbed: + is_being_grabbed = false + if holder != null: + holder = null + if velocity != Vector2.ZERO: + velocity = Vector2.ZERO + if is_moving: + is_moving = false + if $SfxDrag2.playing: + $SfxDrag2.stop() + + # Only handle free-falling if we're not being held (holder_peer_id == 0 is the source of truth) + if holder_peer_id == 0 and !is_being_lifted: # it just spawned or is free-falling: # Apply gravity to vertical movement velocityZ += accelerationZ * delta positionZ += velocityZ * delta @@ -232,6 +318,13 @@ func _physics_process(delta: float) -> void: update_sprite_scale() pass else: + # CRITICAL: If holder_peer_id is 0, ALWAYS clear grab state immediately (client side) + # This must happen before any grab logic runs + if holder_peer_id == 0: + is_being_grabbed = false + if holder != null: + holder = null + if is_fused and $AnimationPlayer.current_animation == "idle": if $SfxBombFuse.playing: $SfxBombFuse.play() @@ -269,16 +362,44 @@ func _physics_process(delta: float) -> void: global_position = target_position positionZ = lift_height update_sprite_scale() - elif is_being_grabbed: - if is_moving: - $GPUParticles2D.emitting = true - $GPUParticles2D/TimerSmokeParticles.start() - if !$SfxDrag2.playing: - $SfxDrag2.play() + # CRITICAL: On client, do NOT move the pot - only the server should move it + # The pot's position is synced via replication from the server + # We only handle visual/audio effects here + elif holder_peer_id == 0: + # No holder - ensure we're not in grabbed state + if is_being_grabbed: + is_being_grabbed = false + is_moving = false + if $SfxDrag2.playing: + $SfxDrag2.stop() + elif is_being_grabbed and holder_peer_id != 0: + # Only handle visual/audio effects on client, don't move the pot + # The server handles the actual movement and syncs position via replication + if holder != null and holder.get_multiplayer_authority() == holder_peer_id: + # Check if pot appears to be moving (based on position changes from server) + var pot_movement = global_position - previous_client_position + + # If pot has moved, it's being pushed/pulled + if pot_movement.length() > 0.5: + is_moving = true + $GPUParticles2D.emitting = true + $GPUParticles2D/TimerSmokeParticles.start() + if !$SfxDrag2.playing: + $SfxDrag2.play() + else: + is_moving = false + if $SfxDrag2.playing: + $SfxDrag2.stop() + + # Update previous position for next frame + previous_client_position = global_position else: + # No valid holder, clear state + is_being_grabbed = false + is_moving = false if $SfxDrag2.playing: $SfxDrag2.stop() - else: + elif !is_being_grabbed: if is_spawning: if positionZ <= 0: $SfxLand.play() @@ -292,7 +413,6 @@ func _physics_process(delta: float) -> void: pass # Fix stuck put_down state if is_being_put_down and lift_progress <= 0: - Console.print("Pot is_being_put_down but lift_progress is 0, clearing state") is_being_put_down = false update_sprite_scale() if is_destroyed and !destroy_initiated: @@ -341,7 +461,6 @@ func throw(direction: Vector2, initial_velocity: float = 200): @rpc("any_peer", "reliable") func throw_rpc(direction: Vector2, initial_velocity: float = 200): - Console.print("Pot throw_rpc called on peer: ", multiplayer.get_unique_id()) # Only execute on server to avoid conflicts if multiplayer.is_server(): throw(direction, initial_velocity) @@ -353,23 +472,70 @@ func grab(new_holder: CharacterBody2D) -> bool: holder_peer_id = new_holder.get_multiplayer_authority() is_being_grabbed = true indicate(false) + # Initialize previous position to current position so we can track movement + previous_holder_position = new_holder.global_position + previous_client_position = global_position # Initialize client position tracking + # Disable pot's collision layer so grabber can't collide with it (prevents blocking when pushing) + # Note: This also means other players can't collide with pot while it's grabbed + # The pot uses direct position updates (not move_and_collide) so collisions aren't needed for movement + self.set_collision_layer_value(8, false) # Disable pot's collision layer + # Don't change pot's position - it should stay where it is and only move when player pushes/pulls return true return false func release(): - Console.print("Pot release() called on peer: ", multiplayer.get_unique_id()) - holder = null - holder_peer_id = 0 - is_being_grabbed = false - hasShownSmokePuffs = false - indicate(true) - if $SfxDrag2.playing: - $SfxDrag2.stop() + # Clear all grab-related state + # CRITICAL: If we're not the server, we need to notify the server to release + # The pot has authority 1 (server), so the server must be the one to clear holder_peer_id + if not multiplayer.is_server(): + # Client requests server to release - use holder_peer_id directly + if holder_peer_id != 0: + request_release_pot.rpc_id(1, get_path(), holder_peer_id) + # Also clear locally for immediate visual feedback + holder = null + holder_peer_id = 0 + is_being_grabbed = false + hasShownSmokePuffs = false + velocity = Vector2.ZERO + # Re-enable pot's collision layer when released + self.set_collision_layer_value(8, true) # Re-enable pot's collision layer + indicate(true) + if $SfxDrag2.playing: + $SfxDrag2.stop() + else: + # Server can release directly + holder = null + holder_peer_id = 0 + is_being_grabbed = false + hasShownSmokePuffs = false + velocity = Vector2.ZERO + # Re-enable pot's collision layer when released + self.set_collision_layer_value(8, true) # Re-enable pot's collision layer + indicate(true) + if $SfxDrag2.playing: + $SfxDrag2.stop() + pass + +@rpc("any_peer", "reliable") +func request_release_pot(pot_path: NodePath, peer_id: int): + if multiplayer.is_server(): + var pot = get_node_or_null(pot_path) + var player = get_tree().get_current_scene().get_node("SpawnRoot").get_node_or_null(str(peer_id)) + if pot and player: + # Check if the pot is being held by this player + if pot.holder_peer_id == peer_id or (pot.holder != null and pot.holder.get_multiplayer_authority() == peer_id): + pot.holder = null + pot.holder_peer_id = 0 + pot.is_being_grabbed = false + pot.velocity = Vector2.ZERO + # Re-enable pot's collision layer when released + pot.set_collision_layer_value(8, true) # Re-enable pot's collision layer + pot.indicate(true) + if $SfxDrag2.playing: + $SfxDrag2.stop() pass func lift(new_holder: CharacterBody2D): - Console.print("Pot lift() called with holder: ", new_holder.name if new_holder else "null") - Console.print("Pot current authority: ", get_multiplayer_authority()) if (new_holder != holder and holder != null) and "lose_held_entity" in holder: # steal from holder holder.lose_held_entity(self) @@ -393,20 +559,15 @@ func lift(new_holder: CharacterBody2D): # Store initial position for smooth lifting - don't change current position yet # The pot will smoothly glide from its current position to above the holder $SfxLand.play() - Console.print("Pot lift() completed, is_being_lifted: ", is_being_lifted) @rpc("any_peer", "reliable") func lift_rpc(holder_path: NodePath): - Console.print("Pot lift_rpc called with holder_path: ", holder_path, " on peer: ", multiplayer.get_unique_id()) # Only execute on server to avoid conflicts if multiplayer.is_server(): # Find the holder by path var holder_node = get_node_or_null(holder_path) if holder_node and holder_node is CharacterBody2D: - Console.print("Pot found holder, calling lift()") lift(holder_node) - else: - Console.print("Pot failed to find holder at path: ", holder_path) func put_down() -> bool: if not is_being_lifted or is_being_put_down: @@ -431,7 +592,6 @@ func put_down() -> bool: var results = space_state.intersect_point(params) if results.size() > 0: # Found overlapping walls at target position - print("Cannot place pot: Wall in the way") return false # Second check: Line of sight between player and target position @@ -446,7 +606,6 @@ func put_down() -> bool: var result = space_state.intersect_ray(query) if result: # Hit something between player and target position - print("Cannot place pot: Path blocked") return false # Third check: Make sure we're not placing on top of another pot or object @@ -454,7 +613,6 @@ func put_down() -> bool: results = space_state.intersect_point(params) if results.size() > 0: # Found overlapping objects at target position - print("Cannot place pot: Object in the way") return false $Area2DCollision.set_deferred("monitoring", false) @@ -554,7 +712,6 @@ func _on_area_2d_collision_body_entered(body: Node2D) -> void: elif collider != self and "breakPot" in collider: collider.take_damage(self, thrown_by) # create particles from pot: - print("ye body is:", body) take_damage.rpc(null, null) pass @@ -583,21 +740,20 @@ func request_grab_pot(pot_path: NodePath, peer_id: int): var player = get_tree().get_current_scene().get_node("SpawnRoot").get_node_or_null(str(peer_id)) if pot and "grab" in pot and player: if pot.grab(player): + # grab() function already disables collisions, but ensure it's done player.grabbed_entity = pot player.grabbed_entity_path = str(pot.get_path()) player.current_animation = "IDLE_PUSH" - # Sync animation and entity to all clients - #var all_players = get_tree().get_current_scene().get_node("SpawnRoot").get_children() - #for p in all_players: - #if p.has_method("sync_animation"): - #p.sync_animation.rpc("IDLE_PUSH") - #p.sync_grabbed_entity.rpc(str(pot.get_path())) + # Lock direction to current last_direction when grabbing + player.locked_grab_direction = player.last_direction + # Sync to all clients (including the joiner who requested it) + player.set_grabbed_entity_path_rpc.rpc(str(pot.get_path())) + player.sync_animation.rpc("IDLE_PUSH") @rpc("any_peer", "reliable") -func request_lift_pot(pot_path: NodePath, peer_id: int): +func request_lift_pot(_pot_path: NodePath, _peer_id: int): # This function is now handled by MultiplayerManager # Keeping it for backward compatibility but it should not be called - print("Pot received request_lift_pot RPC - this should be handled by MultiplayerManager") pass @rpc("any_peer", "reliable") @@ -605,11 +761,9 @@ func request_throw_pot(pot_path: NodePath, peer_id: int, direction: Vector2): if multiplayer.is_server(): var pot = get_node_or_null(pot_path) var player = get_tree().get_current_scene().get_node("SpawnRoot").get_node_or_null(str(peer_id)) - print("Throw request: pot=", pot, " player=", player, " pot.holder_peer_id=", pot.holder_peer_id if pot else "null", " peer_id=", peer_id) if pot and player: # Check if the pot is being held by this player (either by holder_peer_id or by checking the holder directly) if pot.holder_peer_id == peer_id or (pot.holder != null and pot.holder.get_multiplayer_authority() == peer_id): - print("Throw authorized for peer ", peer_id) pot.throw(direction) player.held_entity = null player.held_entity_path = "" @@ -622,8 +776,6 @@ func request_throw_pot(pot_path: NodePath, peer_id: int, direction: Vector2): if p.has_method("sync_animation"): p.sync_animation.rpc("THROW") p.sync_held_entity.rpc("") # Clear held entity - else: - print("Throw denied: holder_peer_id mismatch or holder not found") @rpc("call_local") func take_damage(_iBody: Node2D, _iByWhoOrWhat: Node2D) -> void: @@ -650,7 +802,6 @@ func sync_pot_state(lifted: bool, holder_id: int): holder = null else: holder = null - print("Pot state synced: lifted=", lifted, " holder_id=", holder_id) pass func _on_area_2d_collision_body_exited(_body: Node2D) -> void: diff --git a/src/scripts/entities/world/pot.tscn b/src/scripts/entities/world/pot.tscn index 9f4a838..641c25c 100644 --- a/src/scripts/entities/world/pot.tscn +++ b/src/scripts/entities/world/pot.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=48 format=3 uid="uid://bdlg5orah64m5"] +[gd_scene format=3 uid="uid://bdlg5orah64m5"] [ext_resource type="Script" uid="uid://bj0ueurl3vovc" path="res://scripts/entities/world/pot.gd" id="1_hsjxb"] [ext_resource type="Texture2D" uid="uid://bu4dq78f8lgj5" path="res://assets/gfx/sheet_18.png" id="1_rxnv2"] @@ -104,8 +104,18 @@ _limits = [0.0, 1.0, -1.0, 1.0] _data = [Vector2(-1, 0), 0.0, 0.0, 0, 0, Vector2(0.0124688, 1), 0.0, 0.0, 0, 0, Vector2(0.516209, 1), 0.0, 0.0, 0, 0, Vector2(0.947631, 0), 0.0, 0.0, 0, 0] point_count = 4 +[sub_resource type="Curve" id="Curve_0qg0s"] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="Curve" id="Curve_p028i"] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0] +point_count = 2 + [sub_resource type="CurveXYZTexture" id="CurveXYZTexture_tjjlx"] curve_x = SubResource("Curve_dtubv") +curve_y = SubResource("Curve_0qg0s") +curve_z = SubResource("Curve_p028i") [sub_resource type="Curve" id="Curve_1webc"] _data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(0.0224439, 1), 0.0, 0.0, 0, 0, Vector2(0.880299, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0] @@ -210,20 +220,20 @@ _data = { [sub_resource type="RectangleShape2D" id="RectangleShape2D_nb533"] size = Vector2(14, 10) -[node name="Pot" type="CharacterBody2D"] +[node name="Pot" type="CharacterBody2D" unique_id=364317200] collision_layer = 128 collision_mask = 960 script = ExtResource("1_hsjxb") -[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] +[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="." unique_id=1524006920] replication_config = SubResource("SceneReplicationConfig_hsjxb") -[node name="Sprite2DShadow" type="Sprite2D" parent="."] +[node name="Sprite2DShadow" type="Sprite2D" parent="." unique_id=817113939] z_index = -1 position = Vector2(0, 3) texture = SubResource("GradientTexture2D_87nuj") -[node name="GPUParticles2D" type="GPUParticles2D" parent="."] +[node name="GPUParticles2D" type="GPUParticles2D" parent="." unique_id=779103664] material = SubResource("CanvasItemMaterial_lq20m") emitting = false amount = 16 @@ -236,43 +246,43 @@ use_fixed_seed = true seed = 1565624367 process_material = SubResource("ParticleProcessMaterial_iw3no") -[node name="TimerSmokeParticles" type="Timer" parent="GPUParticles2D"] +[node name="TimerSmokeParticles" type="Timer" parent="GPUParticles2D" unique_id=895713341] wait_time = 0.12 -[node name="Sprite2D" type="Sprite2D" parent="."] +[node name="Sprite2D" type="Sprite2D" parent="." unique_id=720950344] position = Vector2(0, -4) texture = ExtResource("1_rxnv2") hframes = 19 vframes = 19 frame = 14 -[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +[node name="CollisionShape2D" type="CollisionShape2D" parent="." unique_id=1841795873] visible = false position = Vector2(0, -1) shape = SubResource("RectangleShape2D_hsjxb") -[node name="Area2DPickup" type="Area2D" parent="."] +[node name="Area2DPickup" type="Area2D" parent="." unique_id=867581108] visible = false collision_layer = 1024 collision_mask = 512 -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup"] +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DPickup" unique_id=1113571525] position = Vector2(0, -1) shape = SubResource("RectangleShape2D_87nuj") debug_color = Color(0.688142, 0.7, 0.0440007, 0.42) -[node name="SfxShatter" type="AudioStreamPlayer2D" parent="."] +[node name="SfxShatter" type="AudioStreamPlayer2D" parent="." unique_id=301402142] stream = SubResource("AudioStreamRandomizer_ui3li") attenuation = 9.84915 panning_strength = 1.46 bus = &"Sfx" -[node name="SfxDrag" type="AudioStreamPlayer2D" parent="."] +[node name="SfxDrag" type="AudioStreamPlayer2D" parent="." unique_id=955994941] stream = SubResource("AudioStreamRandomizer_wv4em") volume_db = -10.142 bus = &"Sfx" -[node name="SfxDrag2" type="AudioStreamPlayer2D" parent="."] +[node name="SfxDrag2" type="AudioStreamPlayer2D" parent="." unique_id=895274113] stream = SubResource("AudioStreamRandomizer_fvw42") volume_db = -9.703 pitch_scale = 0.77 @@ -281,40 +291,38 @@ attenuation = 10.1965 panning_strength = 1.5 bus = &"Sfx" -[node name="SfxLand" type="AudioStreamPlayer2D" parent="."] +[node name="SfxLand" type="AudioStreamPlayer2D" parent="." unique_id=37979613] stream = SubResource("AudioStreamRandomizer_icnv3") attenuation = 6.9644 panning_strength = 1.25 bus = &"Sfx" -[node name="SfxThrow" type="AudioStreamPlayer2D" parent="."] +[node name="SfxThrow" type="AudioStreamPlayer2D" parent="." unique_id=465813543] stream = ExtResource("21_hd4fl") volume_db = -4.708 pitch_scale = 0.54 bus = &"Sfx" -[node name="SfxDrop" type="AudioStreamPlayer2D" parent="."] +[node name="SfxDrop" type="AudioStreamPlayer2D" parent="." unique_id=1042116419] bus = &"Sfx" -[node name="SfxPickup" type="AudioStreamPlayer2D" parent="."] +[node name="SfxPickup" type="AudioStreamPlayer2D" parent="." unique_id=1755295916] stream = ExtResource("11_lq20m") -[node name="Indicator" type="Sprite2D" parent="."] +[node name="Indicator" type="Sprite2D" parent="." unique_id=1563579882] position = Vector2(0, -11) texture = ExtResource("10_nb533") -[node name="AnimationPlayer" type="AnimationPlayer" parent="Indicator"] -libraries = { -&"": SubResource("AnimationLibrary_76fyq") -} -autoplay = "indicate" +[node name="AnimationPlayer" type="AnimationPlayer" parent="Indicator" unique_id=112267323] +libraries/ = SubResource("AnimationLibrary_76fyq") +autoplay = &"indicate" -[node name="Area2DCollision" type="Area2D" parent="."] +[node name="Area2DCollision" type="Area2D" parent="." unique_id=15533254] visible = false collision_layer = 1024 collision_mask = 704 -[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision"] +[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2DCollision" unique_id=1567360351] position = Vector2(0, -1) shape = SubResource("RectangleShape2D_nb533") debug_color = Color(0.7, 0.132592, 0.232379, 0.42) diff --git a/src/scripts/ui/character_select.gd b/src/scripts/ui/character_select.gd index 3838ac8..a926857 100644 --- a/src/scripts/ui/character_select.gd +++ b/src/scripts/ui/character_select.gd @@ -132,7 +132,7 @@ func _pressCharBut(iCharBut: Button, iIndex: int) -> void: func _on_button_create_pressed() -> void: if characters.size() >= MAX_CHARACTERS: - print("DELETE a characcter, you jhave too many") + pass else: $ControlSelectCharacter/VBoxContainer/ButtonPlay.visible = false $ControlCharacterInfo.visible = true diff --git a/src/scripts/ui/main_menu.gd b/src/scripts/ui/main_menu.gd index d9682a4..615403f 100644 --- a/src/scripts/ui/main_menu.gd +++ b/src/scripts/ui/main_menu.gd @@ -25,7 +25,6 @@ func _connectSuccess(): pass func _on_button_host_pressed() -> void: - Console.print("I am host") MultiplayerManager.host() $CanvasLayer.visible = false self.visible = false @@ -34,7 +33,6 @@ func _on_button_host_pressed() -> void: func _on_button_join_pressed() -> void: - Console.print("I am joiner") MultiplayerManager.join() $CanvasLayer.visible = false self.visible = false