weapon system rework
This commit is contained in:
parent
0ffc2b2497
commit
30b01100f0
27 changed files with 352 additions and 190 deletions
Binary file not shown.
|
|
@ -1,10 +1,48 @@
|
|||
[gd_scene load_steps=5 format=3 uid="uid://cqrh2cc7m2i7f"]
|
||||
[gd_scene load_steps=8 format=3 uid="uid://cqrh2cc7m2i7f"]
|
||||
|
||||
[ext_resource type="Environment" uid="uid://d0cfgtx2yxw13" path="res://environments/prototype_environment.tres" id="1_i6jab"]
|
||||
[ext_resource type="Script" uid="uid://ypgm3aplt78m" path="res://scripts/multiplayer/player_spawner.gd" id="4_pi0y7"]
|
||||
[ext_resource type="Material" uid="uid://bx3f5vx71ynh5" path="res://materials/OrangeMat.tres" id="4_y6i55"]
|
||||
[ext_resource type="Material" uid="uid://mlha6r17v2en" path="res://materials/Bluemat.tres" id="5_bno23"]
|
||||
|
||||
[sub_resource type="Animation" id="Animation_y6i55"]
|
||||
length = 0.001
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("CSGCombiner3D/CSGBox3D7:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0),
|
||||
"transitions": PackedFloat32Array(1),
|
||||
"update": 0,
|
||||
"values": [Vector3(-10.610777, 3.2577968, -10.344306)]
|
||||
}
|
||||
|
||||
[sub_resource type="Animation" id="Animation_pi0y7"]
|
||||
resource_name = "main"
|
||||
length = 5.0
|
||||
loop_mode = 2
|
||||
tracks/0/type = "value"
|
||||
tracks/0/imported = false
|
||||
tracks/0/enabled = true
|
||||
tracks/0/path = NodePath("CSGCombiner3D/CSGBox3D7:position")
|
||||
tracks/0/interp = 1
|
||||
tracks/0/loop_wrap = true
|
||||
tracks/0/keys = {
|
||||
"times": PackedFloat32Array(0, 5),
|
||||
"transitions": PackedFloat32Array(-2, -2),
|
||||
"update": 0,
|
||||
"values": [Vector3(-10.610777, 3.2577968, -10.344306), Vector3(-13.402859, 6.188627, 10.213315)]
|
||||
}
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_bno23"]
|
||||
_data = {
|
||||
&"RESET": SubResource("Animation_y6i55"),
|
||||
&"main": SubResource("Animation_pi0y7")
|
||||
}
|
||||
|
||||
[node name="PrototypeScene" type="Node3D"]
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
|
|
@ -18,22 +56,46 @@ environment = ExtResource("1_i6jab")
|
|||
use_collision = true
|
||||
|
||||
[node name="CSGBox3D2" type="CSGBox3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -9.577414, 2.6, 1.8908081)
|
||||
use_collision = true
|
||||
size = Vector3(6.901001, 1, 4.520691)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.774414, 2.211084, -2.7798462)
|
||||
size = Vector3(1, 3.9007568, 10.341309)
|
||||
material = ExtResource("5_bno23")
|
||||
|
||||
[node name="CSGBox3D3" type="CSGBox3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(0.6651913, 0, -0.746673, 0, 1, 0, 0.746673, 0, 0.6651913, -3.2896764, 2.2110848, -14.45882)
|
||||
size = Vector3(10.241699, 3.9007568, 10.341309)
|
||||
material = ExtResource("5_bno23")
|
||||
|
||||
[node name="CSGBox3D7" type="CSGBox3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(0.6651913, 0, -0.746673, 0, 1, 0, 0.746673, 0, 0.6651913, -10.610777, 3.2577968, -10.344306)
|
||||
size = Vector3(4.6240234, 1.4752808, 4.2929688)
|
||||
material = ExtResource("5_bno23")
|
||||
|
||||
[node name="CSGBox3D4" type="CSGBox3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(0.2536462, 0.36299103, -0.8966053, -0.098810926, 0.9317926, 0.3492834, 0.962237, 0, 0.27221313, 17.497704, 2.2110848, -14.45882)
|
||||
size = Vector3(10.241699, 3.9007568, 10.341309)
|
||||
material = ExtResource("5_bno23")
|
||||
|
||||
[node name="CSGBox3D5" type="CSGBox3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(0.2536462, 0.36299103, -0.8966053, -0.098810926, 0.9317926, 0.3492834, 0.962237, 0, 0.27221313, 14.175301, -0.97636676, 16.262775)
|
||||
size = Vector3(10.241699, 8.579285, 15.858276)
|
||||
material = ExtResource("5_bno23")
|
||||
|
||||
[node name="CSGBox3D6" type="CSGBox3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(0.2464775, -0.4244365, -0.87126493, 0.11553718, 0.90545774, -0.40840852, 0.9622371, -1.5334081e-09, 0.27221313, -19.380054, -0.97636676, 16.262775)
|
||||
size = Vector3(10.241699, 8.579285, 15.858276)
|
||||
material = ExtResource("5_bno23")
|
||||
|
||||
[node name="CSGBox3D" type="CSGBox3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.774414, 0, 1.8908081)
|
||||
material_override = ExtResource("5_bno23")
|
||||
use_collision = true
|
||||
size = Vector3(22.206055, 1, 21.818726)
|
||||
size = Vector3(70.1814, 1, 50.408203)
|
||||
material = ExtResource("4_y6i55")
|
||||
|
||||
[node name="CSGPolygon3D" type="CSGPolygon3D" parent="CSGCombiner3D"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.49652505, 4.840562)
|
||||
polygon = PackedVector2Array(0, 0, -0.061755046, 1.5814729, 2, 0)
|
||||
depth = 2.45
|
||||
transform = Transform3D(-4.371139e-08, 0, -1, 0, 1, 0, 1, 0, -4.371139e-08, -3.3137877, 0.02481842, -3.7979093)
|
||||
polygon = PackedVector2Array(1.1265539, -0.16863012, -3.9689837, 4.1396155, -6.226393, 4.152759, -7.117619, 0.24168777)
|
||||
depth = 2.64
|
||||
material = ExtResource("5_bno23")
|
||||
|
||||
[node name="Spawner" type="Node3D" parent="."]
|
||||
|
|
@ -43,3 +105,9 @@ script = ExtResource("4_pi0y7")
|
|||
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."]
|
||||
_spawnable_scenes = PackedStringArray("uid://dpsr6ug3pkb40", "uid://cheu6vds21er7")
|
||||
spawn_path = NodePath("..")
|
||||
|
||||
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
|
||||
libraries = {
|
||||
&"": SubResource("AnimationLibrary_bno23")
|
||||
}
|
||||
autoplay = "main"
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
[gd_scene load_steps=15 format=3 uid="uid://dpsr6ug3pkb40"]
|
||||
[gd_scene load_steps=14 format=3 uid="uid://dpsr6ug3pkb40"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://3dphlay25fih" path="res://scripts/player/player.gd" id="1_g2els"]
|
||||
[ext_resource type="Script" uid="uid://dalwlndejfdhm" path="res://scripts/player/crosshair.gd" id="3_dqkch"]
|
||||
[ext_resource type="Script" uid="uid://bjhbdh6xsjgnn" path="res://scripts/player/player_camera.gd" id="3_qhqgy"]
|
||||
[ext_resource type="PackedScene" uid="uid://c3hg4ux4j76j2" path="res://models/molikman_hands.glb" id="4_dqkch"]
|
||||
[ext_resource type="Script" uid="uid://6c14qse4vnra" path="res://scripts/player/player_raycast.gd" id="4_fjrip"]
|
||||
[ext_resource type="Script" uid="uid://bmecgup3kcua7" path="res://scripts/weapon_system/system.gd" id="4_qlg0r"]
|
||||
[ext_resource type="Script" uid="uid://c76n6qgu6o4hn" path="res://scripts/weapon_system/gun.gd" id="6_tuyoq"]
|
||||
[ext_resource type="Script" uid="uid://bmecgup3kcua7" path="res://scripts/weapon_system/weapon_system.gd" id="4_qlg0r"]
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_u8vuu"]
|
||||
|
||||
|
|
@ -248,30 +247,9 @@ crosses_offset = 3.0
|
|||
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
|
||||
replication_config = SubResource("SceneReplicationConfig_qhqgy")
|
||||
|
||||
[node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("default_pistol", "default_knife", "animation_player")]
|
||||
[node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("default_pistol", "animation_player")]
|
||||
script = ExtResource("4_qlg0r")
|
||||
default_pistol = NodePath("StartingPistol")
|
||||
default_knife = NodePath("StartingPistol2")
|
||||
default_pistol = NodePath("")
|
||||
animation_player = NodePath("../Camera3D/molikman_hands/AnimationPlayer")
|
||||
|
||||
[node name="StartingPistol" type="Node" parent="WeaponSystem" node_paths=PackedStringArray("raycast")]
|
||||
script = ExtResource("6_tuyoq")
|
||||
max_ammo = 10
|
||||
semi_auto = true
|
||||
emptyable = true
|
||||
damage = 25
|
||||
firerate = 0.1
|
||||
prefix = "baked_sp"
|
||||
raycast = NodePath("../../Camera3D/RayCast3D")
|
||||
|
||||
[node name="StartingPistol2" type="Node" parent="WeaponSystem" node_paths=PackedStringArray("raycast")]
|
||||
script = ExtResource("6_tuyoq")
|
||||
max_ammo = 10
|
||||
semi_auto = true
|
||||
emptyable = true
|
||||
damage = 25
|
||||
firerate = 0.1
|
||||
prefix = "baked_sp"
|
||||
raycast = NodePath("../../Camera3D/RayCast3D")
|
||||
|
||||
[editable path="Camera3D/molikman_hands"]
|
||||
|
|
|
|||
28
scenes/weapons/starting_pistol.tscn
Normal file
28
scenes/weapons/starting_pistol.tscn
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
[gd_scene load_steps=6 format=3 uid="uid://djwjl8xll53vn"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://e6lqknfl4ngt" path="res://scripts/weapon_system/weapon_substate_machine.gd" id="1_g7s1i"]
|
||||
[ext_resource type="Script" uid="uid://ofv4e3dsfe8" path="res://scripts/weapon_system/gun/idle_state.gd" id="2_cmn6f"]
|
||||
[ext_resource type="Script" uid="uid://vj13r83l3xyq" path="res://scripts/weapon_system/gun/semi_auto_shoot_state.gd" id="3_016ti"]
|
||||
[ext_resource type="Script" uid="uid://hmekwp8444ao" path="res://scripts/weapon_system/gun/reload_state.gd" id="4_hoqxt"]
|
||||
[ext_resource type="Script" uid="uid://bmj0bwy2tlian" path="res://scripts/weapon_system/gun/intro_state.gd" id="5_ud1dr"]
|
||||
|
||||
[node name="StartingPistol" type="Node" node_paths=PackedStringArray("enter_state")]
|
||||
script = ExtResource("1_g7s1i")
|
||||
animation_prefix = &"baked_sp_"
|
||||
max_ammo = 20
|
||||
enter_state = NodePath("Intro")
|
||||
metadata/_custom_type_script = "uid://e6lqknfl4ngt"
|
||||
|
||||
[node name="Idle" type="Node" parent="."]
|
||||
script = ExtResource("2_cmn6f")
|
||||
|
||||
[node name="Shoot" type="Node" parent="."]
|
||||
script = ExtResource("3_016ti")
|
||||
|
||||
[node name="Reload" type="Node" parent="."]
|
||||
script = ExtResource("4_hoqxt")
|
||||
|
||||
[node name="Intro" type="Node" parent="."]
|
||||
script = ExtResource("5_ud1dr")
|
||||
|
||||
[node name="FireTimer" type="Timer" parent="."]
|
||||
|
|
@ -26,6 +26,8 @@ const MAX_HP = 100
|
|||
@export var TOGGLE_CROUCH: bool = true
|
||||
@export var WALK_MODIFIER: float = 0.5
|
||||
|
||||
|
||||
|
||||
@export var crouched: bool = false:
|
||||
set(value):
|
||||
if value != crouched and stand_up_area.has_overlapping_bodies() == false:
|
||||
|
|
@ -36,6 +38,8 @@ const MAX_HP = 100
|
|||
get:
|
||||
return crouched
|
||||
|
||||
@onready var TEMP_start_pos = global_position
|
||||
|
||||
var potential_crouched: bool = crouched
|
||||
|
||||
func _enter_tree() -> void:
|
||||
|
|
@ -89,4 +93,5 @@ func _input(event: InputEvent) -> void:
|
|||
crouched = false
|
||||
|
||||
func die() -> void:
|
||||
queue_free()
|
||||
global_position = TEMP_start_pos
|
||||
hp = MAX_HP
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
extends Node
|
||||
|
||||
|
||||
class_name StateMachine
|
||||
|
||||
@export var current_state: State
|
||||
|
|
@ -19,18 +18,36 @@ func on_transition_required(to: StringName):
|
|||
push_warning("Incorrect state request: " + to)
|
||||
return
|
||||
|
||||
change_state(states[to])
|
||||
|
||||
func change_state(to_state: State) -> void:
|
||||
if current_state != null:
|
||||
current_state.exit()
|
||||
current_state = to_state
|
||||
current_state.enter()
|
||||
|
||||
update_remote_machines.rpc(to_state.name)
|
||||
|
||||
@rpc("authority","call_local","unreliable")
|
||||
func clear_state():
|
||||
if current_state == null:
|
||||
return
|
||||
current_state.exit()
|
||||
current_state = null
|
||||
|
||||
@rpc("authority","call_remote","unreliable")
|
||||
func update_remote_machines(to: StringName) -> void:
|
||||
if current_state != null:
|
||||
current_state.exit()
|
||||
current_state = states[to]
|
||||
current_state.enter()
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if current_state == null:
|
||||
push_error("State is not set")
|
||||
return
|
||||
current_state.update(delta)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if current_state == null:
|
||||
push_error("State is not set")
|
||||
return
|
||||
current_state.physics_update(delta)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
@abstract
|
||||
extends Node
|
||||
|
||||
|
||||
class_name State
|
||||
|
||||
signal transition(to: StringName)
|
||||
|
||||
@abstract func enter() -> void
|
||||
@abstract func exit() -> void
|
||||
@abstract func update(delta: float) -> void
|
||||
@abstract func physics_update(delta: float) -> void
|
||||
func update(delta: float) -> void:
|
||||
pass
|
||||
func physics_update(delta: float) -> void:
|
||||
pass
|
||||
|
|
|
|||
27
scripts/state_machine/substate_machine.gd
Normal file
27
scripts/state_machine/substate_machine.gd
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
extends StateMachine
|
||||
|
||||
class_name SubStateMachine
|
||||
|
||||
@export var enter_state: State
|
||||
|
||||
func enter() -> void:
|
||||
change_state(enter_state)
|
||||
|
||||
func exit() -> void:
|
||||
clear_state.rpc()
|
||||
|
||||
func update(delta: float) -> void:
|
||||
if current_state == null:
|
||||
return
|
||||
current_state.update(delta)
|
||||
|
||||
func physics_update(delta: float) -> void:
|
||||
if current_state == null:
|
||||
return
|
||||
current_state.physics_update(delta)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
pass
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
pass
|
||||
1
scripts/state_machine/substate_machine.gd.uid
Normal file
1
scripts/state_machine/substate_machine.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://btc5vyvccdqfp
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
extends Usable
|
||||
|
||||
|
||||
@export var max_ammo: int
|
||||
@export var semi_auto: bool
|
||||
@export var emptyable: bool
|
||||
@export var damage: int
|
||||
|
||||
@export var firerate: float
|
||||
|
||||
@export var prefix: String
|
||||
|
||||
@export var raycast: RayCast3D
|
||||
|
||||
var ammo_amount: int
|
||||
var fire_timer: Timer
|
||||
var state_locked: bool
|
||||
|
||||
func _ready() -> void:
|
||||
fire_timer = Timer.new()
|
||||
fire_timer.wait_time = firerate
|
||||
ammo_amount = max_ammo
|
||||
add_child(fire_timer)
|
||||
if not semi_auto:
|
||||
fire_timer.timeout.connect(fire)
|
||||
|
||||
@rpc("authority","call_local","reliable")
|
||||
func use_begin() -> void:
|
||||
if fire_timer.is_stopped() == false:
|
||||
return
|
||||
fire_timer.start()
|
||||
fire_timer.one_shot = true if semi_auto else false
|
||||
fire()
|
||||
|
||||
@rpc("authority","call_local","reliable")
|
||||
func use_end() -> void:
|
||||
fire_timer.one_shot = true
|
||||
|
||||
func fire() -> void:
|
||||
if ammo_amount == 0 or state_locked:
|
||||
if not semi_auto:
|
||||
fire_timer.stop()
|
||||
return
|
||||
ammo_amount -= 1
|
||||
|
||||
system.animation_player.stop()
|
||||
system.animation_player.play(prefix + with_empty_suffix("_shoot"))
|
||||
system.animation_player.queue(prefix + with_empty_suffix("_idle"))
|
||||
|
||||
if raycast.is_colliding():
|
||||
raycast.get_collider().hp -= damage
|
||||
|
||||
|
||||
func alternate_state() -> void:
|
||||
pass
|
||||
|
||||
func switch_mode() -> void:
|
||||
pass
|
||||
|
||||
func enter() -> void:
|
||||
system.animation_player.animation_changed.connect(on_animation_changed)
|
||||
state_locked = true
|
||||
system.animation_player.stop()
|
||||
system.animation_player.play(prefix+with_empty_suffix("_intro"))
|
||||
system.animation_player.queue(prefix+with_empty_suffix("_idle"))
|
||||
|
||||
func exit() -> void:
|
||||
system.animation_player.animation_changed.disconnect(on_animation_changed)
|
||||
|
||||
func on_animation_changed(old_animation: StringName,_new_animation: StringName) -> void:
|
||||
if old_animation == prefix + with_empty_suffix("_reload"):
|
||||
state_locked = false
|
||||
ammo_amount = max_ammo
|
||||
if old_animation == prefix + with_empty_suffix("_intro"):
|
||||
state_locked = false
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if not system.is_multiplayer_authority() or not in_use: return
|
||||
|
||||
if event.is_action_pressed("plr_reload"):
|
||||
init_reload.rpc()
|
||||
|
||||
@rpc("call_local","authority","reliable")
|
||||
func init_reload():
|
||||
if ammo_amount == max_ammo or state_locked:
|
||||
return
|
||||
state_locked = true
|
||||
system.animation_player.play(prefix + with_empty_suffix("_reload"))
|
||||
system.animation_player.queue(prefix + "_idle")
|
||||
ammo_amount = max_ammo
|
||||
|
||||
func with_empty_suffix(animation):
|
||||
return (animation+"_empty") if emptyable and ammo_amount == 0 else animation
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://c76n6qgu6o4hn
|
||||
26
scripts/weapon_system/gun/idle_state.gd
Normal file
26
scripts/weapon_system/gun/idle_state.gd
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
extends WeaponState
|
||||
|
||||
@export var emptyable: bool
|
||||
|
||||
func enter() -> void:
|
||||
machine.animation_player.play(with_morphems("idle"))
|
||||
|
||||
func exit() -> void:
|
||||
pass
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if not machine.is_multiplayer_authority(): return
|
||||
|
||||
if event.is_action_pressed("plr_reload"):
|
||||
init_reload()
|
||||
|
||||
func use_begin() -> void:
|
||||
transition.emit("Shoot")
|
||||
|
||||
func init_reload():
|
||||
if machine.ammo == machine.max_ammo:
|
||||
return
|
||||
transition.emit("Reload")
|
||||
|
||||
func with_morphems(animation):
|
||||
return machine.animation_prefix + (animation+"_empty") if emptyable and machine.ammo == 0 else animation
|
||||
1
scripts/weapon_system/gun/idle_state.gd.uid
Normal file
1
scripts/weapon_system/gun/idle_state.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://ofv4e3dsfe8
|
||||
17
scripts/weapon_system/gun/intro_state.gd
Normal file
17
scripts/weapon_system/gun/intro_state.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
extends WeaponState
|
||||
|
||||
@export var emptyable: bool
|
||||
|
||||
func enter() -> void:
|
||||
machine.animation_player.play(with_morphems("intro"))
|
||||
machine.animation_player.animation_finished.connect(on_animation_finished)
|
||||
|
||||
func exit() -> void:
|
||||
machine.animation_player.animation_finished.disconnect(on_animation_finished)
|
||||
|
||||
func on_animation_finished(animation):
|
||||
if animation == with_morphems("intro"):
|
||||
transition.emit("Idle")
|
||||
|
||||
func with_morphems(animation):
|
||||
return machine.animation_prefix + (animation+"_empty") if emptyable and machine.ammo == 0 else animation
|
||||
1
scripts/weapon_system/gun/intro_state.gd.uid
Normal file
1
scripts/weapon_system/gun/intro_state.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://bmj0bwy2tlian
|
||||
18
scripts/weapon_system/gun/reload_state.gd
Normal file
18
scripts/weapon_system/gun/reload_state.gd
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
extends WeaponState
|
||||
|
||||
@export var emptyable: bool
|
||||
|
||||
func enter() -> void:
|
||||
machine.animation_player.play(with_morphems("reload"))
|
||||
machine.animation_player.animation_finished.connect(on_animation_finished)
|
||||
|
||||
func exit() -> void:
|
||||
machine.animation_player.animation_finished.disconnect(on_animation_finished)
|
||||
|
||||
func on_animation_finished(animation):
|
||||
if animation == with_morphems("reload"):
|
||||
machine.ammo = machine.max_ammo
|
||||
transition.emit("Idle")
|
||||
|
||||
func with_morphems(animation):
|
||||
return machine.animation_prefix + (animation+"_empty") if emptyable and machine.ammo == 0 else animation
|
||||
1
scripts/weapon_system/gun/reload_state.gd.uid
Normal file
1
scripts/weapon_system/gun/reload_state.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://hmekwp8444ao
|
||||
39
scripts/weapon_system/gun/semi_auto_shoot_state.gd
Normal file
39
scripts/weapon_system/gun/semi_auto_shoot_state.gd
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
extends WeaponState
|
||||
|
||||
@export var raycast: RayCast3D
|
||||
@export var emptyable: bool
|
||||
@export var damage: int
|
||||
|
||||
@export var fire_timer: Timer
|
||||
|
||||
func enter() -> void:
|
||||
fire()
|
||||
machine.animation_player.animation_finished.connect(on_animation_finished)
|
||||
|
||||
func exit() -> void:
|
||||
machine.animation_player.animation_finished.disconnect(on_animation_finished)
|
||||
|
||||
func on_animation_finished(animation):
|
||||
if animation == with_morphems("shoot"):
|
||||
transition.emit("Idle")
|
||||
|
||||
func use_begin() -> void:
|
||||
if fire_timer.time_left > 0:
|
||||
return
|
||||
fire()
|
||||
|
||||
func fire() -> void:
|
||||
if machine.ammo == 0 or fire_timer.time_left > 0:
|
||||
return
|
||||
machine.ammo -= 1
|
||||
|
||||
machine.animation_player.stop()
|
||||
machine.animation_player.play(with_morphems("shoot"))
|
||||
|
||||
if raycast.is_colliding():
|
||||
raycast.get_collider().hp -= damage
|
||||
|
||||
fire_timer.start()
|
||||
|
||||
func with_morphems(animation):
|
||||
return machine.animation_prefix + (animation+"_empty") if emptyable and machine.ammo == 0 else animation
|
||||
1
scripts/weapon_system/gun/semi_auto_shoot_state.gd.uid
Normal file
1
scripts/weapon_system/gun/semi_auto_shoot_state.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://vj13r83l3xyq
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
@abstract
|
||||
extends Node
|
||||
|
||||
class_name Usable
|
||||
|
||||
var system: WeaponSystem
|
||||
var in_use: bool = false
|
||||
|
||||
@rpc("authority","call_local","reliable")
|
||||
@abstract func use_begin() -> void
|
||||
@rpc("authority","call_local","reliable")
|
||||
@abstract func use_end() -> void
|
||||
@abstract func alternate_state() -> void
|
||||
# Need to clarify naming; Switch mode like firemode. For different states use
|
||||
# alternate_state
|
||||
@abstract func switch_mode() -> void
|
||||
|
||||
func enter() -> void:
|
||||
pass
|
||||
func exit() -> void:
|
||||
pass
|
||||
func update(_delta: float) -> void:
|
||||
pass
|
||||
func physics_update(_delta: float) -> void:
|
||||
pass
|
||||
|
|
@ -1 +0,0 @@
|
|||
uid://qj4m67w7ps7j
|
||||
17
scripts/weapon_system/weapon_state.gd
Normal file
17
scripts/weapon_system/weapon_state.gd
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
@abstract
|
||||
extends State
|
||||
|
||||
class_name WeaponState
|
||||
|
||||
var machine: WeaponSubStateMachine
|
||||
|
||||
func use_begin() -> void:
|
||||
pass
|
||||
func use_end() -> void:
|
||||
pass
|
||||
func alternate_state() -> void:
|
||||
pass
|
||||
# Need to clarify naming; Switch mode like firemode. For different states use
|
||||
# alternate_state
|
||||
func switch_mode() -> void:
|
||||
pass
|
||||
1
scripts/weapon_system/weapon_state.gd.uid
Normal file
1
scripts/weapon_system/weapon_state.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://fd4tm5wexdk
|
||||
33
scripts/weapon_system/weapon_substate_machine.gd
Normal file
33
scripts/weapon_system/weapon_substate_machine.gd
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
extends SubStateMachine
|
||||
|
||||
class_name WeaponSubStateMachine
|
||||
|
||||
@export var animation_prefix: StringName
|
||||
|
||||
@export var max_ammo: int
|
||||
@onready var ammo: int = max_ammo
|
||||
|
||||
var system: WeaponSystem
|
||||
var animation_player: AnimationPlayer
|
||||
|
||||
func _ready() -> void:
|
||||
for child in get_children():
|
||||
if child is WeaponState:
|
||||
states[child.name] = child
|
||||
child.machine = self
|
||||
child.transition.connect(on_transition_required)
|
||||
else:
|
||||
push_warning("Child of state machine is not state")
|
||||
|
||||
@rpc("authority","call_local","reliable")
|
||||
func use_begin() -> void:
|
||||
current_state.use_begin()
|
||||
@rpc("authority","call_local","reliable")
|
||||
func use_end() -> void:
|
||||
current_state.use_end()
|
||||
func alternate_state() -> void:
|
||||
current_state.alternate_state()
|
||||
# Need to clarify naming; Switch mode like firemode. For different states use
|
||||
# alternate_state
|
||||
func switch_mode() -> void:
|
||||
current_state.switch_mode()
|
||||
1
scripts/weapon_system/weapon_substate_machine.gd.uid
Normal file
1
scripts/weapon_system/weapon_substate_machine.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://e6lqknfl4ngt
|
||||
|
|
@ -1,16 +1,15 @@
|
|||
extends Node
|
||||
|
||||
|
||||
class_name WeaponSystem
|
||||
|
||||
@export var default_pistol: Usable
|
||||
@export var default_knife: Usable
|
||||
@export var default_pistol: WeaponSubStateMachine
|
||||
@export var default_knife: WeaponSubStateMachine
|
||||
|
||||
@export var animation_player: AnimationPlayer
|
||||
|
||||
var current_usable: Usable
|
||||
var current_state: WeaponSubStateMachine
|
||||
|
||||
var slots: Dictionary[StringName,Usable] = {
|
||||
var slots: Dictionary[StringName,WeaponSubStateMachine] = {
|
||||
"primary": null,
|
||||
"secondary": default_pistol,
|
||||
"knife": default_knife,
|
||||
|
|
@ -21,61 +20,63 @@ var slots: Dictionary[StringName,Usable] = {
|
|||
"ultimate": null
|
||||
}
|
||||
|
||||
signal switched_to(usable: Usable)
|
||||
signal switched_to(state: WeaponSubStateMachine)
|
||||
|
||||
func _ready() -> void:
|
||||
for child in get_children():
|
||||
if child is Usable:
|
||||
if child is WeaponSubStateMachine:
|
||||
child.system = self
|
||||
child.animation_player = animation_player
|
||||
else:
|
||||
push_warning("Child of weapon system is not ability or weapon")
|
||||
|
||||
current_usable = default_pistol
|
||||
current_state = default_pistol
|
||||
slots["knife"] = default_knife
|
||||
slots["secondary"] = default_pistol
|
||||
current_usable.enter()
|
||||
current_state.enter()
|
||||
current_state.in_use = true
|
||||
|
||||
func can_add(slot: StringName) -> bool:
|
||||
return slots.has(slot)
|
||||
|
||||
func add(usable: Usable, slot: StringName) -> void:
|
||||
func add(state: WeaponSubStateMachine, slot: StringName) -> void:
|
||||
if can_add(slot) == false:
|
||||
return
|
||||
|
||||
add_child(usable)
|
||||
add_child(state)
|
||||
|
||||
slots[slot] = usable
|
||||
usable.system = self
|
||||
slots[slot] = state
|
||||
state.system = self
|
||||
|
||||
|
||||
func switch(to: StringName):
|
||||
if slots.has(to) == false or slots[to] == null or slots[to] == current_usable:
|
||||
if slots.has(to) == false or slots[to] == null or slots[to] == current_state:
|
||||
return
|
||||
current_usable.exit()
|
||||
current_usable.in_use = false
|
||||
current_usable = slots[to]
|
||||
current_usable.enter()
|
||||
current_usable.in_use = true
|
||||
current_state.exit()
|
||||
current_state.in_use = false
|
||||
current_state = slots[to]
|
||||
current_state.enter()
|
||||
current_state.in_use = true
|
||||
|
||||
switched_to.emit(current_usable)
|
||||
switched_to.emit(current_state)
|
||||
|
||||
update_remotes.rpc(to)
|
||||
#update_remotes.rpc(to)
|
||||
|
||||
@rpc("authority","call_remote","reliable")
|
||||
func update_remotes(to: StringName):
|
||||
switch(to)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if current_usable == null:
|
||||
if current_state == null:
|
||||
push_error("State is not set")
|
||||
return
|
||||
current_usable.update(delta)
|
||||
current_state.update(delta)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if current_usable == null:
|
||||
if current_state == null:
|
||||
push_error("State is not set")
|
||||
return
|
||||
current_usable.physics_update(delta)
|
||||
current_state.physics_update(delta)
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if is_multiplayer_authority() == false: return
|
||||
|
|
@ -98,11 +99,11 @@ func _input(event: InputEvent) -> void:
|
|||
switch("knife")
|
||||
|
||||
if event.is_action_pressed("plr_fire"):
|
||||
current_usable.use_begin.rpc()
|
||||
current_state.use_begin.rpc()
|
||||
if event.is_action_released("plr_fire"):
|
||||
current_usable.use_end.rpc()
|
||||
current_state.use_end.rpc()
|
||||
if event.is_action_pressed("plr_scope"):
|
||||
current_usable.alternate_state()
|
||||
current_state.alternate_state()
|
||||
if event.is_action_pressed("plr_firemode"):
|
||||
current_usable.switch_mode()
|
||||
current_state.switch_mode()
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue