equipped weapon; health; death; test enemy; weapon cooldown

This commit is contained in:
Rowan 2025-06-21 10:00:20 -04:00
parent 5c4c0384ba
commit 27bd064c15
22 changed files with 521 additions and 92 deletions

View file

@ -27,9 +27,15 @@ class Some extends Option:
func _init(val: Variant) -> void:
value = val
func chain(fn: Callable) -> Option:
func and_then(fn: Callable) -> Option:
return fn.call(value)
func and_other(other: Option) -> Option:
return other
func contains(target_value: Variant) -> bool:
return value == target_value
func filter(fn: Callable) -> Option:
if fn.call(value): return self
else: return Option.none
@ -42,25 +48,50 @@ class Some extends Option:
func map(fn: Callable) -> Option:
return Option.some(fn.call(value))
func ok_or(_err: Variant) -> Result:
return Result.ok(value)
func ok_or_else(fn: Callable) -> Result:
return Result.ok(value)
func or_other(option: Option) -> Option:
return self
func inspect(fn: Callable) -> Option:
fn.call(value)
return self
func is_some() -> bool:
return true
func is_none() -> bool:
return false
func or_default(_default_value: Variant) -> Variant:
return value
func or_else(_fn: Callable) -> Variant:
return value
func unwrap() -> Variant:
return value
func unwrap_or(_default_value: Variant) -> Variant:
return value
func unwrap_or_else(_fn: Callable) -> Variant:
return value
func xor_other(other: Option) -> Option:
if other.is_none():
return self
else:
return Option.none
class None extends Option:
func chain(_fn: Callable) -> Option:
func and_then(_fn: Callable) -> Option:
return self
func and_other(other: Option) -> Option:
return self
func contains(value: Variant) -> bool:
return false
func filter(_f: Callable) -> Option:
return self
@ -70,18 +101,36 @@ class None extends Option:
func map(_fn: Callable) -> Option:
return self
func ok_or(err: Variant) -> Result:
return Result.err(err)
func ok_or_else(fn: Callable) -> Result:
return Result.err(fn.call())
func or_other(option: Option) -> Option:
return option
func inspect(_fn: Callable) -> Option:
return self
func is_some() -> bool:
return false
func is_none() -> bool:
return true
func or_default(default_value: Variant) -> Variant:
return default_value
func or_else(fn: Callable) -> Variant:
return fn.call()
func unwrap() -> Variant:
assert(false, "Called unwrap() on a None value")
return null
func unwrap_or(default_value: Variant) -> Variant:
return default_value
func unwrap_or_else(fn: Callable) -> Variant:
return fn.call()
func xor_other(other: Option) -> Option:
if other.is_some():
return other
else:
return self

BIN
godot/assets/mann.glb Normal file

Binary file not shown.

View file

@ -0,0 +1,44 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cyrwuqefk3efr"
path="res://.godot/imported/mann.glb-288e378e28910734d9c899c96305cd64.scn"
[deps]
source_file="res://assets/mann.glb"
dest_files=["res://.godot/imported/mann.glb-288e378e28910734d9c899c96305cd64.scn"]
[params]
nodes/root_type=""
nodes/root_name=""
nodes/apply_root_scale=true
nodes/root_scale=0.008
nodes/import_as_skeleton_bones=false
nodes/use_node_type_suffixes=true
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
meshes/force_disable_compression=false
skins/use_named_skins=true
animation/import=true
animation/fps=30
animation/trimming=false
animation/remove_immutable_tracks=true
animation/import_rest_as_RESET=false
import_script/path=""
_subresources={
"nodes": {
"PATH:AnimationPlayer": {
"import_tracks/position": 0,
"import_tracks/scale": 2
}
}
}
gltf/naming_version=1
gltf/embedded_image_handling=1

