From 6da70f9bfe16d17dd20aea34cb042ebbfcc25e48 Mon Sep 17 00:00:00 2001 From: Twirpytherobot Date: Sat, 15 Nov 2025 16:44:58 +0000 Subject: [PATCH] Weapon and shield slots --- level/resources/weapon_shield.tres | 9 +- level/scenes/level.tscn | 6 +- level/scenes/player.tscn | 108 ++++++++++++------- level/scenes/weapons/shield_mesh.tscn | 2 +- level/scenes/weapons/sword_mesh.tscn | 6 +- level/scripts/player.gd | 147 ++++++++++++++++++++------ level/scripts/weapon_data.gd | 3 + 7 files changed, 199 insertions(+), 82 deletions(-) diff --git a/level/resources/weapon_shield.tres b/level/resources/weapon_shield.tres index 447546b..9416b06 100644 --- a/level/resources/weapon_shield.tres +++ b/level/resources/weapon_shield.tres @@ -1,16 +1,15 @@ -[gd_resource type="Resource" script_class="WeaponData" load_steps=3 format=3] +[gd_resource type="Resource" script_class="WeaponData" load_steps=3 format=3 uid="uid://ujavkmbq6nar"] -[ext_resource type="Script" path="res://level/scripts/weapon_data.gd" id="1"] -[ext_resource type="PackedScene" path="res://level/scenes/weapons/shield_mesh.tscn" id="2"] +[ext_resource type="Script" uid="uid://d2homvlmrg6xs" path="res://level/scripts/weapon_data.gd" id="1"] +[ext_resource type="PackedScene" uid="uid://rbvk4mg40ceg" path="res://level/scenes/weapons/shield_mesh.tscn" id="2"] [resource] script = ExtResource("1") weapon_name = "Wooden Shield" description = "A sturdy wooden shield. Can be used to bash enemies." +hand_type = 1 damage = 8.0 attack_range = 2.5 attack_cooldown = 0.8 -attack_animation = "Attack1" mesh_scene = ExtResource("2") -pickup_radius = 1.5 weight = 3.0 diff --git a/level/scenes/level.tscn b/level/scenes/level.tscn index 2b18ce2..46a0ca0 100644 --- a/level/scenes/level.tscn +++ b/level/scenes/level.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=18 format=3 uid="uid://dugaivbj1o66n"] +[gd_scene load_steps=19 format=3 uid="uid://dugaivbj1o66n"] [ext_resource type="Script" uid="uid://d0dgljwwl463n" path="res://level/scripts/level.gd" id="1_e1sh7"] [ext_resource type="PackedScene" uid="uid://cffjduipbb3s5" path="res://level/scenes/player.tscn" id="1_uvcbi"] [ext_resource type="FontFile" uid="uid://diapabmalpcrj" path="res://assets/fonts/Kurland.ttf" id="3_icc4p"] [ext_resource type="PackedScene" uid="uid://b48oxbcgxu3d8" path="res://assets/Objects/Colosseum_10.fbx" id="4_u750a"] +[ext_resource type="PackedScene" path="res://level/scenes/weapons/world_weapon_shield.tscn" id="5_xerh7"] [sub_resource type="PlaneMesh" id="PlaneMesh_r5xs5"] size = Vector2(90, 90) @@ -346,6 +347,9 @@ offset_bottom = 40.0 [node name="Colosseum_10" parent="." instance=ExtResource("4_u750a")] transform = Transform3D(15, 0, 0, 0, 15, 0, 0, 0, 15, 1.301034, -1.2294581, 2.0630608) +[node name="WorldWeaponShield" parent="." instance=ExtResource("5_xerh7")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 6.6566563, 0.024999619, 8.476057) + [connection signal="pressed" from="Menu/MainContainer/MainMenu/Buttons/Host" to="." method="_on_host_pressed"] [connection signal="pressed" from="Menu/MainContainer/MainMenu/Buttons/Join" to="." method="_on_join_pressed"] [connection signal="pressed" from="Menu/MainContainer/MainMenu/Option4/Quit" to="." method="_on_quit_pressed"] diff --git a/level/scenes/player.tscn b/level/scenes/player.tscn index a7019a1..757ac8b 100644 --- a/level/scenes/player.tscn +++ b/level/scenes/player.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=47 format=4 uid="uid://cffjduipbb3s5"] +[gd_scene load_steps=48 format=4 uid="uid://cffjduipbb3s5"] [ext_resource type="Script" uid="uid://c2si8gkbnde0c" path="res://level/scripts/player.gd" id="1_tdh26"] [ext_resource type="Texture2D" uid="uid://bdg48m6l86q8i" path="res://assets/characters/player/3DGodotRobot_GodotPalette.png" id="1_w11jc"] @@ -666,6 +666,18 @@ tracks/29/path = NodePath("RobotArmature/Skeleton3D:forearm.R") tracks/29/interp = 1 tracks/29/loop_wrap = true tracks/29/keys = PackedFloat32Array(0, 1, -0.0175777, 0.091351, -0.0271132, 0.995294) +tracks/30/type = "value" +tracks/30/imported = false +tracks/30/enabled = true +tracks/30/path = NodePath("RobotArmature/Skeleton3D/WeaponPoint:position") +tracks/30/interp = 1 +tracks/30/loop_wrap = true +tracks/30/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(-0.79307234, 0.808052, 0.11223535)] +} [sub_resource type="Animation" id="Animation_xmmkv"] resource_name = "Crouch" @@ -4742,6 +4754,9 @@ tracks/29/interp = 1 tracks/29/loop_wrap = true tracks/29/keys = PackedFloat32Array(0, 1, -0.0175777, 0.091351, -0.0271132, 0.995294) +[sub_resource type="Animation" id="Animation_2i6bm"] +length = 0.001 + [sub_resource type="AnimationLibrary" id="AnimationLibrary_f1v7x"] _data = { &"Attack1": SubResource("Animation_jou0i"), @@ -4759,6 +4774,7 @@ _data = { &"Jump3": SubResource("Animation_uw5ew"), &"Kick": SubResource("Animation_huvcy"), &"LongJump": SubResource("Animation_utfbj"), +&"RESET": SubResource("Animation_2i6bm"), &"Run": SubResource("Animation_822pa"), &"Sprint": SubResource("Animation_n4rw8"), &"T-pose": SubResource("Animation_f42pc"), @@ -4780,13 +4796,16 @@ properties/3/path = NodePath("3DGodotRobot:rotation") properties/3/spawn = true properties/3/replication_mode = 1 -[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("_body", "_spring_arm_offset", "_weapon_attachment")] +[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("_body", "_spring_arm_offset", "_weapon_attachment", "_weapon_container", "_offhand_attachment", "_offhand_container")] transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, 0, 0) collision_mask = 3 script = ExtResource("1_tdh26") _body = NodePath("3DGodotRobot") _spring_arm_offset = NodePath("SpringArmOffset") _weapon_attachment = NodePath("3DGodotRobot/RobotArmature/Skeleton3D/WeaponPoint") +_weapon_container = NodePath("3DGodotRobot/RobotArmature/Skeleton3D/WeaponPoint/WeaponContainer") +_offhand_attachment = NodePath("3DGodotRobot/RobotArmature/Skeleton3D/OffhandPoint") +_offhand_container = NodePath("3DGodotRobot/RobotArmature/Skeleton3D/OffhandPoint/OffhandContainer") blue_texture = ExtResource("4_max2b") yellow_texture = ExtResource("3_l3dv8") green_texture = ExtResource("4_74ree") @@ -4810,50 +4829,50 @@ bones/0/name = "spine" bones/0/parent = -1 bones/0/rest = Transform3D(1, 9.10383e-15, 2.38419e-07, 7.10847e-09, 0.999555, -0.0298151, -2.38313e-07, 0.0298151, 0.999556, 8.26265e-18, 0.90683, 0.0298551) bones/0/enabled = true -bones/0/position = Vector3(-3.5256e-16, 0.861288, 0.0298551) -bones/0/rotation = Quaternion(0.014909198, 1.1919598e-07, 1.7773096e-09, 0.99988884) -bones/0/scale = Vector3(1, 1, 1) +bones/0/position = Vector3(-3.421493e-16, 0.85448635, 0.0298551) +bones/0/rotation = Quaternion(0.035353143, 1.1913432e-07, 4.2144204e-09, 0.9993749) +bones/0/scale = Vector3(1, 0.9999995, 1.0000005) bones/1/name = "spine.001" bones/1/parent = 0 bones/1/rest = Transform3D(1, -1.40362e-08, 4.13501e-10, 1.40362e-08, 0.998266, -0.0588722, 4.13562e-10, 0.0588722, 0.998266, -3.15279e-15, 0.264173, 5.80784e-09) bones/1/enabled = true bones/1/position = Vector3(-3.15279e-15, 0.264173, 5.80784e-09) -bones/1/rotation = Quaternion(0.029448908, -1.5218204e-14, 7.0211716e-09, 0.9995663) -bones/1/scale = Vector3(1, 1, 1) +bones/1/rotation = Quaternion(0.031719886, 0.05703742, -0.0043385546, 0.99785864) +bones/1/scale = Vector3(1, 1.0000004, 1.0000004) bones/2/name = "spine.002" bones/2/parent = 1 bones/2/rest = Transform3D(1, 2.54997e-08, -4.7547e-07, 2.54996e-08, 0.994264, 0.106953, 4.7547e-07, -0.106953, 0.994264, -3.69508e-15, 0.169598, 7.45058e-09) bones/2/enabled = true bones/2/position = Vector3(-3.69508e-15, 0.169598, 7.45058e-09) -bones/2/rotation = Quaternion(-0.0535535, -2.38076e-07, -2.22364e-15, 0.998565) -bones/2/scale = Vector3(1, 1, 1) +bones/2/rotation = Quaternion(-0.053553354, -2.3807664e-07, -2.223637e-15, 0.998565) +bones/2/scale = Vector3(1, 0.99999994, 0.99999994) bones/3/name = "spine.003" bones/3/parent = 2 bones/3/rest = Transform3D(1, -3.97482e-09, 2.38385e-07, -1.33227e-15, 0.999861, 0.0166716, -2.38419e-07, -0.0166716, 0.999861, 2.27648e-15, 0.138171, 1.86161e-09) bones/3/enabled = true bones/3/position = Vector3(2.27648e-15, 0.138171, 1.86161e-09) -bones/3/rotation = Quaternion(-0.0083361, 1.19205e-07, 9.93739e-10, 0.999965) -bones/3/scale = Vector3(1, 1, 1) +bones/3/rotation = Quaternion(-0.008336091, 1.1920537e-07, 9.937406e-10, 0.99996525) +bones/3/scale = Vector3(1, 0.99999994, 0.99999994) bones/4/name = "spine.004" bones/4/parent = 3 bones/4/rest = Transform3D(1, 6.66134e-16, -2.38419e-07, -2.57501e-09, 0.999942, -0.0108004, 2.38405e-07, 0.0108004, 0.999942, -2.88374e-16, 0.176079, -0.0108779) bones/4/enabled = true -bones/4/position = Vector3(-3.65722e-16, 0.151501, -0.011741) -bones/4/rotation = Quaternion(0.005400273, -1.1920807e-07, -6.4376326e-10, 0.9999855) -bones/4/scale = Vector3(1, 1, 1) +bones/4/position = Vector3(0.0010912558, 0.1568266, -0.012192782) +bones/4/rotation = Quaternion(0.0028387355, -0.048486076, -0.010282211, 0.99876696) +bones/4/scale = Vector3(1, 1.0000004, 1.0000004) bones/5/name = "Head" bones/5/parent = 4 bones/5/rest = Transform3D(1, 3.91584e-09, -3.22583e-11, -3.91584e-09, 0.999865, -0.0164242, -3.20606e-11, 0.0164242, 0.999865, -8.70283e-16, 0.138682, 3.72529e-09) bones/5/enabled = true bones/5/position = Vector3(-8.70283e-16, 0.138682, 3.72529e-09) bones/5/rotation = Quaternion(0.008212383, -4.9429028e-14, -1.9579807e-09, 0.99996626) -bones/5/scale = Vector3(1, 1, 1) +bones/5/scale = Vector3(1, 0.9999999, 0.9999999) bones/6/name = "HeadTop" bones/6/parent = 5 bones/6/rest = Transform3D(1, 1.87855e-09, 2.38411e-07, -2.22045e-16, 0.999969, -0.00787923, -2.38419e-07, 0.00787923, 0.999969, 2.16882e-17, 0.646177, 1.87855e-09) bones/6/enabled = true bones/6/position = Vector3(2.16882e-17, 0.646177, 1.87855e-09) -bones/6/rotation = Quaternion(0.00393965, 1.19208e-07, -4.69642e-10, 0.999992) +bones/6/rotation = Quaternion(0.003939646, 1.1920858e-07, -4.696433e-10, 0.99999225) bones/6/scale = Vector3(1, 1, 1) bones/7/name = "Eyes" bones/7/parent = 5 @@ -4875,21 +4894,21 @@ bones/9/rest = Transform3D(0.0360757, 0.999142, 0.0203239, -0.0345019, -0.019079 bones/9/enabled = true bones/9/position = Vector3(0.267321, 0.0764983, -0.028224) bones/9/rotation = Quaternion(-0.523067, -0.45780203, -0.521926, 0.49438003) -bones/9/scale = Vector3(1, 1, 1) +bones/9/scale = Vector3(0.9999997, 0.9999996, 1.0000005) bones/10/name = "upper_arm.L" bones/10/parent = 9 bones/10/rest = Transform3D(-0.106441, 0.0606935, 0.992465, -0.00297219, 0.998111, -0.0613576, -0.994315, -0.00948077, -0.10606, 0.00943596, 0.223043, -8.37785e-05) bones/10/enabled = true bones/10/position = Vector3(0.00943596, 0.223043, -8.37785e-05) -bones/10/rotation = Quaternion(-0.35644102, 0.6178471, -0.43310705, 0.55102915) -bones/10/scale = Vector3(1, 1, 1) +bones/10/rotation = Quaternion(-0.32633743, 0.63426304, -0.4061254, 0.5712062) +bones/10/scale = Vector3(1.0000004, 0.9999996, 1.0000001) bones/11/name = "forearm.L" bones/11/parent = 10 bones/11/rest = Transform3D(0.98184, -0.0507598, -0.182795, 0.0571828, 0.997912, 0.0300364, 0.180889, -0.0399437, 0.982692, -1.57789e-07, 0.280382, -1.0906e-08) bones/11/enabled = true bones/11/position = Vector3(-1.57789e-07, 0.280382, -1.0906e-08) bones/11/rotation = Quaternion(-0.017577708, -0.09135104, 0.027113209, 0.9952944) -bones/11/scale = Vector3(1, 1, 1) +bones/11/scale = Vector3(1.0000002, 1.0000001, 0.9999999) bones/12/name = "hand.L" bones/12/parent = 11 bones/12/rest = Transform3D(0.998796, 0.0360371, 0.0332857, -0.0346117, 0.998499, -0.0424496, -0.0347655, 0.0412464, 0.998544, -3.72351e-07, 0.225629, 2.17875e-08) @@ -4903,21 +4922,21 @@ bones/13/rest = Transform3D(0.0360757, -0.999142, -0.0203239, 0.0345019, -0.0190 bones/13/enabled = true bones/13/position = Vector3(-0.267321, 0.0764983, -0.028224) bones/13/rotation = Quaternion(-0.523067, 0.45780203, 0.521926, 0.49438003) -bones/13/scale = Vector3(1, 1, 1) +bones/13/scale = Vector3(0.9999997, 0.9999996, 1.0000005) bones/14/name = "upper_arm.R" bones/14/parent = 13 bones/14/rest = Transform3D(-0.106441, -0.0606935, -0.992465, 0.00297219, 0.998111, -0.0613576, 0.994315, -0.00948077, -0.10606, -0.00943596, 0.223043, -8.37785e-05) bones/14/enabled = true bones/14/position = Vector3(-0.00943596, 0.223043, -8.37785e-05) -bones/14/rotation = Quaternion(-0.35644102, -0.6178471, 0.43310705, 0.55102915) -bones/14/scale = Vector3(1, 1, 1) +bones/14/rotation = Quaternion(-0.33203182, -0.63130087, 0.41124824, 0.56752884) +bones/14/scale = Vector3(1.0000004, 0.9999996, 1.0000001) bones/15/name = "forearm.R" bones/15/parent = 14 bones/15/rest = Transform3D(0.98184, 0.0507598, 0.182795, -0.0571828, 0.997912, 0.0300364, -0.180889, -0.0399437, 0.982692, 1.57789e-07, 0.280382, -1.0906e-08) bones/15/enabled = true bones/15/position = Vector3(1.57789e-07, 0.280382, -1.0906e-08) bones/15/rotation = Quaternion(-0.017577708, 0.09135104, -0.027113209, 0.9952944) -bones/15/scale = Vector3(1, 1, 1) +bones/15/scale = Vector3(1.0000002, 1.0000001, 0.9999999) bones/16/name = "hand.R" bones/16/parent = 15 bones/16/rest = Transform3D(0.998796, -0.0360371, -0.0332857, 0.0346117, 0.998499, -0.0424496, 0.0347655, 0.0412464, 0.998544, 3.72351e-07, 0.225629, 2.17875e-08) @@ -4930,57 +4949,57 @@ bones/17/parent = 0 bones/17/rest = Transform3D(0.999169, 0.0422695, -0.00959818, 0.0419598, -0.998643, -0.0308697, -0.0108906, 0.0304362, -0.999534, 0.276084, 0.0659952, -0.00346868) bones/17/enabled = true bones/17/position = Vector3(0.276084, 0.0659952, -0.00346868) -bones/17/rotation = Quaternion(0.9914149, 0.020339603, -0.0074862493, 0.12894498) -bones/17/scale = Vector3(1.00011, 1, 1.00006) +bones/17/rotation = Quaternion(0.99330246, 0.02045423, -0.0071681803, 0.11349219) +bones/17/scale = Vector3(1.000109, 1.0000004, 1.0000566) bones/18/name = "shin.L" bones/18/parent = 17 bones/18/rest = Transform3D(0.998494, -0.0540184, 0.00956905, 0.0538958, 0.998466, 0.012631, -0.0102367, -0.0120962, 0.999874, -5.17625e-09, 0.374795, -3.10704e-09) bones/18/enabled = true bones/18/position = Vector3(-5.17625e-09, 0.374795, -3.10704e-09) bones/18/rotation = Quaternion(0.24962787, 0.008717706, 0.024973989, 0.9679805) -bones/18/scale = Vector3(1, 1, 1) +bones/18/scale = Vector3(0.99999994, 0.99999934, 0.9999995) bones/19/name = "foot.L" bones/19/parent = 18 bones/19/rest = Transform3D(0.999932, 0.00648757, 0.00970069, -0.0116559, 0.514227, 0.857575, 0.000575222, -0.85763, 0.514268, 8.31179e-09, 0.334457, -5.94341e-09) bones/19/enabled = true bones/19/position = Vector3(8.31179e-09, 0.334457, -5.94341e-09) bones/19/rotation = Quaternion(-0.60871375, 0.0033154185, -0.004791208, 0.7933686) -bones/19/scale = Vector3(1, 1, 1) +bones/19/scale = Vector3(1, 1.0000004, 1.0000002) bones/20/name = "toe.L" bones/20/parent = 19 bones/20/rest = Transform3D(-1, 5.912e-07, 3.60961e-06, -8.35906e-07, 0.923797, -0.382882, -3.56091e-06, -0.382882, -0.923797, 4.99904e-08, 0.251469, -2.97474e-08) bones/20/enabled = true bones/20/position = Vector3(4.99904e-08, 0.251469, -2.97474e-08) -bones/20/rotation = Quaternion(-6.23762e-08, 0.980764, -0.195196, 1.82779e-06) -bones/20/scale = Vector3(1, 1, 1) +bones/20/rotation = Quaternion(-6.2376095e-08, 0.9807643, -0.19519575, 1.8277893e-06) +bones/20/scale = Vector3(1, 0.99999976, 0.99999976) bones/21/name = "thigh.R" bones/21/parent = 0 bones/21/rest = Transform3D(0.999168, -0.0422695, 0.00959819, -0.0419598, -0.998643, -0.0308697, 0.0108906, 0.0304362, -0.999534, -0.276084, 0.0659953, -0.00346881) bones/21/enabled = true bones/21/position = Vector3(-0.276084, 0.0659953, -0.00346881) -bones/21/rotation = Quaternion(0.9914149, -0.020339599, 0.0074862596, 0.12894498) -bones/21/scale = Vector3(1.00011, 1, 1.00006) +bones/21/rotation = Quaternion(0.9856188, -0.020029755, 0.008274097, 0.16758825) +bones/21/scale = Vector3(1.0001079, 1.0000004, 1.0000566) bones/22/name = "shin.R" bones/22/parent = 21 bones/22/rest = Transform3D(0.998494, 0.0540184, -0.00956902, -0.0538959, 0.998467, 0.012631, 0.0102367, -0.0120963, 0.999875, -4.78381e-09, 0.374795, -3.10751e-09) bones/22/enabled = true bones/22/position = Vector3(-4.78381e-09, 0.374795, -3.10751e-09) -bones/22/rotation = Quaternion(0.24962787, -0.008717654, -0.024974087, 0.96798044) -bones/22/scale = Vector3(1, 1, 1) +bones/22/rotation = Quaternion(0.27024382, -0.0090048965, -0.02473223, 0.96243215) +bones/22/scale = Vector3(0.99999994, 1.0000004, 1.0000005) bones/23/name = "foot.R" bones/23/parent = 22 bones/23/rest = Transform3D(0.999932, -0.00648758, -0.0097007, 0.011656, 0.514227, 0.857575, -0.000575223, -0.85763, 0.514267, 2.49345e-08, 0.334457, -1.36528e-08) bones/23/enabled = true bones/23/position = Vector3(2.49345e-08, 0.334457, -1.36528e-08) -bones/23/rotation = Quaternion(-0.60871375, -0.0033154383, 0.004791258, 0.7933686) -bones/23/scale = Vector3(1, 1, 1) +bones/23/rotation = Quaternion(-0.610117, -0.0033239783, 0.0047853417, 0.7922899) +bones/23/scale = Vector3(1, 1.0000004, 0.99999976) bones/24/name = "toe.R" bones/24/parent = 23 bones/24/rest = Transform3D(-1, -5.89079e-07, -3.61003e-06, 8.38026e-07, 0.923797, -0.382882, 3.56048e-06, -0.382882, -0.923797, -1.90709e-08, 0.251469, -1.65948e-08) bones/24/enabled = true bones/24/position = Vector3(-1.90709e-08, 0.251469, -1.65948e-08) -bones/24/rotation = Quaternion(-6.34575e-08, -0.980764, 0.195196, 1.82779e-06) -bones/24/scale = Vector3(1, 1, 1) +bones/24/rotation = Quaternion(6.3457655e-08, 0.9807643, -0.19519575, -1.8277855e-06) +bones/24/scale = Vector3(1, 0.99999976, 0.99999976) [node name="Bottom" type="MeshInstance3D" parent="3DGodotRobot/RobotArmature/Skeleton3D"] mesh = SubResource("ArrayMesh_qcia5") @@ -5008,10 +5027,21 @@ skin = SubResource("Skin_gooby") surface_material_override/0 = SubResource("StandardMaterial3D_1ln88") [node name="WeaponPoint" type="BoneAttachment3D" parent="3DGodotRobot/RobotArmature/Skeleton3D"] -transform = Transform3D(-0.95200163, -0.30448738, -0.031308167, 0.30294672, -0.9519023, 0.045883153, -0.043773204, 0.03419612, 0.99845606, -0.64481956, 1.0056509, 0.02542795) +transform = Transform3D(-0.9240522, -0.37213418, 0.08743024, 0.3744485, -0.92718107, 0.011133001, 0.07692078, 0.04302559, 0.99610895, -0.67841375, 1.0102787, 0.113374464) bone_name = "hand.R" bone_idx = 16 +[node name="WeaponContainer" type="Node3D" parent="3DGodotRobot/RobotArmature/Skeleton3D/WeaponPoint"] +transform = Transform3D(0.9925028, -0.11405668, -0.043932315, -0.0413078, 0.025272824, -0.99882764, 0.115033016, 0.993153, 0.020371865, 0.055101156, 0.22179395, 0.05231151) + +[node name="OffhandPoint" type="BoneAttachment3D" parent="3DGodotRobot/RobotArmature/Skeleton3D"] +transform = Transform3D(-0.90828115, 0.39437774, 0.1396136, -0.3964694, -0.91794586, 0.013698864, 0.1335604, -0.04291001, 0.9901115, 0.6844704, 1.0179272, -0.042168632) +bone_name = "hand.L" +bone_idx = 12 + +[node name="OffhandContainer" type="Node3D" parent="3DGodotRobot/RobotArmature/Skeleton3D/OffhandPoint"] +transform = Transform3D(-0.99287575, 0.038754553, 0.11267701, 0.09095743, -0.36435834, 0.92680585, 0.07697269, 0.93045205, 0.35823718, 0.005940199, 0.3933037, 0.06604202) + [node name="AnimationPlayer" type="AnimationPlayer" parent="3DGodotRobot"] libraries = { &"": SubResource("AnimationLibrary_f1v7x") diff --git a/level/scenes/weapons/shield_mesh.tscn b/level/scenes/weapons/shield_mesh.tscn index af505e4..30dc85e 100644 --- a/level/scenes/weapons/shield_mesh.tscn +++ b/level/scenes/weapons/shield_mesh.tscn @@ -5,5 +5,5 @@ [node name="ShieldMesh" type="Node3D"] [node name="MeshInstance3D" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.28306955, -0.70267653) +transform = Transform3D(-0.79798645, 0, -0.056724526, 0, 0.8, 0, 0.056724526, 0, -0.79798645, 0.75818217, -1.2635326, 1.7408726) mesh = ExtResource("1") diff --git a/level/scenes/weapons/sword_mesh.tscn b/level/scenes/weapons/sword_mesh.tscn index b668832..fe3d2e1 100644 --- a/level/scenes/weapons/sword_mesh.tscn +++ b/level/scenes/weapons/sword_mesh.tscn @@ -1,9 +1,9 @@ [gd_scene load_steps=2 format=3 uid="uid://dyjfaq654xne3"] -[ext_resource type="ArrayMesh" uid="uid://dmottq5u3my52" path="res://assets/characters/Lobster/10029_Lobster_v1_iterations-2.obj" id="1_olchg"] +[ext_resource type="ArrayMesh" uid="uid://cc1kxfbkvpo2d" path="res://assets/Objects/swordlowpoly.obj" id="1"] [node name="SwordMesh" type="Node3D"] [node name="MeshInstance3D" type="MeshInstance3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.3645025, -0.7985528, -1.0164871) -mesh = ExtResource("1_olchg") +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.4839063, -2.9492104, -3.4711354) +mesh = ExtResource("1") diff --git a/level/scripts/player.gd b/level/scripts/player.gd index 5d5e9a4..954365c 100644 --- a/level/scripts/player.gd +++ b/level/scripts/player.gd @@ -13,7 +13,10 @@ enum SkinColor { BLUE, YELLOW, GREEN, RED } @export_category("Objects") @export var _body: Node3D = null @export var _spring_arm_offset: Node3D = null -@export var _weapon_attachment: BoneAttachment3D = null # WeaponPoint bone attachment +@export var _weapon_attachment: BoneAttachment3D = null # WeaponPoint bone attachment (main hand) +@export var _weapon_container: Node3D = null # Container node for main hand weapons +@export var _offhand_attachment: BoneAttachment3D = null # OffHandPoint bone attachment +@export var _offhand_container: Node3D = null # Container node for off-hand weapons @export_category("Skin Colors") @export var blue_texture : CompressedTexture2D @@ -30,7 +33,8 @@ var _current_speed: float var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") # Weapon system -var equipped_weapon: BaseWeapon = null +var equipped_weapon: BaseWeapon = null # Main hand weapon +var equipped_offhand: BaseWeapon = null # Off-hand weapon var _nearby_weapons: Array[WorldWeapon] = [] # Attack system @@ -84,6 +88,29 @@ func _ready(): else: push_warning("Could not find BoneAttachment3D for weapons!") + # Auto-find weapon container if not set + if _weapon_container == null and _weapon_attachment: + var container = _weapon_attachment.get_node_or_null("WeaponContainer") + if container: + _weapon_container = container + print("Auto-found main hand weapon container") + else: + push_warning("Could not find WeaponContainer! Weapons will attach directly to BoneAttachment3D.") + + # Auto-find off-hand attachment if not set + if _offhand_attachment == null: + var offhand_attach = get_node_or_null("3DGodotRobot/RobotArmature/Skeleton3D/OffHandPoint") + if offhand_attach: + _offhand_attachment = offhand_attach + print("Auto-found off-hand attachment point") + + # Auto-find off-hand container if not set + if _offhand_container == null and _offhand_attachment: + var container = _offhand_attachment.get_node_or_null("OffHandContainer") + if container: + _offhand_container = container + print("Auto-found off-hand weapon container") + func _physics_process(delta): # Check if multiplayer is ready if multiplayer.multiplayer_peer == null: @@ -144,15 +171,24 @@ func _process(delta): # Handle weapon pickup/drop if Input.is_action_just_pressed("pickup") and not is_dead: - print("Pickup pressed! Equipped: ", equipped_weapon != null, " Nearby: ", _nearby_weapons.size()) - if equipped_weapon: + print("Pickup pressed! Main: ", equipped_weapon != null, " OffHand: ", equipped_offhand != null, " Nearby: ", _nearby_weapons.size()) + + # Try to pickup nearby weapon + if _nearby_weapons.size() > 0: + _pickup_nearest_weapon() + # If no nearby weapons, drop what we're holding (main hand first, then off-hand) + elif equipped_weapon: # Tell server to drop (server will handle spawning) if multiplayer.is_server(): - drop_weapon() + drop_weapon(false) # main hand else: - rpc_id(1, "drop_weapon") # Only send to server - elif _nearby_weapons.size() > 0: - _pickup_nearest_weapon() + rpc_id(1, "drop_weapon", false) # Only send to server + elif equipped_offhand: + # Drop off-hand + if multiplayer.is_server(): + drop_weapon(true) # off-hand + else: + rpc_id(1, "drop_weapon", true) else: print("No weapons nearby to pick up") @@ -239,11 +275,16 @@ func _perform_attack(): if not is_multiplayer_authority() or is_dead: return - # Use equipped weapon if available + # Use main hand weapon if available if equipped_weapon and equipped_weapon.can_attack(): equipped_weapon.perform_attack() return + # Or use off-hand weapon if available + if equipped_offhand and equipped_offhand.can_attack(): + equipped_offhand.perform_attack() + return + # Fallback to default unarmed attack # Don't attack if already attacking if _body and _body.animation_player and _body.animation_player.current_animation == "Attack1": @@ -487,59 +528,84 @@ func equip_weapon_from_world(weapon_data_path: String): ## Equip a weapon with given data func equip_weapon(data: WeaponData): - # Unequip current weapon first - if equipped_weapon: - unequip_weapon() + # Determine which hand based on weapon type + var is_offhand = (data.hand_type == WeaponData.Hand.OFF_HAND) + + # Unequip current weapon in that hand first + if is_offhand: + if equipped_offhand: + unequip_weapon(true) + else: + if equipped_weapon: + unequip_weapon(false) + + # Determine where to attach the weapon + var attach_point: Node3D + if is_offhand: + attach_point = _offhand_container if _offhand_container else _offhand_attachment + else: + attach_point = _weapon_container if _weapon_container else _weapon_attachment - if not _weapon_attachment: - push_error("No weapon attachment point found!") + if not attach_point: + push_error("No weapon attachment point found for ", "off-hand" if is_offhand else "main hand") return # Create new weapon instance var weapon = BaseWeapon.new() weapon.weapon_data = data - weapon.name = "EquippedWeapon" + weapon.name = "EquippedOffHand" if is_offhand else "EquippedWeapon" weapon.set_owner_character(self) - # Attach to bone - _weapon_attachment.add_child(weapon) - equipped_weapon = weapon + # Attach to weapon container (or bone attachment if no container) + attach_point.add_child(weapon) + + # Store reference + if is_offhand: + equipped_offhand = weapon + else: + equipped_weapon = weapon if is_multiplayer_authority(): - print("Equipped: ", data.weapon_name) + print("Equipped: ", data.weapon_name, " to ", attach_point.name) ## Unequip current weapon (local only) -func unequip_weapon(): - if equipped_weapon: - equipped_weapon.queue_free() - equipped_weapon = null +func unequip_weapon(is_offhand: bool = false): + if is_offhand: + if equipped_offhand: + equipped_offhand.queue_free() + equipped_offhand = null + else: + if equipped_weapon: + equipped_weapon.queue_free() + equipped_weapon = null ## Sync unequip across all clients @rpc("any_peer", "call_local", "reliable") -func _unequip_weapon_sync(): - unequip_weapon() +func _unequip_weapon_sync(is_offhand: bool = false): + unequip_weapon(is_offhand) ## Drop currently equipped weapon @rpc("any_peer", "reliable") -func drop_weapon(): - print("drop_weapon called on peer ", multiplayer.get_unique_id(), " is_server: ", multiplayer.is_server(), " has weapon: ", equipped_weapon != null) +func drop_weapon(is_offhand: bool = false): + var has_weapon = equipped_offhand if is_offhand else equipped_weapon + print("drop_weapon called on peer ", multiplayer.get_unique_id(), " is_server: ", multiplayer.is_server(), " has weapon: ", has_weapon != null, " offhand: ", is_offhand) - if not equipped_weapon: - print("No weapon equipped, cannot drop") + if not has_weapon: + print("No weapon equipped in ", "off-hand" if is_offhand else "main hand", ", cannot drop") return # Only server spawns the world weapon if multiplayer.is_server(): print("Server spawning dropped weapon") - _spawn_world_weapon(equipped_weapon.weapon_data) + _spawn_world_weapon(has_weapon.weapon_data) # Tell all clients to unequip - rpc("_unequip_weapon_sync") + rpc("_unequip_weapon_sync", is_offhand) # Unequip locally - unequip_weapon() + unequip_weapon(is_offhand) if is_multiplayer_authority(): - print("Dropped weapon") + print("Dropped weapon from ", "off-hand" if is_offhand else "main hand") ## Spawn a weapon in the world (server only) func _spawn_world_weapon(data: WeaponData): @@ -585,6 +651,21 @@ func _pickup_nearest_weapon(): closest_weapon = weapon if closest_weapon: + # Check what hand this weapon goes in + var weapon_hand_type = closest_weapon.weapon_data.hand_type if closest_weapon.weapon_data else WeaponData.Hand.MAIN_HAND + var is_offhand = (weapon_hand_type == WeaponData.Hand.OFF_HAND) + var slot_occupied = equipped_offhand if is_offhand else equipped_weapon + + # If the slot is occupied, drop it first + if slot_occupied: + print("Slot occupied, dropping current weapon before picking up") + if multiplayer.is_server(): + drop_weapon(is_offhand) + else: + rpc_id(1, "drop_weapon", is_offhand) + # Wait a tiny bit for the drop to complete + await get_tree().create_timer(0.1).timeout + # Request server to pickup (server validates) if multiplayer.is_server(): closest_weapon.try_pickup(multiplayer.get_unique_id()) diff --git a/level/scripts/weapon_data.gd b/level/scripts/weapon_data.gd index a299ca7..a9f6777 100644 --- a/level/scripts/weapon_data.gd +++ b/level/scripts/weapon_data.gd @@ -4,9 +4,12 @@ class_name WeaponData ## Resource that stores weapon statistics and properties ## Can be reused for both equipped weapons and world pickups +enum Hand { MAIN_HAND, OFF_HAND, TWO_HAND } + @export_category("Weapon Info") @export var weapon_name: String = "Weapon" @export_multiline var description: String = "" +@export var hand_type: Hand = Hand.MAIN_HAND @export_category("Combat Stats") @export var damage: float = 10.0