diff --git a/levels/prototype_scene.tscn b/levels/prototype_scene.tscn index c31cf6f..0b2bb08 100644 --- a/levels/prototype_scene.tscn +++ b/levels/prototype_scene.tscn @@ -4,9 +4,9 @@ [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_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"] +[ext_resource type="Script" uid="uid://bqjv6l7hh0lix" path="res://scripts/multiplayer/spawn_system/dyn_objects_spawner.gd" id="6_oujx2"] [sub_resource type="Animation" id="Animation_y6i55"] length = 0.001 @@ -132,11 +132,11 @@ _spawnable_scenes = PackedStringArray("uid://dpsr6ug3pkb40", "uid://ckjabjcvgki6 spawn_path = NodePath("..") [node name="DynamicObjectsContainer" type="Node3D" parent="."] -script = ExtResource("5_y6i55") [node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="DynamicObjectsContainer"] -_spawnable_scenes = PackedStringArray("uid://dtbpyfdawb02b", "uid://cxdgk74ln5xpn") +_spawnable_scenes = PackedStringArray("uid://dtbpyfdawb02b", "uid://cxdgk74ln5xpn", "uid://dgfqppi21c2u0") spawn_path = NodePath("..") +script = ExtResource("6_oujx2") [node name="Bomb" type="Node3D" parent="DynamicObjectsContainer"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -28.858309, 4.6431036, 12.873563) diff --git a/models/weapons/starting_pistol.glb b/models/weapons/starting_pistol.glb index 32b8a05..43ed5da 100644 Binary files a/models/weapons/starting_pistol.glb and b/models/weapons/starting_pistol.glb differ diff --git a/scenes/molikman.tscn b/scenes/molikman.tscn index fa9d09b..be17a36 100644 --- a/scenes/molikman.tscn +++ b/scenes/molikman.tscn @@ -256,9 +256,10 @@ script = ExtResource("12_fulsm") player = NodePath("../..") SPEED = 5.0 -[node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("default_pistol", "animation_player", "camera", "player")] +[node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("default_pistol", "default_knife", "animation_player", "camera", "player")] script = ExtResource("4_qlg0r") default_pistol = NodePath("StartingPistol") +default_knife = NodePath("KnifePlaceholder") animation_player = NodePath("../Camera3D/molikman_hands/AnimationPlayer") camera = NodePath("../Camera3D") player = NodePath("..") @@ -268,6 +269,11 @@ player = NodePath("..") [node name="Shoot" parent="WeaponSystem/StartingPistol" index="1" node_paths=PackedStringArray("raycast")] raycast = NodePath("../../../Camera3D/RayCast3D") +[node name="KnifePlaceholder" parent="WeaponSystem" instance=ExtResource("7_fjrip")] + +[node name="Shoot" parent="WeaponSystem/KnifePlaceholder" index="1" node_paths=PackedStringArray("raycast")] +raycast = NodePath("../../../Camera3D/RayCast3D") + [node name="WeaponSpawner" type="MultiplayerSpawner" parent="WeaponSystem"] spawn_path = NodePath("..") @@ -298,3 +304,4 @@ shape = SubResource("CapsuleShape3D_3xmak") [editable path="Camera3D/molikman_hands"] [editable path="WeaponSystem/StartingPistol"] +[editable path="WeaponSystem/KnifePlaceholder"] diff --git a/scenes/weapons/bomb.tscn b/scenes/weapons/bomb.tscn index f828c8f..861089f 100644 --- a/scenes/weapons/bomb.tscn +++ b/scenes/weapons/bomb.tscn @@ -1,16 +1,16 @@ -[gd_scene load_steps=4 format=3 uid="uid://bxdatd1ilfgmc"] +[gd_scene load_steps=3 format=3 uid="uid://bxdatd1ilfgmc"] [ext_resource type="Script" uid="uid://e6lqknfl4ngt" path="res://scripts/weapon_system/weapon_substate_machine.gd" id="1_krsgt"] -[ext_resource type="PackedScene" uid="uid://dftij0fdq3lbr" path="res://models/weapons/Bomb.glb" id="2_1x0so"] [ext_resource type="Script" uid="uid://rx78vdadldm7" path="res://scripts/weapon_system/bomb/bomb_state.gd" id="2_870cc"] [node name="Bomb" type="Node" node_paths=PackedStringArray("enter_state")] script = ExtResource("1_krsgt") animation_prefix = &"baked_bomb_" -model = ExtResource("2_1x0so") +droppable = &"uid://cxdgk74ln5xpn" visibility_target = &"bomb" max_ammo = 1 can_be_previous = false +destroy_when_empty = true enter_state = NodePath("Main") metadata/_custom_type_script = "uid://e6lqknfl4ngt" diff --git a/scenes/weapons/droppable_sp.tscn b/scenes/weapons/droppable_sp.tscn new file mode 100644 index 0000000..1261136 --- /dev/null +++ b/scenes/weapons/droppable_sp.tscn @@ -0,0 +1,35 @@ +[gd_scene load_steps=6 format=3 uid="uid://dgfqppi21c2u0"] + +[ext_resource type="Script" uid="uid://cskgqgkr7pmb0" path="res://scripts/weapon_system/dropped_weapon.gd" id="1_jym52"] +[ext_resource type="PackedScene" uid="uid://djwjl8xll53vn" path="res://scenes/weapons/starting_pistol.tscn" id="2_jym52"] +[ext_resource type="PackedScene" uid="uid://d3sjs6efbshpk" path="res://models/weapons/starting_pistol.glb" id="3_jym52"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_hsebh"] +size = Vector3(0.07324219, 0.25274658, 0.46972656) + +[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="DroppableStartingPistol" type="RigidBody3D" node_paths=PackedStringArray("weapon")] +collision_layer = 8 +collision_mask = 9 +script = ExtResource("1_jym52") +slot = &"secondary" +weapon = NodePath("StartingPistol") +team = 3 + +[node name="StartingPistol" parent="." instance=ExtResource("2_jym52")] + +[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="starting_pistol" parent="." instance=ExtResource("3_jym52")] diff --git a/scenes/weapons/starting_pistol.tscn b/scenes/weapons/starting_pistol.tscn index 2b61eef..b0075ea 100644 --- a/scenes/weapons/starting_pistol.tscn +++ b/scenes/weapons/starting_pistol.tscn @@ -1,7 +1,6 @@ -[gd_scene load_steps=9 format=3 uid="uid://djwjl8xll53vn"] +[gd_scene load_steps=8 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="PackedScene" uid="uid://d3sjs6efbshpk" path="res://models/weapons/starting_pistol.glb" id="2_016ti"] [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"] @@ -22,7 +21,7 @@ point_count = 5 [node name="StartingPistol" type="Node" node_paths=PackedStringArray("enter_state")] script = ExtResource("1_g7s1i") animation_prefix = &"baked_sp_" -model = ExtResource("2_016ti") +droppable = &"uid://dgfqppi21c2u0" visibility_target = &"sp" max_ammo = 20 enter_state = NodePath("Intro") diff --git a/scripts/multiplayer/dynamic_objects_spawner.gd b/scripts/multiplayer/dynamic_objects_spawner.gd deleted file mode 100644 index d5593dc..0000000 --- a/scripts/multiplayer/dynamic_objects_spawner.gd +++ /dev/null @@ -1,5 +0,0 @@ -extends Node3D - - -func _ready() -> void: - Session.dynamic_objects_container = self diff --git a/scripts/multiplayer/dynamic_objects_spawner.gd.uid b/scripts/multiplayer/dynamic_objects_spawner.gd.uid deleted file mode 100644 index 0dbc95a..0000000 --- a/scripts/multiplayer/dynamic_objects_spawner.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://be7l33prlm8gh diff --git a/scripts/multiplayer/session.gd b/scripts/multiplayer/session.gd index 980e592..e0f9e1e 100644 --- a/scripts/multiplayer/session.gd +++ b/scripts/multiplayer/session.gd @@ -7,4 +7,29 @@ enum TEAMS { UNASSIGNED } -var dynamic_objects_container: Node3D +var dynamic_objects_spawner: MultiplayerSpawner + +func spawn(data: Dictionary) -> void: + spawn_internal.rpc_id(1,data) + +@rpc("any_peer","call_local","reliable") +func spawn_internal(data: Dictionary) -> void: + if multiplayer.is_server() == false: + printerr(str(multiplayer.get_remote_sender_id())+" tried to spawn internally on "+str(multiplayer.get_unique_id())) + return + + var object = dynamic_objects_spawner.spawn(data) + + if data.has("position"): + object.global_position = data.position + +func despawn(path: NodePath): + despawn_internal.rpc_id(1,path) + +@rpc("any_peer","call_local","reliable") +func despawn_internal(path: NodePath) -> void: + if multiplayer.is_server() == false: + printerr(str(multiplayer.get_remote_sender_id())+" tried to despawn internally on "+str(multiplayer.get_unique_id())) + return + + get_node(path).queue_free() diff --git a/scripts/multiplayer/spawn_system/dyn_objects_spawner.gd b/scripts/multiplayer/spawn_system/dyn_objects_spawner.gd new file mode 100644 index 0000000..1cd660c --- /dev/null +++ b/scripts/multiplayer/spawn_system/dyn_objects_spawner.gd @@ -0,0 +1,17 @@ +extends MultiplayerSpawner + +func _ready() -> void: + spawn_function = request_spawn + Session.dynamic_objects_spawner = self + +func request_spawn(data: Variant) -> Node: + if data.has_all(["scene","impulse"]): + var projectile: RigidBody3D = load(data.scene).instantiate() + if data.has_all(["ammo","remaining_ammo","slot"]): + projectile.weapon.ammo = data.ammo + projectile.weapon.remaining_ammo = data.remaining_ammo + projectile.slot = data.slot + + projectile.apply_impulse(data.impulse) + return projectile + return Node.new() diff --git a/scripts/multiplayer/spawn_system/dyn_objects_spawner.gd.uid b/scripts/multiplayer/spawn_system/dyn_objects_spawner.gd.uid new file mode 100644 index 0000000..515c347 --- /dev/null +++ b/scripts/multiplayer/spawn_system/dyn_objects_spawner.gd.uid @@ -0,0 +1 @@ +uid://bqjv6l7hh0lix diff --git a/scripts/player/player_pickup.gd b/scripts/player/player_pickup.gd index 9655848..53b167a 100644 --- a/scripts/player/player_pickup.gd +++ b/scripts/player/player_pickup.gd @@ -19,4 +19,16 @@ func on_body_entered(body: Node3D): "slot": body.slot }) weapon_system.on_weapon_added(weapon) - body.queue_free() + + Session.despawn(body.get_path()) + +func start_temp_ignore(): + if is_multiplayer_authority() == false: + return + monitoring = false + get_tree().create_timer(0.5).timeout.connect(stop_temp_ignore) + +func stop_temp_ignore(): + if is_multiplayer_authority() == false: + return + monitoring = true diff --git a/scripts/weapon_system/dropped_weapon.gd b/scripts/weapon_system/dropped_weapon.gd index 5be6418..c7790e6 100644 --- a/scripts/weapon_system/dropped_weapon.gd +++ b/scripts/weapon_system/dropped_weapon.gd @@ -2,6 +2,14 @@ extends RigidBody3D class_name DroppableWeapon +const IMPULSE = 10 + @export var slot: StringName @export var weapon: WeaponSubStateMachine @export var team: Session.TEAMS + +@rpc("any_peer","call_local","reliable") +func drop(direction: Vector3,new_position: Vector3): + apply_impulse(direction * IMPULSE) + global_position = new_position + diff --git a/scripts/weapon_system/gun/idle_state.gd b/scripts/weapon_system/gun/idle_state.gd index f790d0b..edb111c 100644 --- a/scripts/weapon_system/gun/idle_state.gd +++ b/scripts/weapon_system/gun/idle_state.gd @@ -15,11 +15,12 @@ func state_input(event: InputEvent) -> void: init_reload.rpc() func use_begin() -> void: - transition.emit("Shoot") + if machine.ammo > 0: + transition.emit("Shoot") @rpc("authority","call_local","reliable") func init_reload(): - if machine.ammo == machine.max_ammo: + if machine.ammo == machine.max_ammo or machine.remaining_ammo <= 0: return transition.emit("Reload") diff --git a/scripts/weapon_system/gun/reload_state.gd b/scripts/weapon_system/gun/reload_state.gd index 6abafee..325846a 100644 --- a/scripts/weapon_system/gun/reload_state.gd +++ b/scripts/weapon_system/gun/reload_state.gd @@ -11,7 +11,12 @@ func exit() -> void: func on_animation_finished(animation): if animation == with_morphems("reload"): - machine.ammo = machine.max_ammo + if machine.remaining_ammo > machine.max_ammo: + machine.ammo = machine.max_ammo + machine.remaining_ammo -= machine.max_ammo + else: + machine.ammo = machine.remaining_ammo + machine.remaining_ammo = 0 transition.emit("Idle") func with_morphems(animation): diff --git a/scripts/weapon_system/weapon_substate_machine.gd b/scripts/weapon_system/weapon_substate_machine.gd index b1cb38a..545c84e 100644 --- a/scripts/weapon_system/weapon_substate_machine.gd +++ b/scripts/weapon_system/weapon_substate_machine.gd @@ -3,8 +3,7 @@ extends SubStateMachine class_name WeaponSubStateMachine @export var animation_prefix: StringName -@export var droppable: PackedScene -@export var self_scene: PackedScene +@export var droppable: StringName @export var visibility_target: StringName @export var max_ammo: int @@ -12,6 +11,7 @@ class_name WeaponSubStateMachine @onready var remaining_ammo: int = max_ammo * 3 @export var can_be_previous: bool = true +@export var destroy_when_empty: bool = false var slot: StringName diff --git a/scripts/weapon_system/weapon_system.gd b/scripts/weapon_system/weapon_system.gd index 52d4078..1e64d02 100644 --- a/scripts/weapon_system/weapon_system.gd +++ b/scripts/weapon_system/weapon_system.gd @@ -28,6 +28,7 @@ signal switched_to(state: WeaponSubStateMachine) func _ready() -> void: current_state = default_pistol add(default_pistol,"secondary") + add(default_knife,"knife") current_state.enter() $WeaponSpawner.spawn_function = pick_up_weapon $WeaponSpawner.spawned.connect(on_weapon_added) @@ -55,7 +56,7 @@ func add(state: WeaponSubStateMachine, slot: StringName) -> void: state.request_return.connect(return_to_previous) func switch(to: StringName): - if slots.has(to) == false or slots[to] == null or slots[to] == current_state: + if slots.has(to) == false or slots[to] == null or slots[to] == current_state or is_multiplayer_authority() == false: return current_state.exit() if current_state.can_be_previous: @@ -69,7 +70,23 @@ func switch(to: StringName): update_remotes.rpc(to) -func drop(): pass +func drop(): + if slots.find_key(current_state) == "knife": + return + var drop_data: Dictionary = {} + drop_data.scene = current_state.droppable + drop_data.ammo = current_state.ammo + drop_data.remaining_ammo = current_state.remaining_ammo + drop_data.slot = current_state.slot + drop_data.position = camera.global_position + drop_data.impulse = -camera.global_basis.z * 10 + + Session.spawn(drop_data) + + $"../PickupRange".start_temp_ignore() + + Session.despawn(current_state.get_path()) + return_to_previous() # Spawn function # Data should be a dictionary with these keys: @@ -91,6 +108,8 @@ func on_weapon_added(weapon: Node): func return_to_previous(): if last_slot != "": switch(last_slot) + else: + switch("knife") @rpc("authority","call_remote","reliable") func update_remotes(to: StringName): @@ -143,4 +162,7 @@ func _input(event: InputEvent) -> void: current_state.alternate_state() if event.is_action_pressed("plr_firemode"): current_state.switch_mode() + + if event.is_action_pressed("plr_drop"): + drop()