Pawn bodies split out, character select redesigned, and started the dreaded process of correcting the netcode. Players can connect to a shared room, character select, and start a match. They appear correctly differentiated with cameras and map icons that follow them independently. Jankiness with trap ownership is present as is stuff connected to animation. Unit tests for all network functionality required.

This commit is contained in:
2026-03-10 01:41:15 -04:00
parent 984567cf96
commit d128501f7c
52 changed files with 1179 additions and 929 deletions

View File

@@ -15,9 +15,10 @@ const hack_template = preload("res://templates/hack.tscn")
const uninstall_hack_modal = preload("res://templates/uninstall_hack_modal.tscn")
const decompile_hack_modal = preload("res://templates/decompile_hack_modal.tscn")
const range_sphere_template = preload("res://templates/range_sphere.tscn")
@export var pawn_name : StringName
@export var speed : float = 10
@onready var body : PawnBody = $PawnBody
@onready var body : PawnBody
@onready var input : PawnInput = $PawnInput
@onready var data : PawnLevelData = $Data
@onready var hack_sound : AudioStreamPlayer3D = $HackSound
@@ -28,7 +29,7 @@ const range_sphere_template = preload("res://templates/range_sphere.tscn")
@onready var reload_sound : AudioStreamPlayer3D = $PawnBody/ReloadSound
@onready var detect_icon : Sprite3D = $DetectIcon
var id : int = 1
@export var id : int = 1
@export var state : State
var button_actions : Dictionary[int, String]
@@ -62,6 +63,8 @@ var max_ammo = 5
var combat_target
var meleeing : bool = false
var shooting : bool = false
var reloading : bool = false
var take_shot : bool = false
var flinch : float = 0
@@ -95,6 +98,8 @@ func _exit_tree() -> void:
#Game.level.evaluate_outcome()
#Game.evaluate
func _physics_process(delta: float) -> void:
if attack_timer > 0:
attack_timer -= delta
@@ -155,10 +160,11 @@ func _physics_process(delta: float) -> void:
body.play_footsteps(lerp(.78, .33, dir.length()))
else:
body.stop_footsteps()
else:
elif body != null:
body.stop_footsteps()
body.set_animation_parameter("parameters/Motion/blend_position", dir.length())
body.set_animation_parameter("parameters/Crouch/blend_position", dir.length())
if body != null:
body.set_animation_parameter("parameters/Motion/blend_position", dir.length())
body.set_animation_parameter("parameters/Crouch/blend_position", dir.length())
State.KNOCKUP:
if is_on_floor():
knockdown(facing)
@@ -197,6 +203,20 @@ func _physics_process(delta: float) -> void:
elif state == State.NORMAL:
update_actions()
@rpc("call_local", "reliable")
func setup_pawn_body(pd : PawnBaseData) -> void:
set_pawn_body(pd.pawn_body.instantiate())
func set_pawn_body(pb : PawnBody) -> void:
if body != null:
body.queue_free()
body = pb
pb.reloading.connect(reload_ranged)
pb.shooting.connect(fire_ranged)
add_child(body)
struggling.connect(body._on_struggle_changed)
func attack() -> void:
if attack_timer > 0:
return
@@ -205,22 +225,25 @@ func attack() -> void:
attack_timer = melee_recovery_time
else:
if ammo <= 0:
reload_sound.play()
ammo = max_ammo
attack_timer = ranged_reload_time
ammo_changed.emit(ammo, max_ammo)
reloading = true
return
ammo-=1
ammo_changed.emit(ammo, max_ammo)
attack_timer = ranged_recovery_time
shooting == true
shooting = true
take_shot = true
if combat_target != null:
var v = body.global_position.direction_to(combat_target.global_position)
v.y = 0
body.look_at(body.global_position - v)
func reload_ranged() -> void:
reloading = false
reload_sound.play()
ammo = max_ammo
attack_timer = ranged_reload_time
ammo_changed.emit(ammo, max_ammo)
func update_actions() -> void:
if attack_timer <= 0 and shooting and !input.is_action_pressed("attack"):
shooting = false
@@ -297,6 +320,9 @@ func update_poison(delta : float) -> void:
func fire_ranged() -> void:
var shot = body.projectile_template.instantiate()
var tdir : Vector3 = Vector3.ZERO
take_shot = false
ammo-=1
ammo_changed.emit(ammo, max_ammo)
shot.speed = projectile_speed
tdir = body.ranged_point.global_position.direction_to(combat_target.global_position) if combat_target else facing
shot.direction = tdir
@@ -490,15 +516,15 @@ func clear_detect_region() -> void:
detect_squares = {}
@rpc("authority", "call_local", "reliable")
func setup(id : int, hacks : Array, pos : Vector3) -> void:
func setup(id : int, pawn : StringName) -> void:
self.id = id
self.global_position = pos
var base_data : PawnBaseData = Game.pawns[pawn]
var hacklist : Array[PawnLevelData.HackData] = []
for hack in hacks:
for hack in base_data.starting_hacks:
hacklist.append(PawnLevelData.HackData.new(hack.type, hack.qty, hack.qty))
$Data.hacks = hacklist
input.set_multiplayer_authority(id)
struggling.connect(body._on_struggle_changed)
setup_pawn_body(base_data)
Game.setup_player(self)
func uninstall_hack_at(square) -> void: