diff --git a/levels/prototype_scene.tscn b/levels/prototype_scene.tscn index 1b040bf..c31cf6f 100644 --- a/levels/prototype_scene.tscn +++ b/levels/prototype_scene.tscn @@ -1,10 +1,12 @@ -[gd_scene load_steps=9 format=3 uid="uid://cqrh2cc7m2i7f"] +[gd_scene load_steps=11 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/team_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"] -[ext_resource type="Script" uid="uid://be7l33prlm8gh" path="res://scripts/multiplayer/dynamic_objects_container.gd" id="5_y6i55"] +[ext_resource type="Script" uid="uid://be7l33prlm8gh" path="res://scripts/multiplayer/dynamic_objects_spawner.gd" id="5_y6i55"] +[ext_resource type="Script" uid="uid://dncldab5y4yod" path="res://scripts/item_spawner.gd" id="6_61ure"] +[ext_resource type="PackedScene" uid="uid://cxdgk74ln5xpn" path="res://scenes/weapons/droppable_bomb.tscn" id="6_bno23"] [sub_resource type="Animation" id="Animation_y6i55"] length = 0.001 @@ -55,6 +57,7 @@ environment = ExtResource("1_i6jab") [node name="CSGCombiner3D" type="CSGCombiner3D" parent="."] use_collision = true +collision_mask = 9 [node name="CSGBox3D2" type="CSGBox3D" parent="CSGCombiner3D"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3.774414, 2.211084, -2.7798462) @@ -132,5 +135,10 @@ spawn_path = NodePath("..") script = ExtResource("5_y6i55") [node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="DynamicObjectsContainer"] -_spawnable_scenes = PackedStringArray("uid://dtbpyfdawb02b") +_spawnable_scenes = PackedStringArray("uid://dtbpyfdawb02b", "uid://cxdgk74ln5xpn") spawn_path = NodePath("..") + +[node name="Bomb" type="Node3D" parent="DynamicObjectsContainer"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -28.858309, 4.6431036, 12.873563) +script = ExtResource("6_61ure") +item = ExtResource("6_bno23") diff --git a/scenes/molikman.tscn b/scenes/molikman.tscn index e076db9..fa9d09b 100644 --- a/scenes/molikman.tscn +++ b/scenes/molikman.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=24 format=3 uid="uid://dpsr6ug3pkb40"] +[gd_scene load_steps=25 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"] @@ -16,7 +16,7 @@ [ext_resource type="Script" uid="uid://u0e2b2mvij1k" path="res://scripts/player/states/standing.gd" id="10_a8ls1"] [ext_resource type="Script" uid="uid://cwasvwhm5yg0o" path="res://scripts/player/states/walk.gd" id="11_qfm1y"] [ext_resource type="Script" uid="uid://cq4i0afwesdm3" path="res://scripts/player/states/falling.gd" id="12_fulsm"] -[ext_resource type="PackedScene" uid="uid://bxdatd1ilfgmc" path="res://scenes/weapons/bomb.tscn" id="17_fjvrb"] +[ext_resource type="Script" uid="uid://xsgfbuyje35p" path="res://scripts/player/player_pickup.gd" id="17_fjvrb"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_u8vuu"] resource_local_to_scene = true @@ -125,6 +125,10 @@ _data = { &"crouch": SubResource("Animation_oprun") } +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_3xmak"] +radius = 0.82177734 +height = 3.7087402 + [node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("weapon_models")] collision_layer = 2 collision_mask = 3 @@ -252,10 +256,9 @@ script = ExtResource("12_fulsm") player = NodePath("../..") SPEED = 5.0 -[node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("default_pistol", "default_knife", "animation_player", "camera", "player")] +[node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("default_pistol", "animation_player", "camera", "player")] script = ExtResource("4_qlg0r") default_pistol = NodePath("StartingPistol") -default_knife = NodePath("Bomb") animation_player = NodePath("../Camera3D/molikman_hands/AnimationPlayer") camera = NodePath("../Camera3D") player = NodePath("..") @@ -265,7 +268,8 @@ player = NodePath("..") [node name="Shoot" parent="WeaponSystem/StartingPistol" index="1" node_paths=PackedStringArray("raycast")] raycast = NodePath("../../../Camera3D/RayCast3D") -[node name="Bomb" parent="WeaponSystem" instance=ExtResource("17_fjvrb")] +[node name="WeaponSpawner" type="MultiplayerSpawner" parent="WeaponSystem"] +spawn_path = NodePath("..") [node name="AnimationPlayer" type="AnimationPlayer" parent="."] libraries = { @@ -278,6 +282,17 @@ player = NodePath("..") layer = true inverse = true +[node name="PickupRange" type="Area3D" parent="." node_paths=PackedStringArray("weapon_spawner", "weapon_system")] +collision_layer = 0 +collision_mask = 8 +script = ExtResource("17_fjvrb") +weapon_spawner = NodePath("../WeaponSystem/WeaponSpawner") +weapon_system = NodePath("../WeaponSystem") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="PickupRange"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.8543701, 0) +shape = SubResource("CapsuleShape3D_3xmak") + [connection signal="spawned" from="." to="Camera3D/RayCast3D/TeamUpdater" method="on_spawned"] [connection signal="spawned" from="." to="TeamUpdater" method="on_spawned"] diff --git a/scenes/weapons/droppable_bomb.tscn b/scenes/weapons/droppable_bomb.tscn new file mode 100644 index 0000000..de5b894 --- /dev/null +++ b/scenes/weapons/droppable_bomb.tscn @@ -0,0 +1,38 @@ +[gd_scene load_steps=6 format=3 uid="uid://cxdgk74ln5xpn"] + +[ext_resource type="Script" uid="uid://cskgqgkr7pmb0" path="res://scripts/weapon_system/dropped_weapon.gd" id="1_hsebh"] +[ext_resource type="PackedScene" uid="uid://dftij0fdq3lbr" path="res://models/weapons/Bomb.glb" id="1_pcfvq"] +[ext_resource type="PackedScene" uid="uid://bxdatd1ilfgmc" path="res://scenes/weapons/bomb.tscn" id="2_ucc3u"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_hsebh"] +size = Vector3(1, 0.25274658, 0.7492676) + +[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_ddvbd"] +properties/0/path = NodePath(".:position") +properties/0/spawn = true +properties/0/replication_mode = 1 +properties/1/path = NodePath(".:rotation") +properties/1/spawn = true +properties/1/replication_mode = 1 + +[node name="DroppableBomb" type="RigidBody3D" node_paths=PackedStringArray("weapon")] +collision_layer = 8 +collision_mask = 9 +script = ExtResource("1_hsebh") +slot = &"bomb" +weapon = NodePath("BombWeapon") + +[node name="BombWeapon" parent="." instance=ExtResource("2_ucc3u")] + +[node name="Bomb" parent="." instance=ExtResource("1_pcfvq")] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -3.0517578e-05, 0.0010986328) +shape = SubResource("BoxShape3D_hsebh") + +[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] +replication_config = SubResource("SceneReplicationConfig_ddvbd") + +[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."] +_spawnable_scenes = PackedStringArray("uid://bxdatd1ilfgmc") +spawn_path = NodePath("..") diff --git a/scripts/item_spawner.gd b/scripts/item_spawner.gd new file mode 100644 index 0000000..9822f71 --- /dev/null +++ b/scripts/item_spawner.gd @@ -0,0 +1,13 @@ +extends Node3D + +@export var item: PackedScene + +func _ready() -> void: + deferred_spawn.call_deferred() + +func deferred_spawn(): + if multiplayer.is_server(): + var node = item.instantiate() + add_sibling(node,true) + node.global_position = global_position + queue_free() diff --git a/scripts/item_spawner.gd.uid b/scripts/item_spawner.gd.uid new file mode 100644 index 0000000..83011cf --- /dev/null +++ b/scripts/item_spawner.gd.uid @@ -0,0 +1 @@ +uid://dncldab5y4yod diff --git a/scripts/multiplayer/dynamic_objects_container.gd b/scripts/multiplayer/dynamic_objects_spawner.gd similarity index 100% rename from scripts/multiplayer/dynamic_objects_container.gd rename to scripts/multiplayer/dynamic_objects_spawner.gd diff --git a/scripts/multiplayer/dynamic_objects_container.gd.uid b/scripts/multiplayer/dynamic_objects_spawner.gd.uid similarity index 100% rename from scripts/multiplayer/dynamic_objects_container.gd.uid rename to scripts/multiplayer/dynamic_objects_spawner.gd.uid diff --git a/scripts/multiplayer/session.gd b/scripts/multiplayer/session.gd index e12aad1..980e592 100644 --- a/scripts/multiplayer/session.gd +++ b/scripts/multiplayer/session.gd @@ -3,7 +3,8 @@ extends Node enum TEAMS { DEFENCE, ATTACK, - SPECTATE + SPECTATE, + UNASSIGNED } var dynamic_objects_container: Node3D diff --git a/scripts/player/player_pickup.gd b/scripts/player/player_pickup.gd new file mode 100644 index 0000000..9655848 --- /dev/null +++ b/scripts/player/player_pickup.gd @@ -0,0 +1,22 @@ +extends Area3D + +@export var weapon_spawner: MultiplayerSpawner +@export var weapon_system: WeaponSystem + +func _ready() -> void: + if is_multiplayer_authority() == false: return + + body_entered.connect(on_body_entered) + +func on_body_entered(body: Node3D): + if body is DroppableWeapon: + if weapon_system.can_add(body.slot) == false: + return + var weapon = weapon_spawner.spawn({ + "ammo": body.weapon.ammo, + "remaining_ammo": body.weapon.remaining_ammo, + "scene_file_path": body.weapon.scene_file_path, + "slot": body.slot + }) + weapon_system.on_weapon_added(weapon) + body.queue_free() diff --git a/scripts/player/player_pickup.gd.uid b/scripts/player/player_pickup.gd.uid new file mode 100644 index 0000000..fc5c6a4 --- /dev/null +++ b/scripts/player/player_pickup.gd.uid @@ -0,0 +1 @@ +uid://xsgfbuyje35p diff --git a/scripts/state_machine/substate_machine.gd b/scripts/state_machine/substate_machine.gd index 26b2384..5e29246 100644 --- a/scripts/state_machine/substate_machine.gd +++ b/scripts/state_machine/substate_machine.gd @@ -8,7 +8,8 @@ func enter() -> void: change_state(enter_state) func exit() -> void: - clear_state.rpc() + if is_multiplayer_authority(): + clear_state.rpc() func update(delta: float) -> void: if current_state == null: diff --git a/scripts/weapon_system/dropped_weapon.gd b/scripts/weapon_system/dropped_weapon.gd new file mode 100644 index 0000000..5be6418 --- /dev/null +++ b/scripts/weapon_system/dropped_weapon.gd @@ -0,0 +1,7 @@ +extends RigidBody3D + +class_name DroppableWeapon + +@export var slot: StringName +@export var weapon: WeaponSubStateMachine +@export var team: Session.TEAMS diff --git a/scripts/weapon_system/dropped_weapon.gd.uid b/scripts/weapon_system/dropped_weapon.gd.uid new file mode 100644 index 0000000..ec3aa6f --- /dev/null +++ b/scripts/weapon_system/dropped_weapon.gd.uid @@ -0,0 +1 @@ +uid://cskgqgkr7pmb0 diff --git a/scripts/weapon_system/weapon_state.gd b/scripts/weapon_system/weapon_state.gd index 1b7750c..b00dc16 100644 --- a/scripts/weapon_system/weapon_state.gd +++ b/scripts/weapon_system/weapon_state.gd @@ -3,6 +3,7 @@ extends State class_name WeaponState +@warning_ignore("unused_signal") signal return_to_previous var machine: WeaponSubStateMachine diff --git a/scripts/weapon_system/weapon_substate_machine.gd b/scripts/weapon_system/weapon_substate_machine.gd index e9f4cd4..b1cb38a 100644 --- a/scripts/weapon_system/weapon_substate_machine.gd +++ b/scripts/weapon_system/weapon_substate_machine.gd @@ -3,7 +3,8 @@ extends SubStateMachine class_name WeaponSubStateMachine @export var animation_prefix: StringName -@export var model: PackedScene +@export var droppable: PackedScene +@export var self_scene: PackedScene @export var visibility_target: StringName @export var max_ammo: int @@ -12,6 +13,8 @@ class_name WeaponSubStateMachine @export var can_be_previous: bool = true +var slot: StringName + signal request_return var system: WeaponSystem diff --git a/scripts/weapon_system/weapon_system.gd b/scripts/weapon_system/weapon_system.gd index 45eef7d..52d4078 100644 --- a/scripts/weapon_system/weapon_system.gd +++ b/scripts/weapon_system/weapon_system.gd @@ -27,9 +27,10 @@ signal switched_to(state: WeaponSubStateMachine) func _ready() -> void: current_state = default_pistol - add(default_knife,"knife") add(default_pistol,"secondary") current_state.enter() + $WeaponSpawner.spawn_function = pick_up_weapon + $WeaponSpawner.spawned.connect(on_weapon_added) func can_add(slot: StringName) -> bool: return slots.has(slot) and slots[slot] == null @@ -38,12 +39,13 @@ func can_add(slot: StringName) -> bool: func add(state: WeaponSubStateMachine, slot: StringName) -> void: if can_add(slot) == false: return - print('leech') if state.get_parent() == null: - add_child(state) + add_child(state, true) if state.get_parent() != self: - state.reparent(self) + state.get_parent().remove_child(state) + add_child(state,true) + state.ready.emit() slots[slot] = state state.system = self @@ -67,6 +69,25 @@ func switch(to: StringName): update_remotes.rpc(to) +func drop(): pass + +# Spawn function +# Data should be a dictionary with these keys: +# ammo +# remaining_ammo +# scene_file_path +func pick_up_weapon(data: Variant) -> Node: + if data.has("ammo") == false or data.has("remaining_ammo") == false or data.has("scene_file_path") == false or data.has("slot") == false: + return null + var scene: WeaponSubStateMachine = load(data["scene_file_path"]).instantiate() + scene.ammo = data["ammo"] + scene.remaining_ammo = data["remaining_ammo"] + scene.slot = data["slot"] + return scene + +func on_weapon_added(weapon: Node): + add(weapon,weapon.slot) + func return_to_previous(): if last_slot != "": switch(last_slot)