feat: implement player character with state management, network synchronization, and manager integration.
This commit is contained in:
+21
-7
@@ -1933,6 +1933,10 @@ func sync_throw_tekton(target_pos: Vector2i):
|
|||||||
if p.has_method("apply_stagger"):
|
if p.has_method("apply_stagger"):
|
||||||
print("[Throw] Applying stagger to %s" % p.name)
|
print("[Throw] Applying stagger to %s" % p.name)
|
||||||
p.apply_stagger(3.0)
|
p.apply_stagger(3.0)
|
||||||
|
# Apply floor freeze around the stunned player (Radius 0 or 1? "change to 6" implies under them)
|
||||||
|
if tekton.has_method("temporarily_change_floor"):
|
||||||
|
tekton.temporarily_change_floor(Vector2i(p.current_position.x, p.current_position.y), 1, 6, 3.0)
|
||||||
|
|
||||||
NotificationManager.send_message(self , "Stunned " + p.name + "!", NotificationManager.MessageType.WARNING)
|
NotificationManager.send_message(self , "Stunned " + p.name + "!", NotificationManager.MessageType.WARNING)
|
||||||
|
|
||||||
# 2. Tekton drops tiles (Spawn tiles around) AND shrinks
|
# 2. Tekton drops tiles (Spawn tiles around) AND shrinks
|
||||||
@@ -1976,12 +1980,22 @@ func sync_knock_tekton(tekton_path: NodePath):
|
|||||||
if is_multiplayer_authority():
|
if is_multiplayer_authority():
|
||||||
rpc("trigger_screen_shake", "heavy")
|
rpc("trigger_screen_shake", "heavy")
|
||||||
|
|
||||||
func _find_nearby_tekton() -> Node3D:
|
func _find_nearby_tekton() -> Node3D: # Find closest Tekton
|
||||||
|
var closest_tekton = null
|
||||||
|
var min_dist = 9999.0
|
||||||
|
|
||||||
var tektons = get_tree().get_nodes_in_group("Tektons")
|
var tektons = get_tree().get_nodes_in_group("Tektons")
|
||||||
for tekton in tektons:
|
for t in tektons:
|
||||||
if tekton.is_carried: continue
|
if t.is_carried: continue
|
||||||
|
if t.get("is_recovering"): continue # Cannot grab recovering/shrunk Tekton
|
||||||
|
|
||||||
var dist = (tekton.current_position - current_position).length()
|
# Check adjacency (or same tile)
|
||||||
if dist <= 1.5: # Adjacent (1.0 or 1.41)
|
# Assuming is_adjacent_or_same is a helper function that checks if two Vector2i are adjacent or the same.
|
||||||
return tekton
|
# For example: (pos1 - pos2).length_squared() <= 2 (for adjacent or same tile)
|
||||||
return null
|
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)
|
||||||
|
var dist = global_position.distance_to(t.global_position)
|
||||||
|
if dist < min_dist:
|
||||||
|
min_dist = dist
|
||||||
|
closest_tekton = t
|
||||||
|
return closest_tekton
|
||||||
|
|||||||
+15
-4
@@ -145,11 +145,15 @@ func _flash_damage():
|
|||||||
t.tween_property(mesh, "scale", base_scale * 1.2, 0.1)
|
t.tween_property(mesh, "scale", base_scale * 1.2, 0.1)
|
||||||
t.tween_property(mesh, "scale", base_scale, 0.1)
|
t.tween_property(mesh, "scale", base_scale, 0.1)
|
||||||
|
|
||||||
|
var is_recovering: bool = false # True when shrunk/waiting
|
||||||
|
|
||||||
@rpc("any_peer", "call_local", "reliable")
|
@rpc("any_peer", "call_local", "reliable")
|
||||||
func on_thrown_landing(attacker: Node = null):
|
func on_thrown_landing(attacker: Node = null):
|
||||||
"""Called when Tekton lands after being thrown."""
|
"""Called when Tekton lands after being thrown."""
|
||||||
print("[Tekton] Landed! Shrinking and waiting...")
|
print("[Tekton] Landed! Shrinking and waiting...")
|
||||||
|
|
||||||
|
is_recovering = true
|
||||||
|
|
||||||
# Disable movement/interaction logic temporarily
|
# Disable movement/interaction logic temporarily
|
||||||
var controller = get_node_or_null("TektonController")
|
var controller = get_node_or_null("TektonController")
|
||||||
if controller and controller.get("timer"):
|
if controller and controller.get("timer"):
|
||||||
@@ -170,8 +174,8 @@ func on_thrown_landing(attacker: Node = null):
|
|||||||
var t = create_tween()
|
var t = create_tween()
|
||||||
t.tween_property(mesh, "scale", base_scale * 0.5, 0.2).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
|
t.tween_property(mesh, "scale", base_scale * 0.5, 0.2).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
|
||||||
|
|
||||||
# Wait 1 seconds
|
# Wait 3 seconds
|
||||||
await get_tree().create_timer(1.0).timeout
|
await get_tree().create_timer(3.0).timeout
|
||||||
|
|
||||||
# Grow back
|
# Grow back
|
||||||
for i in range(mesh_cache.size()):
|
for i in range(mesh_cache.size()):
|
||||||
@@ -181,6 +185,8 @@ func on_thrown_landing(attacker: Node = null):
|
|||||||
var t = create_tween()
|
var t = create_tween()
|
||||||
t.tween_property(mesh, "scale", base_scale, 0.2).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
|
t.tween_property(mesh, "scale", base_scale, 0.2).set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_BACK)
|
||||||
|
|
||||||
|
is_recovering = false
|
||||||
|
|
||||||
# Resume AI
|
# Resume AI
|
||||||
if controller and controller.has_method("_start_timer"):
|
if controller and controller.has_method("_start_timer"):
|
||||||
if is_multiplayer_authority() and not is_carried:
|
if is_multiplayer_authority() and not is_carried:
|
||||||
@@ -191,9 +197,14 @@ func on_thrown_landing(attacker: Node = null):
|
|||||||
spawn_tiles_around(8) # Standard amount
|
spawn_tiles_around(8) # Standard amount
|
||||||
|
|
||||||
# Floor Freeze (Visual/Instant - Run on all clients locally)
|
# Floor Freeze (Visual/Instant - Run on all clients locally)
|
||||||
_temporarily_change_floor(current_position, 1, 6, 3.0)
|
temporarily_change_floor(current_position, 1, 6, 3.0)
|
||||||
|
|
||||||
|
# Stun nearby players handled by Thrower (Player.gd) or here?
|
||||||
|
# Player.gd handles the stun call because it knows the impact zone context better?
|
||||||
|
# Actually, Player.gd calls this function. Player.gd *also* iterates players to stun them.
|
||||||
|
# That is fine.
|
||||||
|
|
||||||
func _temporarily_change_floor(center: Vector2i, radius: int, new_id: int, duration: float):
|
func temporarily_change_floor(center: Vector2i, radius: int, new_id: int, duration: float):
|
||||||
if not enhanced_gridmap: return
|
if not enhanced_gridmap: return
|
||||||
|
|
||||||
# Run locally on all clients to ensure instant feedback without network delay
|
# Run locally on all clients to ensure instant feedback without network delay
|
||||||
|
|||||||
Reference in New Issue
Block a user