BIN
godot/assets/mann_0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 MiB

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://c3upx1jyltix0"
path.s3tc="res://.godot/imported/mann_0.png-0eec56285f3b8080c8323d0defc178e9.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={
"md5": "8af17aa62c9ee95592da5f3e6e42fcf1"
}
[deps]
source_file="res://assets/mann_0.png"
dest_files=["res://.godot/imported/mann_0.png-0eec56285f3b8080c8323d0defc178e9.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

BIN
godot/assets/mann_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 MiB

View file

@ -0,0 +1,38 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://b14nebibcf2g6"
path.s3tc="res://.godot/imported/mann_1.png-93592f6ed267c9cdc1a955fda87a4e91.s3tc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
}
generator_parameters={
"md5": "018299a57123ad32d2eaf390dda03ca7"
}
[deps]
source_file="res://assets/mann_1.png"
dest_files=["res://.godot/imported/mann_1.png-93592f6ed267c9cdc1a955fda87a4e91.s3tc.ctex"]
[params]
compress/mode=2
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=1
compress/channel_pack=0
mipmaps/generate=true
mipmaps/limit=-1
roughness/mode=1
roughness/src_normal="res://assets/mann_1.png"
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=0

85
godot/scenes/enemy.tscn Normal file
View file

@ -0,0 +1,85 @@
[gd_scene load_steps=10 format=3 uid="uid://c0cf6jkxasplk"]
[ext_resource type="PackedScene" uid="uid://cyrwuqefk3efr" path="res://assets/mann.glb" id="2_4ra3w"]
[ext_resource type="Script" uid="uid://d4anpy5efe22d" path="res://src/health.gd" id="2_md0e3"]
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_md0e3"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_md0e3"]
animation = &"HeadHit"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_4ra3w"]
animation = &"DyingBackwards"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_5uy6h"]
animation = &"T-Pose (No Animation)"
[sub_resource type="AnimationNodeOneShot" id="AnimationNodeOneShot_c4w8v"]
[sub_resource type="AnimationNodeTransition" id="AnimationNodeTransition_xwavj"]
input_0/name = "idle"
input_0/auto_advance = false
input_0/break_loop_at_end = false
input_0/reset = true
input_1/name = "dead"
input_1/auto_advance = false
input_1/break_loop_at_end = false
input_1/reset = true
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_nenq2"]
graph_offset = Vector2(-685.25, 50.2044)
nodes/Animation/node = SubResource("AnimationNodeAnimation_5uy6h")
nodes/Animation/position = Vector2(-220, 120)
"nodes/Animation 2/node" = SubResource("AnimationNodeAnimation_md0e3")
"nodes/Animation 2/position" = Vector2(-140, 320)
"nodes/Animation 3/node" = SubResource("AnimationNodeAnimation_4ra3w")
"nodes/Animation 3/position" = Vector2(60, 420)
nodes/Hit/node = SubResource("AnimationNodeOneShot_c4w8v")
nodes/Hit/position = Vector2(60, 120)
nodes/Transition/node = SubResource("AnimationNodeTransition_xwavj")
nodes/Transition/position = Vector2(260, 120)
nodes/output/position = Vector2(440, 120)
node_connections = [&"Hit", 0, &"Animation", &"Hit", 1, &"Animation 2", &"Transition", 0, &"Hit", &"Transition", 1, &"Animation 3", &"output", 0, &"Transition"]
[node name="Enemy" type="CharacterBody3D"]
transform = Transform3D(1.75, 0, 0, 0, 1.75, 0, 0, 0, 1.75, 0, 0, 0)
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("CapsuleShape3D_md0e3")
[node name="Health" type="Node" parent="."]
script = ExtResource("2_md0e3")
max_health = 5
metadata/_custom_type_script = "uid://d4anpy5efe22d"
[node name="AnimationTree" type="AnimationTree" parent="."]
root_node = NodePath("../AuxScene")
tree_root = SubResource("AnimationNodeBlendTree_nenq2")
anim_player = NodePath("../AuxScene/AnimationPlayer")
parameters/Hit/active = false
parameters/Hit/internal_active = false
parameters/Hit/request = 0
parameters/Transition/current_state = "idle"
parameters/Transition/transition_request = ""
parameters/Transition/current_index = 0
[node name="AuxScene" parent="." instance=ExtResource("2_4ra3w")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.708055, 0)
[node name="Skeleton3D" parent="AuxScene/Node" index="0"]
bones/14/rotation = Quaternion(-0.049153, -0.00278018, 0.056403, 0.997194)
bones/30/rotation = Quaternion(-0.00214526, -6.9426e-18, 1.71983e-18, 0.999998)
bones/33/rotation = Quaternion(0.0397321, 6.93342e-18, -2.75697e-19, 0.99921)
bones/39/rotation = Quaternion(0.0548733, -0.109425, -0.0279963, 0.992084)
bones/45/rotation = Quaternion(0.0420007, -5.82877e-19, -1.38655e-17, 0.999118)
bones/46/rotation = Quaternion(-0.00160061, -2.22129e-20, 1.38778e-17, 0.999999)
bones/50/rotation = Quaternion(-0.027251, 0, 0, 0.999629)
bones/52/rotation = Quaternion(0.0706924, 0.00317808, 0.0447985, 0.996487)
bones/56/rotation = Quaternion(0.0852392, 0.00496034, 0.0578828, 0.994665)
bones/61/rotation = Quaternion(-0.00265969, 1.04465e-05, -0.0039276, 0.999989)
[connection signal="damaged" from="Health" to="AnimationTree" method="set" binds= ["parameters/Hit/request", 1]]
[connection signal="died" from="Health" to="AnimationTree" method="set" binds= ["parameters/Transition/transition_request", "dead"]]
[editable path="AuxScene"]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=15 format=3 uid="uid://dttyp3682enn7"]
[gd_scene load_steps=16 format=3 uid="uid://dttyp3682enn7"]
[ext_resource type="PackedScene" uid="uid://crbrniwi6kd3p" path="res://scenes/player.tscn" id="1_2q6dc"]
[ext_resource type="Script" uid="uid://csjccrhj5wnx7" path="res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd" id="2_klq6b"]
@ -9,6 +9,7 @@
[ext_resource type="Script" uid="uid://cdvtrsqkkxtdd" path="res://src/persistence.gd" id="4_mx8sn"]
[ext_resource type="Resource" uid="uid://cqfnwpmo4fyv4" path="res://resources/items/key.tres" id="7_8c41q"]
[ext_resource type="PackedScene" uid="uid://cn7tgd4y67wnd" path="res://scenes/inventory.tscn" id="8_b121j"]
[ext_resource type="PackedScene" uid="uid://c0cf6jkxasplk" path="res://scenes/enemy.tscn" id="10_olg7q"]
[sub_resource type="PlaneMesh" id="PlaneMesh_rd3vj"]
@ -113,6 +114,10 @@ text = "Load
[node name="Inventory" parent="CanvasLayer" instance=ExtResource("8_b121j")]
visible = false
[node name="Enemy" parent="." instance=ExtResource("10_olg7q")]
transform = Transform3D(1.75, 0, 0, 0, 1.75, 0, 0, 0, 1.75, 6, 0, 0)
[connection signal="opened" from="Door" to="Door" method="hide"]
[connection signal="interacted" from="Door/Interactable" to="Door" method="_on_interact"]
[connection signal="pressed" from="CanvasLayer/Control/HBoxContainer/SaveButton" to="CanvasLayer/Control/Persistence" method="save" binds= ["save1.sav"]]
[connection signal="pressed" from="CanvasLayer/Control/HBoxContainer/LoadButton" to="CanvasLayer/Control/Persistence" method="load" binds= ["save1.sav"]]

