Work on pickups and multiplayer

This commit is contained in:
2026-03-19 23:50:29 -04:00
parent d128501f7c
commit 9d931a3b46
42 changed files with 771 additions and 324 deletions

View File

@@ -65,8 +65,8 @@ func is_multiplayer() -> bool:
return multiplayer_game
func start_level(pawns : Dictionary[int, StringName]) -> void:
pawns_selected = pawns
func start_level(pawn_dict : Dictionary[int, StringName]) -> void:
pawns_selected = pawn_dict
if !Multiplayer.is_host():
return
@@ -135,11 +135,11 @@ func level_spawned(peer_id : int) -> void:
check_level_ready()
func check_level_ready() -> void:
var ready : bool = true
var level_ready : bool = true
for id in level_synced:
if level_synced[id] == false:
ready = false
if ready:
level_ready = false
if level_ready:
level.setup()
func oneshot(stream : AudioStream) -> void:

View File

@@ -81,26 +81,26 @@ func is_server() -> bool:
func is_host() -> bool:
return id == 1
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
if waiting:
var ready : bool = true
var group_ready : bool = true
for pr in player_readiness.values():
if !pr:
ready = false
group_ready = false
break
if ready:
if group_ready:
all_ready.emit()
waiting = false
for pr in player_readiness.keys():
player_readiness[pr] = false
func _add_player_to_game(id : int) -> void:
print("Player %s joined the game!" % id)
func _add_player_to_game(pid : int) -> void:
print("Player %s joined the game!" % pid)
await get_tree().create_timer(0.5).timeout
get_handle_from_peer(id)
get_handle_from_peer(pid)
func _remove_player_from_game(id : int) -> void:
print("Player %s left the game!" % id)
func _remove_player_from_game(pid : int) -> void:
print("Player %s left the game!" % pid)
func get_handle_from_peer(peer_id) -> void:
rpc_id(peer_id, "report_handle_to_peer", id)

17
scripts/collectable.gd Normal file
View File

@@ -0,0 +1,17 @@
class_name Pickup extends Area3D
enum Type{
DATABLOCK,
INTEGRITY,
SCAN,
BASIC_HACK,
ADVANCED_HACK
}
@export var type : Type
func _on_body_entered(body: Node3D) -> void:
if body is PawnController:
body.pickup(type)
queue_free()

View File

@@ -0,0 +1 @@
uid://du3s0b1kotb6l

View File

@@ -10,7 +10,7 @@ func _on_melee_range_changed(melee : bool) -> void:
range_attack_button.visible = !melee
melee_attack_button.visible = melee
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
hack_button.set_pressed_no_signal(Input.is_action_pressed("install"))
detect_button.set_pressed_no_signal(Input.is_action_pressed("detect"))
switch_button.set_pressed_no_signal(Input.is_action_pressed("detonate"))

View File

@@ -47,7 +47,7 @@ var decompiling : bool
var failed : bool
var difficulty : int = 1
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
timer_label.text = "%02f.3" % timer.time_left
func start_decompiling() -> void:
@@ -109,5 +109,5 @@ func succeed() -> void:
func _on_hack_failed() -> void:
fail()
func _on_hack_removed(type : Hack.Type) -> void:
func _on_hack_removed(_type : Hack.Type) -> void:
Game.player.close_modal()

View File

