t_p1_hitscan: Add lag-compensated hitscan weapon system
NEW: server/scripts/combat/lag_compensation.gd
- 128-entry ring buffer of player positions per server tick
- rewind_and_raycast(tick, origin, direction, range, exclude):
saves current positions, rewinds to tick-time positions,
performs PhysicsDirectSpaceState3D.intersect_ray(), restores
- Falls back to normal raycast if history missing for tick
- shot_processed signal
NEW: scripts/combat/damage_processor.gd
- Processes WeaponServer hit results: applies damage, tracks kills
- Optional distance-based damage falloff
- player_damaged / player_killed signals
- Health and kill-count queries
MODIFY: server/scripts/weapons/weapon_server.gd
- fire() now takes tick parameter: fire(tick, player_id, ...)
- _perform_hitscan() uses LagCompensation.rewind_and_raycast()
when lag_compensation reference is set and tick >= 0
- Non-compensated fallback path preserved
MODIFY: server/scripts/game_server.gd
- Adds _current_tick counter, incremented each simulation tick
- Creates WeaponServer + LagCompensation + DamageProcessor as children
- record_tick() called before each tick's simulation
- register/unregister_player_node() for player lifecycle
- _on_player_killed() relays kill events via player_damaged signal
MODIFY: scripts/network/server_main.gd
- _spawn_player() registers node with GameServer.register_player_node()
- _despawn_player() unregisters via unregister_player_node()
This commit is contained in:
@@ -171,6 +171,10 @@ func _spawn_player(peer_id: int) -> void:
|
||||
if entity_id >= 0:
|
||||
# Store entity_id on player node for reference
|
||||
player.set_meta(&"entity_id", entity_id)
|
||||
# Register with lag compensation and damage processor
|
||||
# (player is a Node3D, which is a valid argument for register_player_node)
|
||||
if _game_server.has_method(&"register_player_node"):
|
||||
_game_server.register_player_node(entity_id, player)
|
||||
print("[ServerMain] Player %d assigned entity %d" % [peer_id, entity_id])
|
||||
|
||||
# Broadcast spawn to all clients so they create a visual player node
|
||||
@@ -185,6 +189,9 @@ func _despawn_player(peer_id: int) -> void:
|
||||
# Despawn entity from GameServer
|
||||
if _game_server != null and player.has_meta(&"entity_id"):
|
||||
var entity_id: int = player.get_meta(&"entity_id")
|
||||
# Unregister from lag compensation and damage processor first
|
||||
if _game_server.has_method(&"unregister_player_node"):
|
||||
_game_server.unregister_player_node(entity_id)
|
||||
_game_server.despawn_player_entity(entity_id)
|
||||
|
||||
player.queue_free()
|
||||
|
||||
Reference in New Issue
Block a user