More work on maps and multiplayer

This commit is contained in:
2026-01-15 11:10:12 -05:00
parent dc8585b1f0
commit bc48e9cea2
25 changed files with 3740 additions and 136 deletions

View File

@@ -15,6 +15,7 @@ const disarm_trap_modal = preload("res://templates/disarm_trap_modal.tscn")
@export var speed : float = 10
@onready var body : PawnBody = $PawnBody
@onready var input : PawnInput = $PawnInput
@onready var data : PawnLevelData = $Data
@onready var trap_sound : AudioStreamPlayer3D = $TrapSound
@onready var detonate_sound : AudioStreamPlayer3D = $DetonateSound
@@ -26,11 +27,11 @@ const disarm_trap_modal = preload("res://templates/disarm_trap_modal.tscn")
var id : int = 1
var state : State
@export var state : State
var button_actions : Dictionary[int, String]
var current_square : Vector3i
var facing : Vector3
var detecting : bool = false
@export var detecting : bool = false
var detect_squares : Dictionary[Vector3i, bool] = {}
var detect_tween : Tween = null
var fling_direction : Vector3
@@ -77,32 +78,14 @@ func _physics_process(delta: float) -> void:
if attack_timer > 0:
attack_timer -= delta
check_attack_target()
if is_poisoned():
poison_time_remaining -= delta
poison_pulse_timer += delta
if poison_pulse_timer >= 1.0:
poison_pulse_timer -= 1.0
hurt(poison_strength)
if poison_time_remaining <= 0:
var pshader : ShaderMaterial = body.material.next_pass
pshader.set_shader_parameter("strength", 0)
poison_status_changed.emit(false)
var dir = Input.get_vector("west", "east", "north", "south")
dir = Vector3(dir.x, 0, dir.y)
if struggle_timer > 0:
struggle_timer -= delta
var snapped_angle = round(dir.angle_to(Vector3(1,0,0)) * 4 / PI) * PI * .25
if abs(snapped_angle - struggle_angle) >= PI * .25:
struggle_angle = snapped_angle
struggle_timer -= 2 * delta
struggling.emit(struggle_timer)
if struggle_timer <= 0:
hurt(1)
knockdown(facing)
else:
return
update_poison(delta)
if !update_struggle(delta):
return
var dir = input.dir
if input_locked or modal != null:
dir = Vector3.ZERO
@@ -163,12 +146,11 @@ func _physics_process(delta: float) -> void:
move_and_slide()
if detecting:
update_detecting()
update_detect_region.rpc(true)
#Deal with the rest of the buttons
if !input_locked:
if modal:
var evt = InputEventAction.new()
var buttons = [
"lay trap",
"detect",
@@ -176,31 +158,16 @@ func _physics_process(delta: float) -> void:
"detonate"
]
for button in buttons:
if Input.is_action_just_pressed(button):
evt.action = button
evt.pressed = true
modal.button_pressed(evt)
if input.is_action_just_pressed(button):
modal.button_pressed(button)
elif state == State.NORMAL:
if Input.is_action_just_pressed("left cycle trap"):
cycle_active_trap(-1)
if Input.is_action_just_pressed("right cycle trap"):
cycle_active_trap(1)
if Input.is_action_just_pressed("detonate"):
detonate()
elif Input.is_action_just_pressed("detect"):
start_detecting()
elif Input.is_action_just_released("detect"):
stop_detecting()
elif !detecting and Input.is_action_just_pressed("lay trap"):
try_lay_trap()
elif Input.is_action_pressed("attack"):
attack()
update_actions()
func attack() -> void:
if attack_timer > 0:
return
if meleeing:
body.play_animation("melee")
body.play_animation.rpc("melee")
attack_timer = melee_recovery_time
else:
if ammo <= 0:
@@ -219,6 +186,50 @@ func attack() -> void:
v.y = 0
body.look_at(body.global_position - v)
func update_actions() -> void:
if input.is_action_just_pressed("left cycle trap"):
cycle_active_trap(-1)
if input.is_action_just_pressed("right cycle trap"):
cycle_active_trap(1)
if input.is_action_just_pressed("detonate"):
detonate()
elif input.is_action_just_pressed("detect"):
start_detecting()
elif input.is_action_just_released("detect"):
stop_detecting()
elif !detecting and input.is_action_just_pressed("lay trap"):
try_lay_trap()
elif input.is_action_pressed("attack"):
attack()
func update_struggle(delta : float) -> bool:
if struggle_timer > 0:
struggle_timer -= delta
var snapped_angle = round(input.dir.angle_to(Vector3(1,0,0)) * 4 / PI) * PI * .25
if abs(snapped_angle - struggle_angle) >= PI * .25:
struggle_angle = snapped_angle
struggle_timer -= 2 * delta
struggling.emit(struggle_timer)
if struggle_timer <= 0:
hurt(1)
knockdown(facing)
else:
return false
return true
func update_poison(delta : float) -> void:
if is_poisoned():
poison_time_remaining -= delta
poison_pulse_timer += delta
if poison_pulse_timer >= 1.0:
poison_pulse_timer -= 1.0
hurt(poison_strength)
if poison_time_remaining <= 0:
var pshader : ShaderMaterial = body.material.next_pass
pshader.set_shader_parameter("strength", 0)
poison_status_changed.emit(false)
func fire_ranged() -> void:
var shot = body.projectile_template.instantiate()
var tdir : Vector3 = Vector3.ZERO
@@ -308,52 +319,6 @@ func clear_action() -> void:
input_locked = false
action_tween = null
func update_detecting() -> void:
var new_square : Vector3i = (global_position - Vector3.ONE * .5).round()
if new_square == current_square:
return
current_square = new_square
var new_squares : Dictionary[Vector3i, bool] = {}
for i in range(-2, 3):
for j in range(-2, 3):
for k in range(-2, 2):
if abs(i) + abs(j) < 3:
var sq = current_square + Vector3i(i, k, j)
new_squares[sq] = true
for sq in detect_squares.keys():
if !new_squares.has(sq):
Game.level.detect_square(sq, false)
var remove_list = []
var trap_detected : bool = false
for sq in new_squares.keys():
if detect_squares.has(sq):
continue
if !Game.level.detect_square(sq, true):
remove_list.append(sq)
else:
var trap = Game.level.get_square_trap(sq + Vector3i(0,1,0))
if trap and trap.is_just_revealed():
trap_detected = true
if trap_detected:
detect_alert()
detect_squares = new_squares
for key in remove_list:
detect_squares.erase(key)
var trap : Trap = Game.level.get_square_trap(current_square)
if trap != null:
if trap.trap_owner == Multiplayer.id:
show_remove_trap_modal()
else:
trap.disarming = true
show_disarm_trap_modal()
func detect_alert() -> void:
detect_sound.play()
@@ -392,26 +357,44 @@ func show_disarm_trap_modal() -> void:
func start_detecting() -> void:
detecting = true
current_square = (global_position - Vector3.ONE * .5).round()
detect_squares = {}
update_detect_region.rpc(false)
@rpc("authority")
func update_detect_region(update : bool) -> void:
var new_square : Vector3i = (global_position - Vector3.ONE * .5).round()
if update and new_square == current_square:
return
current_square = new_square
var new_squares : Dictionary[Vector3i, bool] = {}
for i in range(-2, 3):
for j in range(-2, 3):
for k in range(-2, 2):
if abs(i) + abs(j) < 3:
var sq = current_square + Vector3i(i, k, j)
detect_squares[sq] = true
new_squares[sq] = true
if update:
for sq in detect_squares.keys():
if !new_squares.has(sq):
Game.level.detect_square(sq, false)
var remove_list = []
var trap_detected : bool = false
for sq in detect_squares.keys():
for sq in new_squares.keys():
if update and detect_squares.has(sq):
continue
if !Game.level.detect_square(sq, true):
remove_list.append(sq)
else:
var trap = Game.level.get_square_trap(sq + Vector3i(0,1,0))
if trap and trap.is_just_revealed():
trap_detected = true
if trap_detected:
detect_alert()
detect_squares = new_squares
for key in remove_list:
detect_squares.erase(key)
@@ -419,9 +402,16 @@ func start_detecting() -> void:
if trap != null:
if trap.trap_owner == Multiplayer.id:
show_remove_trap_modal()
else:
trap.disarming = true
show_disarm_trap_modal()
func stop_detecting() -> void:
detecting = false
clear_detect_region()
@rpc("authority")
func clear_detect_region() -> void:
for sq in detect_squares.keys():
Game.level.detect_square(sq, false)
detect_squares = {}
@@ -434,7 +424,7 @@ func setup(id : int, traps : Array, pos : Vector3) -> void:
for trap in traps:
traplist.append(PawnLevelData.TrapData.new(trap.type, trap.qty, trap.qty))
$Data.traps = traplist
set_multiplayer_authority(id)
input.set_multiplayer_authority(id)
struggling.connect(body._on_struggle_changed)
Game.setup_player(self)