@@ -22,25 +22,25 @@ func _on_timeout() -> void:
func spread() -> void:
var new_squares : Dictionary[Vector3i, bool] = {}
for square in last_spread:
for sq in last_spread:
for i in range(-1, 2):
for j in range(-1, 2):
for k in range(-1, 2):
var ts = square + Vector3i(i, j, k)
new_squares[square + Vector3i(i, j, k)] = true
#var ts = sq + Vector3i(i, j, k)
new_squares[sq + Vector3i(i, j, k)] = true
last_spread = []
for square in new_squares.keys():
if squares.has(square):
for sq in new_squares.keys():
if squares.has(sq):
continue
var floor_square = square + Vector3i(0,-1,0)
var floor_square = sq + Vector3i(0,-1,0)
if(Game.level.floor_layer.get_cell_item(floor_square) == GridMap.INVALID_CELL_ITEM
and Game.level.ramp_layer.get_cell_item(floor_square) == GridMap.INVALID_CELL_ITEM):
continue
last_spread.append(square)
squares[square] = true
emit_gas(square)
last_spread.append(sq)
squares[sq] = true
emit_gas(sq)
func emit_gas(square) -> void:
func emit_gas(sq) -> void:
var gas = gas_square_template.instantiate()
gas.setup(hack_owner, damage)
Game.level.add_vfx(gas, square)
Game.level.add_vfx(gas, sq)

View File

@@ -16,9 +16,9 @@ func _physics_process(delta: float) -> void:
if time_remaining <= 0:
queue_free()
func setup(owner, damage) -> void:
self.hack_owner = hack_owner
self.damage = damage
func setup(h_owner, dam) -> void:
hack_owner = h_owner
damage = dam
time_remaining = 2.0
func _on_body_entered(body: Node3D) -> void:

View File

@@ -26,10 +26,10 @@ const hack_icons : Dictionary = {
Hack.Type.PURGE : preload("res://external/purge-icon.png"),
}
const destroy_explosion_template = preload("res://templates/explosion.tscn")
const purge_explosion_template = preload("res://templates/explosion.tscn")
const destroy_explosion_template = preload("res://experimental/BinbunVFX/impact_explosions/effects/explosion/vfx_explosion_01.tscn")
const purge_explosion_template = preload("res://experimental/BinbunVFX/impact_explosions/effects/explosion/vfx_explosion_03.tscn")
const contain_template = preload("res://templates/pitfall.tscn")
const trigger_explosion_template = preload("res://templates/explosion.tscn")
const trigger_explosion_template = preload("res://experimental/BinbunVFX/impact_explosions/effects/explosion/vfx_explosion_04.tscn")
const infect_emitter_template = preload("res://templates/gas_emitter.tscn")
const force_activate_sound = preload("res://audio/sounds/TomWinandySFX_UI_ScifiTech_Start_06.wav")
@@ -69,13 +69,13 @@ func _enter_tree() -> void:
func _exit_tree() -> void:
Game.level.remove_map_marker(self)
func setup(type : Type, direction : Vector3, hack_owner : int) -> void:
self.type = type
self.hack_owner = hack_owner
func setup(new_type : Type, dir : Vector3, h_owner : int) -> void:
type = new_type
hack_owner = h_owner
if type == Type.REDIRECT:
var r : float = atan2(direction.z, direction.x)
var r : float = atan2(dir.z, dir.x)
var cardinal : float = roundi(r * 2 / PI) * PI / 2
self.direction = Vector3(cos(cardinal), 0, sin(cardinal))
direction = Vector3(cos(cardinal), 0, sin(cardinal))
func remove() -> void:
removed.emit(type)
@@ -127,7 +127,7 @@ func _ready() -> void:
force_strip.rotate_y(r)
force_strip.visible = owns_hack
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
just_revealed = false
func blast(body : PawnController) -> void:
@@ -149,16 +149,16 @@ func activate() -> void:
for body in get_overlapping_bodies():
body.fling(direction, 5.0)
Type.PURGE:
var exp = purge_explosion_template.instantiate()
Game.level.add_vfx(exp, square)
var expl = purge_explosion_template.instantiate()
Game.level.add_vfx(expl, square)
explode = true
Type.TRIGGER:
var exp = trigger_explosion_template.instantiate()
Game.level.add_vfx(exp, square)
var expl = trigger_explosion_template.instantiate()
Game.level.add_vfx(expl, square)
explode = true
Type.DESTROY:
var exp = destroy_explosion_template.instantiate()
Game.level.add_vfx(exp, square)
var expl = destroy_explosion_template.instantiate()
Game.level.add_vfx(expl, square)
explode = true
Type.INFECT:
var emitter = infect_emitter_template.instantiate()
@@ -181,10 +181,10 @@ func trigger_adjacent_bombs() -> void:
if hack.type == Type.DESTROY and hack != self:
hack.delay_trigger()
func generate_contain(square : Vector3i) -> void:
func generate_contain(sq : Vector3i) -> void:
var contain = contain_template.instantiate()
contain.duration = 6.0
Game.level.add_vfx(contain, square)
Game.level.add_vfx(contain, sq)
func blast_players() -> void:
for body in range_area.get_overlapping_bodies():
@@ -206,7 +206,7 @@ func _on_body_entered(body: Node3D) -> void:
return
if !decompiling or body.id != decompile_id:
if !body.detecting:
if !body.is_detecting():
activate()