31
godot/scenes/pistol.tscn Normal file
View file

@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=3 uid="uid://isqkayrtr7t8"]
[ext_resource type="Script" uid="uid://bn7dr8s404qnf" path="res://src/usable.gd" id="1_1e3ry"]
[ext_resource type="PackedScene" uid="uid://5a023hrws3gx" path="res://assets/Glock 17 Gen 4/Main.glb" id="1_igbvm"]
[ext_resource type="Script" uid="uid://ddqif2gmm1ec2" path="res://src/damage_source.gd" id="2_buff3"]
[node name="Pistol" type="Node3D"]
script = ExtResource("1_1e3ry")
[node name="Main" parent="." instance=ExtResource("1_igbvm")]
[node name="RayCast3D" type="RayCast3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, -1.25)
target_position = Vector3(0, 0, -100)
debug_shape_custom_color = Color(1, 0, 0, 1)
debug_shape_thickness = 1
[node name="DamageSource" type="Node" parent="." node_paths=PackedStringArray("raycast")]
script = ExtResource("2_buff3")
damage = 1
raycast = NodePath("../RayCast3D")
metadata/_custom_type_script = "uid://ddqif2gmm1ec2"
[node name="Timer" type="Timer" parent="."]
wait_time = 0.5
one_shot = true
[connection signal="used" from="." to="." method="disable"]
[connection signal="used" from="." to="DamageSource" method="try_damage"]
[connection signal="used" from="." to="Timer" method="start"]
[connection signal="timeout" from="Timer" to="." method="enable"]

View file

@ -1,11 +1,13 @@
[gd_scene load_steps=44 format=3 uid="uid://crbrniwi6kd3p"]
[gd_scene load_steps=49 format=3 uid="uid://crbrniwi6kd3p"]
[ext_resource type="PackedScene" uid="uid://dpmbimh6m4ari" path="res://scenes/player_mesh.tscn" id="1_3vyb7"]
[ext_resource type="Script" uid="uid://d1drx1b1s1evy" path="res://src/player.gd" id="1_qhqgy"]
[ext_resource type="Script" uid="uid://50vv0ta67tgl" path="res://src/player.gd" id="1_qhqgy"]
[ext_resource type="Script" uid="uid://877g2wvcupw6" path="res://src/player_input.gd" id="3_dqkch"]
[ext_resource type="Script" uid="uid://c3wlcxy4vnm2i" path="res://src/interactor.gd" id="4_dqkch"]
[ext_resource type="Script" uid="uid://csjl56hf0fnoy" path="res://src/item_container.gd" id="5_qlg0r"]
[ext_resource type="Resource" uid="uid://bllq6ri54q3ne" path="res://resources/player_inventory.tres" id="6_tuyoq"]
[ext_resource type="PackedScene" uid="uid://isqkayrtr7t8" path="res://scenes/pistol.tscn" id="7_fjrip"]
[ext_resource type="Script" uid="uid://c710qg683rqbc" path="res://src/equipment.gd" id="7_ur7pv"]
[sub_resource type="SphereShape3D" id="SphereShape3D_qhqgy"]
@ -14,6 +16,27 @@
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_smehm"]
animation = &"Aim"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_jej6c"]
animation = &"Fire"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_f1ej7"]
animation = &"Aim"
[sub_resource type="AnimationNodeBlend2" id="AnimationNodeBlend2_oprun"]
filter_enabled = true
filters = ["AuxScene/Scene/Armature/Skeleton3D:mixamorigHead", "AuxScene/Scene/Armature/Skeleton3D:mixamorigHead001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigHips", "AuxScene/Scene/Armature/Skeleton3D:mixamorigHips001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftArm", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftFoot", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftForeArm", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftLeg", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftLeg001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftShoulder", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftShoulder001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftToeBase", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftUpLeg", "AuxScene/Scene/Armature/Skeleton3D:mixamorigLeftUpLeg001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigNeck", "AuxScene/Scene/Armature/Skeleton3D:mixamorigNeck001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightArm", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightFoot", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightForeArm", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightLeg", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightLeg001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightShoulder", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightShoulder001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightToeBase", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightUpLeg", "AuxScene/Scene/Armature/Skeleton3D:mixamorigRightUpLeg001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigSpine", "AuxScene/Scene/Armature/Skeleton3D:mixamorigSpine001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigSpine1", "AuxScene/Scene/Armature/Skeleton3D:mixamorigSpine1001", "AuxScene/Scene/Armature/Skeleton3D:mixamorigSpine2", "AuxScene/Scene/Armature/Skeleton3D:mixamorigSpine2001"]
[sub_resource type="AnimationNodeBlendTree" id="AnimationNodeBlendTree_a8ls1"]
graph_offset = Vector2(-454.653, 56.3387)
nodes/Animation/node = SubResource("AnimationNodeAnimation_f1ej7")
nodes/Animation/position = Vector2(200, 340)
"nodes/Animation 2/node" = SubResource("AnimationNodeAnimation_jej6c")
"nodes/Animation 2/position" = Vector2(200, 160)
nodes/Blend2/node = SubResource("AnimationNodeBlend2_oprun")
nodes/Blend2/position = Vector2(380, 160)
nodes/output/position = Vector2(560, 160)
node_connections = [&"Blend2", 0, &"Animation 2", &"Blend2", 1, &"Animation", &"output", 0, &"Blend2"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_d2wvv"]
animation = &"Run"
@ -35,9 +58,6 @@ nodes/Blend2/position = Vector2(60, 140)
nodes/output/position = Vector2(300, 140)
node_connections = [&"Blend2", 0, &"Animation", &"Blend2", 1, &"Animation 2", &"output", 0, &"Blend2"]
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_ur7pv"]
animation = &"Fire"
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_y4r1p"]
animation = &"PistolIdle"
@ -76,14 +96,6 @@ advance_expression = "not velocity"
advance_mode = 2
advance_expression = "is_weapon_ready"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_a8ls1"]
advance_mode = 2
advance_expression = "is_firing"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_qfm1y"]
switch_mode = 2
advance_mode = 2
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_fulsm"]
advance_mode = 2
advance_expression = "not is_weapon_ready"
@ -96,19 +108,30 @@ advance_expression = "is_running"
advance_mode = 2
advance_expression = "not is_running"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_a8ls1"]
advance_mode = 2
advance_expression = "is_firing
"
[sub_resource type="AnimationNodeStateMachineTransition" id="AnimationNodeStateMachineTransition_qfm1y"]
break_loop_at_end = true
switch_mode = 2
advance_mode = 2
[sub_resource type="AnimationNodeStateMachine" id="AnimationNodeStateMachine_d2wvv"]
states/Aim/node = SubResource("AnimationNodeAnimation_smehm")
states/Aim/position = Vector2(327, 194)
states/BlendTree/node = SubResource("AnimationNodeBlendTree_f1ej7")
states/BlendTree/position = Vector2(653, 100)
"states/BlendTree 2/node" = SubResource("AnimationNodeBlendTree_a8ls1")
"states/BlendTree 2/position" = Vector2(488, 194)
states/End/position = Vector2(890, 40)
states/Fire/node = SubResource("AnimationNodeAnimation_ur7pv")
states/Fire/position = Vector2(462, 194)
states/PistolIdle/node = SubResource("AnimationNodeAnimation_y4r1p")
states/PistolIdle/position = Vector2(327, 100)
states/Walk/node = SubResource("AnimationNodeBlendTree_ur7pv")
states/Walk/position = Vector2(488, 100)
transitions = ["Start", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_ur7pv"), "PistolIdle", "Walk", SubResource("AnimationNodeStateMachineTransition_y4r1p"), "Walk", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_d2wvv"), "PistolIdle", "Aim", SubResource("AnimationNodeStateMachineTransition_oprun"), "Aim", "Fire", SubResource("AnimationNodeStateMachineTransition_a8ls1"), "Fire", "Aim", SubResource("AnimationNodeStateMachineTransition_qfm1y"), "Aim", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_fulsm"), "Walk", "BlendTree", SubResource("AnimationNodeStateMachineTransition_4r5pv"), "BlendTree", "Walk", SubResource("AnimationNodeStateMachineTransition_60mlk")]
transitions = ["Start", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_ur7pv"), "PistolIdle", "Walk", SubResource("AnimationNodeStateMachineTransition_y4r1p"), "Walk", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_d2wvv"), "PistolIdle", "Aim", SubResource("AnimationNodeStateMachineTransition_oprun"), "Aim", "PistolIdle", SubResource("AnimationNodeStateMachineTransition_fulsm"), "Walk", "BlendTree", SubResource("AnimationNodeStateMachineTransition_4r5pv"), "BlendTree", "Walk", SubResource("AnimationNodeStateMachineTransition_60mlk"), "Aim", "BlendTree 2", SubResource("AnimationNodeStateMachineTransition_a8ls1"), "BlendTree 2", "Aim", SubResource("AnimationNodeStateMachineTransition_qfm1y")]
graph_offset = Vector2(-75, 65)
[sub_resource type="AnimationNodeAnimation" id="AnimationNodeAnimation_qhqgy"]
animation = &"Idle"
@ -170,12 +193,31 @@ states/Unarmed/node = SubResource("AnimationNodeStateMachine_ur7pv")
states/Unarmed/position = Vector2(356, 50)
transitions = ["Start", "Unarmed", SubResource("AnimationNodeStateMachineTransition_qlg0r"), "Start", "Handgun", SubResource("AnimationNodeStateMachineTransition_3v2ag"), "Handgun", "Unarmed", SubResource("AnimationNodeStateMachineTransition_jej6c"), "Unarmed", "Handgun", SubResource("AnimationNodeStateMachineTransition_f1ej7")]
[node name="Player" type="CharacterBody3D" groups=["persist"]]
[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("input", "interactor", "equipment") groups=["persist"]]
script = ExtResource("1_qhqgy")
input = NodePath("Input")
interactor = NodePath("Interactor")
equipment = NodePath("Weapon")
[node name="Input" type="Node" parent="."]
script = ExtResource("3_dqkch")
[node name="Inventory" type="Node" parent="."]
script = ExtResource("5_qlg0r")
inventory = ExtResource("6_tuyoq")
[node name="Weapon" type="BoneAttachment3D" parent="." node_paths=PackedStringArray("initial_equipment")]
transform = Transform3D(0.00876506, 0.0120414, 0.00178277, 0.00882159, -0.00779736, 0.00929411, 0.00838767, -0.00438243, -0.0116379, -0.128585, 1.36723, 0.500051)
bone_name = "mixamorigRightHandMiddle1"
bone_idx = 24
use_external_skeleton = true
external_skeleton = NodePath("../Mesh/AuxScene/Scene/Armature/Skeleton3D")
script = ExtResource("7_ur7pv")
initial_equipment = NodePath("Pistol")
[node name="Pistol" parent="Weapon" instance=ExtResource("7_fjrip")]
transform = Transform3D(-0.948472, 9.81445, -1.66645, -5.38265, -1.91379, -8.20758, -8.37422, 0.118531, 5.46429, 3.16379, 3.48907, 1.04434)
[node name="Interactor" type="Node3D" parent="." node_paths=PackedStringArray("area", "root_node")]
script = ExtResource("4_dqkch")
area = NodePath("Area3D")
@ -200,10 +242,7 @@ tree_root = SubResource("AnimationNodeStateMachine_y4r1p")
advance_expression_base_node = NodePath("..")
anim_player = NodePath("../Mesh/AnimationPlayer")
parameters/Handgun/BlendTree/Blend2/blend_amount = 1.0
"parameters/Handgun/BlendTree 2/Blend2/blend_amount" = 1.0
parameters/Handgun/Walk/Blend2/blend_amount = 1.0
[node name="ItemContainer" type="Node" parent="."]
script = ExtResource("5_qlg0r")
inventory = ExtResource("6_tuyoq")
[editable path="Mesh"]

View file

@ -0,0 +1,25 @@
class_name DamageSource extends Node
@export var damage: int
@export var raycast: RayCast3D
func _ready() -> void:
raycast.enabled = false
func raycast_to_target() -> Option:
raycast.force_raycast_update()
if raycast.is_colliding():
return Option.some(raycast.get_collider())
else:
return Option.none
func try_damage() -> void:
match raycast_to_target():
var option when option.is_some():
var value = option.unwrap()
match NodeExt.find_child_variant(value, Health):
var node when node.is_some():
var health: Health = node.unwrap()
health.apply_damage(damage)
_: pass
_: pass

View file

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

25
godot/src/equipment.gd Normal file
View file

@ -0,0 +1,25 @@
class_name Equipment extends Node
signal unequipped(item: Item)
signal equipped(item: Item)
@export var initial_equipment: Usable
var current_item: Option = Option.none
func _ready() -> void:
current_item = Option.from(initial_equipment)
func unequip():
if current_item.is_some():
var item = current_item.unwrap()
current_item = Option.none
unequipped.emit(item)
func equip(item: Item):
unequip()
if item != null:
current_item = Option.some(item)
equipped.emit(item)
func use():
current_item.inspect(func(x: Variant) -> void: x.use())

View file

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

26
godot/src/health.gd Normal file
View file

@ -0,0 +1,26 @@
class_name Health extends Node
signal died
signal damaged
@export var max_health: int
@export var current_value: int
@export var heal_on_spawn: bool = true
var dead: bool = false
func _ready() -> void:
if heal_on_spawn:
current_value = max_health
func apply_damage(value: int):
if dead: return
current_value = max(current_value - value, 0)
if current_value <= 0:
dead = true
died.emit()
else:
damaged.emit()
func apply_healing(value: int):
current_value = min(current_value + value, max_health)

1
godot/src/health.gd.uid Normal file
View file

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

View file

@ -1,38 +1,38 @@
class_name NodeExt
class NodeChildIterator:
var _node: Node
var _include_internal: bool
var _index: int
var _length: int
var _node: Node
var _include_internal: bool
var _index: int
var _length: int
func _init(node: Node, include_internal: bool) -> void:
_node = node
_include_internal = include_internal
_index = 0
_length = node.get_child_count(include_internal)
func _init(node: Node, include_internal: bool) -> void:
_node = node
_include_internal = include_internal
_index = 0
_length = node.get_child_count(include_internal)
func _continue() -> bool:
return (_index < _length)
func _continue() -> bool:
return (_index < _length)
func _iter_init(_iter: Array) -> bool:
_index = 0
return _continue()
func _iter_init(_iter: Array) -> bool:
_index = 0
return _continue()
func _iter_next(_iter: Array) -> bool:
_index += 1
return _continue()
func _iter_next(_iter: Array) -> bool:
_index += 1
return _continue()
func _iter_get(_iter: Variant) -> Variant:
return _node.get_child(_index, _include_internal)
func _iter_get(_iter: Variant) -> Variant:
return _node.get_child(_index, _include_internal)
static func find_child(node: Node, predicate: Callable, include_internal: bool = false) -> Option:
for child in NodeChildIterator.new(node, include_internal):
if predicate.call(child):
return Option.some(child)
return Option.none
for child in NodeChildIterator.new(node, include_internal):
if predicate.call(child):
return Option.some(child)
return Option.none
static func find_child_variant(node: Node, variant: Variant, include_internal: bool = false) -> Option:
for child in NodeChildIterator.new(node, include_internal):
if is_instance_of(child, variant):
return Option.some(child)
return Option.none
for child in NodeChildIterator.new(node, include_internal):
if is_instance_of(child, variant):
return Option.some(child)
return Option.none

View file

@ -3,55 +3,56 @@ class_name Player extends CharacterBody3D
@export var walk_speed: float = 4.0
@export var run_speed: float = 6.0
@onready var input = $Input
@onready var interactor = $Interactor
@export var input: PlayerInput
@export var interactor: Interactor
@export var equipment: Equipment
var is_running: bool:
get: return velocity and input.is_running
get: return velocity and input.is_running
var is_carrying_item = true
var is_weapon_ready: bool:
get: return is_carrying_item and input.is_weapon_ready
get: return is_carrying_item and input.is_weapon_ready
func _ready() -> void:
input.connect('interact', _on_interact)
input.connect('fire', _on_fire)
input.connect('interact', _on_interact)
input.connect('fire', _on_fire)
func _physics_process(delta: float) -> void:
if is_weapon_ready:
rotate_toward_look(delta)
else:
move_and_rotate(delta)
if is_weapon_ready:
rotate_toward_look(delta)
else:
move_and_rotate(delta)
func move_and_rotate(_delta: float):
var speed = run_speed if input.is_running else walk_speed
velocity = input.next_velocity(speed)
if !velocity.is_zero_approx():
look_at(global_position + velocity, Vector3.UP, true)
move_and_slide()
var speed = run_speed if input.is_running else walk_speed
velocity = input.next_velocity(speed)
if !velocity.is_zero_approx():
look_at(global_position + velocity, Vector3.UP, true)
move_and_slide()
func rotate_toward_look(_delta: float):
velocity = Vector3.ZERO
var target = input.get_look_target(global_position)
if target.is_some():
look_at(target.unwrap(), Vector3.UP, true)
velocity = Vector3.ZERO
var target = input.get_look_target(global_position)
if target.is_some():
look_at(target.unwrap(), Vector3.UP, true)
func _on_interact():
interactor.interact_nearest()
interactor.interact_nearest()
func _on_fire():
if is_weapon_ready:
print('firing weapon')
if is_weapon_ready:
equipment.use()
func on_save():
return {
position = position,
rotation = rotation
}
return {
position = position,
rotation = rotation
}
func on_before_load():
pass
pass
func on_load(data: Dictionary):
position = data.position
rotation = data.rotation
position = data.position
rotation = data.rotation

1
godot/src/raycast.gd.uid Normal file
View file

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

18
godot/src/usable.gd Normal file
View file

@ -0,0 +1,18 @@
class_name Usable extends Node
signal used
@export var enabled: bool = true
func enable() -> void:
enabled = true
func disable() -> void:
enabled = false
func set_enabled(is_enabled: bool) -> void:
self.enabled = is_enabled
func use():
if enabled:
used.emit()

1
godot/src/usable.gd.uid Normal file
View file

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