fix: a lot of network sync fixes

This commit is contained in:
DottsGit
2026-06-06 20:45:10 -04:00
parent dbbfbef4a4
commit 07a15fe998
8 changed files with 179 additions and 91 deletions
+86 -48
View File
@@ -1,13 +1,14 @@
extends Area3D
class_name CombatArea
var time_left: float = 5.0
var time_safe: float = 0.0
var out_of_bounds_players: Dictionary = {} # body -> { time_left: 5.0 }
var recovery_players: Dictionary = {} # body -> { time_safe: 0.0, time_left: float }
var _player_out_of_bounds: Node3D = null
var _ui_layer: CanvasLayer = null
var _ui_label: Label = null
var _ui_overlay: ColorRect = null
var _is_local_player_out: bool = false
var _local_player_body: Node3D = null
func _ready() -> void:
collision_layer = 0
@@ -17,50 +18,85 @@ func _ready() -> void:
set_process(false)
func _process(delta: float) -> void:
if _player_out_of_bounds:
# If the player dies while out of bounds, stop the timer and remove the UI
if "is_dead" in _player_out_of_bounds and _player_out_of_bounds.is_dead:
_player_out_of_bounds = null
_remove_ui()
return
# Process players who are actively out of bounds
var to_kill: Array = []
for body in out_of_bounds_players.keys():
if "is_dead" in body and body.is_dead:
out_of_bounds_players.erase(body)
if body == _local_player_body:
_remove_ui()
continue
var data = out_of_bounds_players[body]
data.time_left -= delta
if data.time_left <= 0.0:
data.time_left = 0.0
to_kill.append(body)
if body == _local_player_body and _is_local_player_out and _ui_label and _ui_overlay:
_ui_label.text = "WARNING: RETURN TO COMBAT AREA\n%.1f" % data.time_left
_ui_overlay.color = Color(1.0, 0.0, 0.0, 0.8 * (1.0 - (data.time_left / 5.0)))
for body in to_kill:
_kill_player(body)
# Player is outside the combat area!
time_left -= delta
if time_left <= 0.0:
time_left = 0.0
_kill_player()
# Process players who returned but are recovering
var recovered: Array = []
for body in recovery_players.keys():
if "is_dead" in body and body.is_dead:
recovered.append(body)
continue
var data = recovery_players[body]
data.time_safe += delta
if data.time_safe >= 10.0:
recovered.append(body)
for body in recovered:
recovery_players.erase(body)
# Update UI
if _ui_label and _ui_overlay:
_ui_label.text = "WARNING: RETURN TO COMBAT AREA\n%.1f" % time_left
_ui_overlay.color = Color(1.0, 0.0, 0.0, 0.8 * (1.0 - (time_left / 5.0)))
else:
# Player is inside the combat area, but might have a damaged timer
if time_left < 5.0:
time_safe += delta
if time_safe >= 10.0:
time_left = 5.0
time_safe = 0.0
set_process(false) # Fully recovered, sleep
if out_of_bounds_players.is_empty() and recovery_players.is_empty():
set_process(false)
func _on_body_exited(body: Node3D) -> void:
if body.name == "Player":
# Don't trigger if the player is already dead or the scene is tearing down
if body is CharacterBody3D and body.has_method("take_damage") and str(body.name).is_valid_int():
if "is_dead" in body and body.is_dead:
return
if body.is_queued_for_deletion() or not is_inside_tree():
return
_player_out_of_bounds = body
time_safe = 0.0 # Reset recovery timer
_create_ui()
var start_time = 5.0
if recovery_players.has(body):
start_time = recovery_players[body].time_left
recovery_players.erase(body)
out_of_bounds_players[body] = { "time_left": start_time }
var is_local = false
if multiplayer.has_multiplayer_peer():
if body.get_multiplayer_authority() == multiplayer.get_unique_id():
is_local = true
if is_local:
_is_local_player_out = true
_local_player_body = body
_create_ui()
set_process(true)
func _on_body_entered(body: Node3D) -> void:
if body == _player_out_of_bounds:
_player_out_of_bounds = null
_remove_ui()
# set_process(true) stays on to tick the time_safe recovery
if out_of_bounds_players.has(body):
var time_left_val = out_of_bounds_players[body].time_left
out_of_bounds_players.erase(body)
if time_left_val < 5.0:
recovery_players[body] = { "time_left": time_left_val, "time_safe": 0.0 }
set_process(true)
if body == _local_player_body and _is_local_player_out:
_remove_ui()
_is_local_player_out = false
_local_player_body = null
func _create_ui() -> void:
if _ui_layer: return
@@ -83,7 +119,10 @@ func _create_ui() -> void:
_ui_label.add_theme_color_override("font_color", Color(1, 0.2, 0.2))
_ui_label.add_theme_color_override("font_outline_color", Color(0, 0, 0))
_ui_label.add_theme_constant_override("outline_size", 8)
_ui_label.text = "WARNING: RETURN TO COMBAT AREA\n%.1f" % time_left
var display_time = 5.0
if out_of_bounds_players.has(_local_player_body):
display_time = out_of_bounds_players[_local_player_body].time_left
_ui_label.text = "WARNING: RETURN TO COMBAT AREA\n%.1f" % display_time
_ui_layer.add_child(_ui_label)
@@ -97,15 +136,14 @@ func _remove_ui() -> void:
_ui_label = null
_ui_overlay = null
func _kill_player() -> void:
if _player_out_of_bounds:
# PlayerMovementController's take_damage requires (amount, source)
if _player_out_of_bounds.has_method("take_damage"):
_player_out_of_bounds.take_damage(9999, Vector3.ZERO)
elif "health" in _player_out_of_bounds:
_player_out_of_bounds.health = 0
if "is_dead" in _player_out_of_bounds:
_player_out_of_bounds.is_dead = true
_player_out_of_bounds = null
_remove_ui()
func _kill_player(body: Node3D) -> void:
if body:
if multiplayer.is_server():
if body.has_method("take_damage"):
body.take_damage(9999, Vector3.ZERO, null, Vector3.ZERO)
out_of_bounds_players.erase(body)
if body == _local_player_body and _is_local_player_out:
_remove_ui()
_is_local_player_out = false
_local_player_body = null
+7 -8
View File
@@ -39,7 +39,7 @@ func _ready() -> void:
_update_label()
func take_damage(amount: float, hit_position: Vector3, source: Node = null, impulse: Vector3 = Vector3.ZERO) -> void:
func take_damage(amount: float, hit_position: Vector3, source: Node = null, _impulse: Vector3 = Vector3.ZERO) -> void:
if is_dead:
return
@@ -141,14 +141,13 @@ func _die(_hit_position: Vector3, source: Node, damage_amount: float) -> void:
linear_vel = hit_dir * (damage_amount * 0.02)
impulse = hit_dir * (damage_amount * 0.5)
get_tree().create_timer(0.01).timeout.connect(func():
if is_instance_valid(ragdoll_instance):
ragdoll_instance.apply_initial_velocities(linear_vel, impulse)
)
get_tree().create_timer(0.01).timeout.connect(_apply_ragdoll_velocity.bind(ragdoll_instance, linear_vel, impulse))
get_tree().create_timer(3.0).timeout.connect(func():
_respawn()
)
get_tree().create_timer(3.0).timeout.connect(_respawn)
func _apply_ragdoll_velocity(ragdoll: Node3D, l_vel: Vector3, imp: Vector3) -> void:
if is_instance_valid(ragdoll):
ragdoll.apply_initial_velocities(l_vel, imp)
func _respawn() -> void:
if is_instance_valid(ragdoll_instance):
+6 -8
View File
@@ -185,15 +185,13 @@ func _die(_hit_position: Vector3, source: Node, damage_amount: float) -> void:
linear_vel = hit_dir * (damage_amount * 0.02)
impulse = hit_dir * (damage_amount * 0.5)
get_tree().create_timer(0.01).timeout.connect(func():
if is_instance_valid(ragdoll_instance):
# The ragdoll also inherits the current walking velocity natively
ragdoll_instance.apply_initial_velocities(velocity + linear_vel, impulse)
)
get_tree().create_timer(0.01).timeout.connect(_apply_ragdoll_velocity.bind(ragdoll_instance, velocity + linear_vel, impulse))
get_tree().create_timer(3.0).timeout.connect(func():
_respawn()
)
get_tree().create_timer(3.0).timeout.connect(_respawn)
func _apply_ragdoll_velocity(ragdoll: Node3D, l_vel: Vector3, imp: Vector3) -> void:
if is_instance_valid(ragdoll):
ragdoll.apply_initial_velocities(l_vel, imp)
func _respawn() -> void:
if is_instance_valid(ragdoll_instance):