View File

@@ -17,8 +17,8 @@ func proximal_shake(distance : float) -> void:
var d = global_position.distance_squared_to(Game.player.global_position)
var d_sq = distance * distance
if d <= d_sq:
var str : float = (d_sq - d) / d_sq
var l_val : float = lerp(0.0, 1.0, str)
Input.start_joy_vibration(0, l_val,l_val,lerp(0.5, 1.0, str))
var strength : float = (d_sq - d) / d_sq
var l_val : float = lerp(0.0, 1.0, strength)
Input.start_joy_vibration(0, l_val,l_val,lerp(0.5, 1.0, strength))
Game.player.camera.add_trauma(l_val)

View File

@@ -8,11 +8,11 @@ func _ready() -> void:
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
pass
func _on_health_changed(current : int, max : int) -> void:
max_value = max
func _on_health_changed(current : int, max_amt : int) -> void:
max_value = max_amt
value = current
func _on_poison_status_changed(poisoned : bool) -> void:

View File

@@ -25,6 +25,6 @@ func set_ammo(ammo : int) -> void:
ammo_label.text = str(ammo)
ammo_label.modulate = Color.DIM_GRAY if ammo == 0 else Color.WHITE
func _on_ammo_changed(current : int, max : int) -> void:
func _on_ammo_changed(current : int, _max_amt : int) -> void:
set_ammo(current)

View File

@@ -56,13 +56,13 @@ func spawn_players_singleplayer() -> void:
var pc : PawnController = pawn_controller.instantiate()
pawns[1] = pc
pawns_node.add_child(pc,true)
var position : Vector3
var pos : Vector3
if(spawn_points == null
or len(spawn_points) <= 1):
position = Vector3(0,0,0)
pos = Vector3(0,0,0)
else:
position = spawn_points[0].global_position
pc.global_position = position
pos = spawn_points[0].global_position
pc.global_position = pos
pc.setup(1, Game.pawns_selected[1])
add_pawn_camera(pc)
cameras[1].register_pawn(1)
@@ -83,17 +83,17 @@ func spawn_players_multiplayer() -> void:
for key in pawns:
var pc = pawns[key]
var position : Vector3
var pos : Vector3
if(spawn_points == null
or len(spawn_points) <= count):
if key == Multiplayer.id:
position = Vector3(0,0,0)
pos = Vector3(0,0,0)
else:
position = Vector3(3,0,0)
pos = Vector3(3,0,0)
else:
position = spawn_points[count].global_position
pos = spawn_points[count].global_position
count += 1
pc.global_position = position
pc.global_position = pos
pc.setup.rpc(key, Game.pawns_selected[key])
multiplayer_level_setup.set_players_unready(Multiplayer.players.values())
@@ -198,7 +198,7 @@ func remove_map_marker(target) -> void:
func add_map_marker(target) -> void:
var marker : MapMarker
var height : float
var height : float = 0
if target is PawnController:
marker = map_marker_templates.pawn.instantiate()
height += 40

View File

