diff --git a/scenes/player.gd b/scenes/player.gd index 1888fc6..9203016 100644 --- a/scenes/player.gd +++ b/scenes/player.gd @@ -751,7 +751,7 @@ func _apply_tint_recursive(node: Node, color: Color): var immunity_timer: float = 0.0 var tekton_carry_timer: float = 0.0 -const MAX_TEKTON_CARRY_TIME: float = 3.0 +const MAX_TEKTON_CARRY_TIME: float = 4.0 @rpc("any_peer", "call_local") @@ -2139,12 +2139,58 @@ func grab_tekton(): if not is_multiplayer_authority() or is_carrying_tekton or is_frozen or is_stop_frozen: return - # Find nearby Tekton + # 1. Check for nearby carrier to snatch from + var carrier = _find_nearby_carrier() + if carrier: + snatch_tekton(carrier) + return + + # 2. Find nearby roaming Tekton var tekton = _find_nearby_tekton() if tekton: if is_multiplayer_authority() and can_rpc(): rpc("sync_grab_tekton", tekton.get_path()) +func snatch_tekton(target_carrier: Node3D): + if not is_multiplayer_authority() or not target_carrier.is_carrying_tekton: + return + + var tekton = target_carrier.carried_tekton + if tekton: + if is_multiplayer_authority() and can_rpc(): + rpc("sync_snatch_tekton", target_carrier.get_path(), tekton.get_path()) + +@rpc("any_peer", "call_local", "reliable") +func sync_snatch_tekton(carrier_path: NodePath, tekton_path: NodePath): + var carrier = get_node_or_null(carrier_path) + var tekton = get_node_or_null(tekton_path) + if carrier and tekton: + # Security: ensure multiple people don't think they are carrying it + # Transfer logic + carrier.is_carrying_tekton = false + carrier.carried_tekton = null + + self.is_carrying_tekton = true + self.carried_tekton = tekton + tekton.set_carried(true, self) + + # Reset my carry timer (3s rule starts fresh) + tekton_carry_timer = 0.0 + + # Visual/Logic side effects + if is_attack_mode: + is_attack_mode = false + + SfxManager.play("pick_up_tekton_roaming") + play_pickup_animation() + + # Visual feedback for the victim + if carrier.has_method("sync_bump"): + # Bump away from the snatcher + carrier.sync_bump(current_position, true) + + print("[Player %s] SNATCHED Tekton from %s" % [name, carrier.name]) + @rpc("any_peer", "call_local", "reliable") func sync_grab_tekton(tekton_path: NodePath): var tekton = get_node_or_null(tekton_path) @@ -2409,8 +2455,6 @@ func _find_nearby_tekton() -> Node3D: # Find closest Tekton if t.get("is_recovering"): continue # Cannot grab recovering/shrunk Tekton if t.get("is_static_turret"): continue # Cannot grab/knock static turret - # Check adjacency (or same tile) - # Assuming is_adjacent_or_same is a helper function that checks if two Vector2i are adjacent or the same. # For example: (pos1 - pos2).length_squared() <= 2 (for adjacent or same tile) var dist_grid = (t.current_position - current_position).length() if dist_grid <= 1.5: # Adjacent (1.0 or 1.41) or same tile (0.0) @@ -2419,3 +2463,15 @@ func _find_nearby_tekton() -> Node3D: # Find closest Tekton min_dist = dist closest_tekton = t return closest_tekton + +func _find_nearby_carrier() -> Node3D: + """Find a nearby player who is carrying a Tekton.""" + var players = get_tree().get_nodes_in_group("Players") + for p in players: + if p == self: continue + if p.is_carrying_tekton: + # Check adjacency or same tile + var dist = Vector2(p.current_position.x, p.current_position.y).distance_to(Vector2(current_position.x, current_position.y)) + if dist <= 1.5: + return p + return null