@@ -2,17 +2,17 @@ class_name MapMarker extends Node3D
var target : Node3D
func register_target(target : Node3D) -> void:
self.target = target
func register_target(new_target : Node3D) -> void:
target = new_target
reposition()
func reposition() -> void:
var loc = target.position
position = Vector3(loc.x, position.y, loc.z)
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
if target:
reposition()
func _on_hack_revealed(is_visible : bool) -> void:
visible = is_visible
func _on_hack_revealed(reveal : bool) -> void:
visible = reveal

View File

@@ -56,7 +56,7 @@ func _on_pawn_spawner_spawned(node: Node) -> void:
func _on_camera_spawner_spawned(node: Node) -> void:
func _on_camera_spawner_spawned(_node: Node) -> void:
cameras_expected -= 1
if cameras_expected == 0:
all_cameras_spawned.emit()

View File

@@ -70,7 +70,7 @@ func _on_joining_back_button_pressed() -> void:
%Joining.visible = false
%Menu.visible = true
func _on_client_added(peer_handle : String, peer_id : int) -> void:
func _on_client_added(peer_handle : String, _peer_id : int) -> void:
%ParticipantsText.text = "[color=FFFF00][b]*%s[/b][/color]\n[color=FFFFFF]*%s[/color]" % [handle, peer_handle]
%StartButton.disabled = false

View File

@@ -48,6 +48,21 @@ func _on_struggle_changed(value : float) -> void:
else:
struggle_bar.value = value
func set_animation_length(node_name : String, length : float) -> void:
if length == 0:
length = 0.01
var blendtree : AnimationNodeBlendTree = anim_tree.tree_root.get_node(node_name)
if !blendtree:
return
var anim_node : AnimationNodeAnimation = blendtree.get_node("Animation")
if !anim_node:
return
var animation : Animation = anim_player.get_animation(anim_node.animation)
if !animation:
return
var a_scale : float = animation.length / length
anim_tree["parameters/%s/TimeScale/scale" % node_name] = a_scale
func _on_footstep_timer_timeout() -> void:
walk_sound.play()

View File

@@ -45,7 +45,7 @@ func _process(delta: float) -> void:
func shake():
noise_y += .1
var amount = pow(trauma, trauma_power)
var n_val = noise.get_noise_2d(noise.seed*2, noise_y)
#var n_val = noise.get_noise_2d(noise.seed*2, noise_y)
h_offset = max_offset.x * amount * randf_range(-1, 1)
v_offset = max_offset.y * amount * randf_range(-1, 1)
print("%f %f" % [h_offset, v_offset])

View File

@@ -2,6 +2,11 @@ class_name PawnController extends CharacterBody3D
enum State {
NORMAL,
DETECTING,
INSTALLING,
UNINSTALLING,
MELEE_ATTACKING,
RANGED_ATTACKING,
KNOCKDOWN,
KNOCKUP,
FLUNG,
@@ -26,7 +31,7 @@ const range_sphere_template = preload("res://templates/range_sphere.tscn")
@onready var detect_sound : AudioStreamPlayer3D = $DetectSound
@onready var fling_sound : AudioStreamPlayer3D = $FlingSound
@onready var crash_sound : AudioStreamPlayer3D = $CrashSound
@onready var reload_sound : AudioStreamPlayer3D = $PawnBody/ReloadSound
@onready var reload_sound : AudioStreamPlayer3D
@onready var detect_icon : Sprite3D = $DetectIcon
@export var id : int = 1
@@ -35,9 +40,6 @@ const range_sphere_template = preload("res://templates/range_sphere.tscn")
var button_actions : Dictionary[int, String]
var current_square : Vector3i
var facing : Vector3
@export var detecting : bool = false
var installing : bool = false
var uninstalling : bool = false
var range_sphere : RangeSphere
var detect_squares : Dictionary[Vector3i, bool] = {}
var detect_tween : Tween = null
@@ -51,18 +53,17 @@ var poison_time_remaining : float = 0
var poison_pulse_timer : float
var melee_range : float = 3.0
var can_melee : bool = false
var ranged_range : float = 6
var attack_timer : float = 0
var melee_recovery_time : float = .75
var ranged_recovery_time : float = .2
var ranged_recovery_time : float = 0.25
var ranged_reload_time : float = 1
var projectile_speed : float = 10.0
var projectile_damage : int = 4
var ammo = 5
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
@@ -98,7 +99,22 @@ func _exit_tree() -> void:
#Game.level.evaluate_outcome()
#Game.evaluate
func calculate_pawn_velocity(dir : Vector3) -> Vector3:
var y = velocity.y
var result = speed * dir
if is_poisoned():
result *= 0.5
if is_crouching():
result *= .33
result.y = y
return result
func play_footsteps(spd : float, loud : bool) -> void:
if loud:
body.play_footsteps(spd)
func stop_footsteps() -> void:
body.stop_footsteps()
func _physics_process(delta: float) -> void:
if attack_timer > 0:
@@ -142,26 +158,16 @@ func _physics_process(delta: float) -> void:
knockdown(-fling_direction)
hurt(10)
moving = false
State.NORMAL:
State.NORMAL, State.DETECTING, State.INSTALLING:
can_fall = true
if dir.length_squared() > 0:
moving = true
velocity = calculate_pawn_velocity(dir)
facing = dir.normalized()
body.look_at(body.global_position - dir)
var y = velocity.y
velocity = speed * dir
if is_poisoned():
velocity *= 0.5
if is_crouching():
velocity *= .33
velocity.y = y
if !detecting:
body.play_footsteps(lerp(.78, .33, dir.length()))
else:
body.stop_footsteps()
elif body != null:
body.stop_footsteps()
play_footsteps(lerp(.78, .33, dir.length()), true)
else:
stop_footsteps()
if body != null:
body.set_animation_parameter("parameters/Motion/blend_position", dir.length())
body.set_animation_parameter("parameters/Crouch/blend_position", dir.length())
@@ -171,12 +177,9 @@ func _physics_process(delta: float) -> void:
else:
moving = true
can_fall = true
State.KNOCKDOWN,State.BOUND,State.DEAD:
return
if can_fall:
var down = 0
if !is_on_floor():
velocity.y = velocity.y + get_gravity().y * delta
moving = true
@@ -184,8 +187,9 @@ func _physics_process(delta: float) -> void:
if moving:
move_and_slide()
if detecting:
if is_detecting():
update_detect_region.rpc(true)
if range_sphere:
update_range_sphere()
#Deal with the rest of the buttons
@@ -200,7 +204,7 @@ func _physics_process(delta: float) -> void:
for button in buttons:
if input.is_action_just_pressed(button):
modal.button_pressed(button)
elif state == State.NORMAL:
else:
update_actions()
@rpc("call_local", "reliable")
@@ -213,15 +217,17 @@ func set_pawn_body(pb : PawnBody) -> void:
body = pb
pb.reloading.connect(reload_ranged)
pb.shooting.connect(fire_ranged)
reload_sound = body.find_child("ReloadSound")
add_child(body)
body.set_animation_length("Ranged Fire", ranged_recovery_time)
struggling.connect(body._on_struggle_changed)
func attack() -> void:
if attack_timer > 0:
return
if meleeing:
body.play_animation.rpc("melee")
if can_melee:
state = State.MELEE_ATTACKING
attack_timer = melee_recovery_time
else:
if ammo <= 0:
@@ -229,14 +235,14 @@ func attack() -> void:
return
attack_timer = ranged_recovery_time
shooting = true
state = State.RANGED_ATTACKING
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()
@@ -245,41 +251,44 @@ func reload_ranged() -> void:
ammo_changed.emit(ammo, max_ammo)
func update_actions() -> void:
if attack_timer <= 0 and shooting and !input.is_action_pressed("attack"):
shooting = false
if state == State.DEAD:
return
if attack_timer <= 0 and is_attacking():
if !input.is_action_pressed("attack"):
state = State.NORMAL
elif is_shooting():
if ammo <= 0:
reloading = true
else:
take_shot = true
if input.is_action_just_pressed("left cycle hack"):
cycle_active_hack(-1)
if input.is_action_just_pressed("right cycle hack"):
cycle_active_hack(1)
if input.is_action_just_pressed("detonate"):
detonate()
elif !installing:
if input.is_action_just_pressed("detect"):
start_detecting()
elif input.is_action_just_released("detect"):
stop_detecting()
if!detecting:
if input.is_action_just_pressed("install"):
installing = true
if range_sphere != null:
range_sphere.queue_free()
range_sphere = range_sphere_template.instantiate()
Game.level.add_child(range_sphere)
#Set the range sphere size based upon the current hack
update_range_sphere()
if input.is_action_just_released("install"):
installing = false
range_sphere.queue_free()
range_sphere = null
try_install_hack()
match(state):
State.NORMAL:
if input.is_action_just_pressed("detonate"):
detonate()
if(input.is_action_just_pressed("detect")
and input.is_action_pressed("detect")):
start_detecting()
return
if(input.is_action_just_pressed("install")
and input.is_action_pressed("install")):
start_installing()
return
elif input.is_action_pressed("attack"):
attack()
elif input.is_action_just_released("install"):
installing = false
range_sphere.queue_free()
range_sphere = null
try_install_hack()
State.DETECTING:
if !input.is_action_pressed("detect"):
stop_detecting()
State.INSTALLING:
if !input.is_action_pressed("install"):
stop_installing()
try_install_hack()
func update_range_sphere() -> void:
var new_pos = (global_position - Vector3.ONE * .5).round() + Vector3(0.5, 0, 0.5)
@@ -324,6 +333,7 @@ func fire_ranged() -> void:
ammo-=1
ammo_changed.emit(ammo, max_ammo)
shot.speed = projectile_speed
shot.id = id
tdir = body.ranged_point.global_position.direction_to(combat_target.global_position) if combat_target else facing
shot.direction = tdir
shot.damage = projectile_damage
@@ -368,10 +378,10 @@ func check_attack_target() -> void:
ranged_closest = target
ranged_d_sq = d_sq
if melee_closest != null:
meleeing = true
can_melee = true
combat_target = melee_closest
else:
meleeing = false
can_melee = false
if ranged_closest != null:
combat_target = ranged_closest
combat_target_changed.emit(melee_closest != null)
@@ -423,21 +433,21 @@ func detect_alert() -> void:
detect_tween.tween_callback(func(): detect_tween = null)
func close_modal() -> void:
uninstalling = false
state = State.NORMAL
if modal != null:
modal.queue_free()
modal = null
func show_uninstall_hack_modal() -> void:
stop_detecting()
uninstalling = true
state = State.UNINSTALLING
modal = uninstall_hack_modal.instantiate()
modal.square = current_square
Game.level.add_child(modal)
func show_decompile_hack_modal() -> void:
stop_detecting()
uninstalling = true
state = State.UNINSTALLING
modal = decompile_hack_modal.instantiate()
modal.difficulty = Game.level.difficulty
modal.square = current_square
@@ -451,8 +461,23 @@ func show_decompile_hack_modal() -> void:
Game.level.add_child(modal)
func start_detecting() -> void:
detecting = true
update_detect_region.rpc(false)
state = State.DETECTING
update_detect_region(false)
func start_installing() -> void:
state = State.INSTALLING
if id == Multiplayer.id:
if range_sphere != null:
range_sphere.queue_free()
range_sphere = range_sphere_template.instantiate()
Game.level.add_child(range_sphere)
#Set the range sphere size based upon the current hack
update_range_sphere()
func stop_installing() -> void:
state = State.NORMAL
range_sphere.queue_free()
range_sphere = null
@rpc("authority", "call_local")
func update_detect_region(update : bool) -> void:
@@ -477,13 +502,14 @@ func update_detect_region(update : bool) -> void:
var remove_list = []
var hack_detected : bool = false
var hack : Hack
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 hack = Game.level.get_square_hack(sq + Vector3i(0,1,0))
hack = Game.level.get_square_hack(sq + Vector3i(0,1,0))
if hack and hack.is_just_revealed():
hack_detected = true
@@ -495,7 +521,7 @@ func update_detect_region(update : bool) -> void:
for key in remove_list:
detect_squares.erase(key)
var hack : Hack = Game.level.get_square_hack(current_square)
hack = Game.level.get_square_hack(current_square)
if hack != null:
if hack.hack_owner == Multiplayer.id:
show_uninstall_hack_modal()
@@ -504,7 +530,7 @@ func update_detect_region(update : bool) -> void:
show_decompile_hack_modal()
func stop_detecting() -> void:
detecting = false
state = State.NORMAL
clear_detect_region.rpc()
@rpc("authority", "call_local")
@@ -516,8 +542,8 @@ func clear_detect_region() -> void:
detect_squares = {}
@rpc("authority", "call_local", "reliable")
func setup(id : int, pawn : StringName) -> void:
self.id = id
func setup(p_id : int, pawn : StringName) -> void:
id = p_id
var base_data : PawnBaseData = Game.pawns[pawn]
var hacklist : Array[PawnLevelData.HackData] = []
for hack in base_data.starting_hacks:
@@ -564,9 +590,11 @@ func hurt(damage : int) -> void:
health_changed.emit(data.life, data.max_life)
if data.life == 0:
die.rpc()
@rpc("any_peer", "call_local")
@rpc("authority", "call_local")
func die() -> void:
state = State.DEAD
body.travel_animation("Death")
input_locked = true
if id == Multiplayer.id:
var death_tween = create_tween()
@@ -578,21 +606,15 @@ func _on_hack_decompiled(type : Hack.Type) -> void:
for i in range(len(data.hacks)):
var d = data.hacks[i]
if d.type == type:
d.max -= 1
d.max_quantity -= 1
hack_quantity_changed.emit(i, d.quantity)
break
#hurt
#blast
#blast_players
#activate
#activate_hack
#fail
#on_hack_failed
func _on_hack_activated(type : Hack.Type) -> void:
for i in range(len(data.hacks)):
var d = data.hacks[i]
if d.type == type:
d.quantity = min(d.max, d.quantity+ 1)
d.quantity = min(d.max_quantity, d.quantity+ 1)
hack_quantity_changed.emit(i, d.quantity)
break
@@ -623,10 +645,10 @@ func poison(damage : int, length : float) -> void:
pshader.set_shader_parameter("strength", 0.5)
poison_status_changed.emit(true)
func fling(direction : Vector3, speed : float) -> void:
func fling(direction : Vector3, spd : float) -> void:
state = State.FLUNG
fling_direction = direction
fling_speed = speed
fling_speed = spd
fling_sound.play()
func knockdown(direction : Vector3) -> void:
@@ -641,14 +663,14 @@ func knockdown(direction : Vector3) -> void:
knockdown_tween.tween_property(self, "input_locked", false, 0)
knockdown_tween.tween_callback(Callable(body.look_at).bind(facing, Vector3(0,1,0)))
func knockup(velocity : Vector3) -> void:
func knockup(vel : Vector3) -> void:
if state != State.KNOCKUP:
state = State.KNOCKUP
input_locked = true
if is_on_floor():
self.velocity = Vector3.UP * .1
velocity = Vector3.UP * .1
move_and_slide()
self.velocity = velocity
velocity = vel
func knockback(direction : Vector3, impact : float) -> void:
if state != State.NORMAL:
@@ -672,14 +694,46 @@ func start_pitfall(square : Vector3, duration : float) -> void:
tween.tween_property(self, "input_locked", false, 0)
tween.tween_callback(pitfall.bind(duration))
func _on_melee_hit(body : Node3D) -> void:
func _on_melee_hit(_body : Node3D) -> void:
#TODO: WRITE THE MELEE DAMAGE CODE
pass
func is_attacking() -> bool:
return state == State.RANGED_ATTACKING or state == State.MELEE_ATTACKING
func is_meleeing() -> bool:
return state == State.MELEE_ATTACKING
func is_shooting() -> bool:
return state == State.RANGED_ATTACKING
func is_dead() -> bool:
return state == State.DEAD
func is_detecting() -> bool:
return detecting
return state == State.DETECTING
func is_installing() -> bool:
return state == State.INSTALLING
func is_uninstalling() -> bool:
return state == State.UNINSTALLING
func is_crouching() -> bool:
return detecting or installing or uninstalling
var result : bool = false
match(state):
State.DETECTING: result = true
State.INSTALLING: result = true
State.UNINSTALLING: result = true
return result
func add_random_hack(advanced : bool) -> void:
#TODO: Add random hack spawning using RPCs
pass
func pickup(type : Pickup.Type) -> void:
if id != Multiplayer.id:
return
match(type):
Pickup.Type.DATABLOCK: print("Datablock picked up!")
Pickup.Type.BASIC_HACK: add_random_hack(false)

View File

@@ -35,5 +35,5 @@ func tv_blur(amount : float) -> void:
var blinder_mat : ShaderMaterial = portrait_blinder.material
blinder_mat.set_shader_parameter("opacity_limit", amount)
func set_pawn_name(name : String) -> void:
pawn_name.text = name
func set_pawn_name(p_name : String) -> void:
pawn_name.text = p_name

View File

@@ -32,7 +32,7 @@ func _ready() -> void:
"attack":false
}
func _physics_process(delta: float) -> void:
func _physics_process(_delta: float) -> void:
if get_multiplayer_authority() != Multiplayer.id:
return
var d = Input.get_vector("west", "east", "north", "south")

View File

@@ -3,12 +3,12 @@ class_name PawnLevelData extends Node
class HackData:
var type : Hack.Type
var quantity : int
var max : int
var max_quantity : int
func _init(type : Hack.Type, quantity : int, max : int) -> void:
self.type = type
self.quantity = quantity
self.max = max
func _init(new_type : Hack.Type, amt : int, max_amt : int) -> void:
type = new_type
quantity = amt
max_quantity = max_amt
var hacks : Array[HackData] = []
var active_hack : int = 0

View File

@@ -1,23 +1,24 @@
class_name Projectile extends RigidBody3D
class_name Projectile extends Area3D
var id : int = 0
var direction : Vector3
var speed : float
var friend_safe : bool = true
var damage
var time_remaining : float
func _ready() -> void:
linear_velocity = speed * direction
time_remaining = 2
func _physics_process(delta: float) -> void:
global_position += speed * direction * delta
time_remaining -= delta
if time_remaining <= 0:
queue_free()
func _on_body_entered(body: Node) -> void:
queue_free()
func _on_hit_area_entered(body: Node3D) -> void:
if body is PawnController:
body.hurt(damage)
if !friend_safe or id != body.id:
body.hurt(damage)
queue_free()
else:
queue_free()

View File

@@ -15,8 +15,7 @@ var type : Hack.Type = -1
rim_sphere.radius = _radius
if intersect_sphere != null:
intersect_sphere.radius = _radius
func set_range(range : float) -> void:
radius = range
func set_range(new_radius : float) -> void:
radius = new_radius

View File

@@ -56,7 +56,7 @@ func _ready() -> void:
glow_tween.tween_property(target, "modulate:a", .8, .5)
glow_tween.tween_property(target, "modulate:a", 1, .5)
func _process(delta: float) -> void:
func _process(_delta: float) -> void:
if Input.is_action_just_pressed("ui_menu"):
opened = !opened
start.visible = !opened