Merge branch 'multiplayer-rework'

This commit is contained in:
Rendo 2025-12-07 15:54:20 +05:00
commit 2c9ef1cfe1
38 changed files with 535 additions and 288 deletions

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
.godot/ .godot/
/android/ /android/
exports/ exports/
deploy.sh

View file

@ -43,7 +43,7 @@ rm -rf \"{temp_dir}\""
[preset.1] [preset.1]
name="Windows Desktop" name="Windows"
platform="Windows Desktop" platform="Windows Desktop"
runnable=true runnable=true
advanced_options=false advanced_options=false

View file

@ -1,7 +1,6 @@
[gd_scene load_steps=24 format=3 uid="uid://cqrh2cc7m2i7f"] [gd_scene load_steps=21 format=3 uid="uid://cqrh2cc7m2i7f"]
[ext_resource type="Environment" uid="uid://d0cfgtx2yxw13" path="res://environments/prototype_environment.tres" id="1_i6jab"] [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/Graymat.tres" id="4_y6i55"] [ext_resource type="Material" uid="uid://bx3f5vx71ynh5" path="res://materials/Graymat.tres" id="4_y6i55"]
[ext_resource type="Material" uid="uid://dynpcduei1wfn" path="res://materials/Bluemat.tres" id="4_yx0ab"] [ext_resource type="Material" uid="uid://dynpcduei1wfn" path="res://materials/Bluemat.tres" id="4_yx0ab"]
[ext_resource type="Material" uid="uid://mlha6r17v2en" path="res://materials/DarkBluemat.tres" id="5_bno23"] [ext_resource type="Material" uid="uid://mlha6r17v2en" path="res://materials/DarkBluemat.tres" id="5_bno23"]
@ -15,22 +14,9 @@
[ext_resource type="Script" uid="uid://dk1gjbuydemmb" path="res://scripts/multiplayer/plant_site/plant_site.gd" id="8_oujx2"] [ext_resource type="Script" uid="uid://dk1gjbuydemmb" path="res://scripts/multiplayer/plant_site/plant_site.gd" id="8_oujx2"]
[ext_resource type="Script" uid="uid://b4cpux52fmx5o" path="res://scripts/multiplayer/plant_site/plant_deadzone.gd" id="9_1wlgq"] [ext_resource type="Script" uid="uid://b4cpux52fmx5o" path="res://scripts/multiplayer/plant_site/plant_deadzone.gd" id="9_1wlgq"]
[ext_resource type="Material" uid="uid://c6xa4phihtya2" path="res://materials/Redmat.tres" id="9_ysk2e"] [ext_resource type="Material" uid="uid://c6xa4phihtya2" path="res://materials/Redmat.tres" id="9_ysk2e"]
[ext_resource type="Script" uid="uid://ypgm3aplt78m" path="res://scripts/multiplayer/spawn_system/team_spawner.gd" id="10_02ic3"]
[ext_resource type="Script" uid="uid://3i00rp8urth7" path="res://scripts/object_container.gd" id="11_02ic3"] [ext_resource type="Script" uid="uid://3i00rp8urth7" path="res://scripts/object_container.gd" id="11_02ic3"]
[sub_resource type="Animation" id="Animation_y6i55"]
length = 0.001
[sub_resource type="Animation" id="Animation_pi0y7"]
resource_name = "main"
length = 5.0
loop_mode = 2
[sub_resource type="AnimationLibrary" id="AnimationLibrary_bno23"]
_data = {
&"RESET": SubResource("Animation_y6i55"),
&"main": SubResource("Animation_pi0y7")
}
[sub_resource type="BoxShape3D" id="BoxShape3D_ysk2e"] [sub_resource type="BoxShape3D" id="BoxShape3D_ysk2e"]
size = Vector3(15.324341, 0.96273804, 21.381592) size = Vector3(15.324341, 0.96273804, 21.381592)
@ -239,30 +225,24 @@ operation = 2
size = Vector3(20.339264, 4.566284, 3.4625244) size = Vector3(20.339264, 4.566284, 3.4625244)
material = ExtResource("7_8bje3") material = ExtResource("7_8bje3")
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
&"": SubResource("AnimationLibrary_bno23")
}
autoplay = "main"
[node name="PlayersContainer" type="Node3D" parent="." node_paths=PackedStringArray("exlusion_list")] [node name="PlayersContainer" type="Node3D" parent="." node_paths=PackedStringArray("exlusion_list")]
script = ExtResource("11_02ic3") script = ExtResource("11_02ic3")
exlusion_list = [NodePath("DefenceSpawn"), NodePath("AttackSpawn"), NodePath("SpectatorSpawn"), NodePath("MultiplayerSpawner")] exlusion_list = [NodePath("DefenceSpawn"), NodePath("AttackSpawn"), NodePath("SpectatorSpawn"), NodePath("MultiplayerSpawner")]
[node name="DefenceSpawn" type="Marker3D" parent="PlayersContainer"] [node name="DefenceSpawn" type="Marker3D" parent="PlayersContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 37.170197, 0.5180037, -11.271502) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 37.170197, 0.5180037, -11.271502)
script = ExtResource("4_pi0y7") script = ExtResource("10_02ic3")
spawn_radius = 10.0 spawn_radius = 10.0
[node name="AttackSpawn" type="Marker3D" parent="PlayersContainer"] [node name="AttackSpawn" type="Marker3D" parent="PlayersContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -31.553003, 0.5180037, 20.371899) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -31.553003, 0.5180037, 20.371899)
script = ExtResource("4_pi0y7") script = ExtResource("10_02ic3")
team = 1 team = 1
spawn_radius = 5.0 spawn_radius = 5.0
[node name="SpectatorSpawn" type="Marker3D" parent="PlayersContainer"] [node name="SpectatorSpawn" type="Marker3D" parent="PlayersContainer"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.1422176, 39.792877, -1.3889732) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4.1422176, 39.792877, -1.3889732)
script = ExtResource("4_pi0y7") script = ExtResource("10_02ic3")
team = 2 team = 2
spawn_radius = 10.0 spawn_radius = 10.0
@ -275,7 +255,7 @@ script = ExtResource("11_02ic3")
exlusion_list = [NodePath("MultiplayerSpawner"), NodePath("Bomb")] exlusion_list = [NodePath("MultiplayerSpawner"), NodePath("Bomb")]
[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="DynamicObjectsContainer"] [node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="DynamicObjectsContainer"]
_spawnable_scenes = PackedStringArray("uid://dtbpyfdawb02b", "uid://cxdgk74ln5xpn", "uid://dgfqppi21c2u0") _spawnable_scenes = PackedStringArray("uid://cxdgk74ln5xpn", "uid://dgfqppi21c2u0")
spawn_path = NodePath("..") spawn_path = NodePath("..")
script = ExtResource("6_oujx2") script = ExtResource("6_oujx2")

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 KiB

View file

@ -0,0 +1,43 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://50bjd4m600y"
path="res://.godot/imported/molikman_ingame_tex_Molikman.png-fa994ec91481577d99049156480274fc.ctex"
metadata={
"vram_texture": false
}
generator_parameters={
"md5": "adf17223cdac27afac207ae40df37427"
}
[deps]
source_file="res://models/characters/worldmodels/molikman_ingame_tex_Molikman.png"
dest_files=["res://.godot/imported/molikman_ingame_tex_Molikman.png-fa994ec91481577d99049156480274fc.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/uastc_level=0
compress/rdo_quality_loss=0.0
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/channel_remap/red=0
process/channel_remap/green=1
process/channel_remap/blue=2
process/channel_remap/alpha=3
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=1

View file

@ -22,6 +22,7 @@ Lobby="*res://scripts/multiplayer/lobby.gd"
Session="*res://scripts/multiplayer/session.gd" Session="*res://scripts/multiplayer/session.gd"
ClientSettings="*res://scripts/client_settings.gd" ClientSettings="*res://scripts/client_settings.gd"
Registry="*res://scripts/registry.gd" Registry="*res://scripts/registry.gd"
ClientSettingsMenu="res://scenes/gui/client_settings.tscn"
[display] [display]
@ -167,3 +168,7 @@ menu_settings={
3d_physics/layer_5="Players Attack Team" 3d_physics/layer_5="Players Attack Team"
3d_physics/layer_6="Players Defence Team" 3d_physics/layer_6="Players Defence Team"
3d_physics/layer_7="Interactible" 3d_physics/layer_7="Interactible"
[physics]
3d/default_gravity=39.2

View file

@ -2,29 +2,36 @@
[ext_resource type="Script" uid="uid://ddi1alk8oyi1b" path="res://scripts/gui/client_settings_menu.gd" id="1_xqyus"] [ext_resource type="Script" uid="uid://ddi1alk8oyi1b" path="res://scripts/gui/client_settings_menu.gd" id="1_xqyus"]
[node name="ClientSettings" type="PanelContainer"] [node name="ClientSettingsMenu" type="CanvasLayer"]
[node name="CenterContainer" type="CenterContainer" parent="."]
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
mouse_filter = 2
[node name="PanelContainer" type="PanelContainer" parent="CenterContainer"]
visible = false
layout_mode = 2
script = ExtResource("1_xqyus") script = ExtResource("1_xqyus")
[node name="VBoxContainer" type="VBoxContainer" parent="."] [node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer/PanelContainer"]
layout_mode = 2 layout_mode = 2
[node name="FullscreenButton" type="CheckButton" parent="VBoxContainer"] [node name="FullscreenButton" type="CheckButton" parent="CenterContainer/PanelContainer/VBoxContainer"]
layout_mode = 2 layout_mode = 2
text = "Полный экран" text = "Полный экран"
[node name="Sensitivity" type="HBoxContainer" parent="VBoxContainer"] [node name="Sensitivity" type="HBoxContainer" parent="CenterContainer/PanelContainer/VBoxContainer"]
layout_mode = 2 layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/Sensitivity"] [node name="Label" type="Label" parent="CenterContainer/PanelContainer/VBoxContainer/Sensitivity"]
layout_mode = 2 layout_mode = 2
text = "Чувствительность" text = "Чувствительность"
[node name="HSlider" type="HSlider" parent="VBoxContainer/Sensitivity"] [node name="HSlider" type="HSlider" parent="CenterContainer/PanelContainer/VBoxContainer/Sensitivity"]
custom_minimum_size = Vector2(256, 0) custom_minimum_size = Vector2(256, 0)
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
@ -33,7 +40,7 @@ max_value = 0.1
step = 0.001 step = 0.001
value = 0.02 value = 0.02
[node name="SpinBox" type="SpinBox" parent="VBoxContainer/Sensitivity"] [node name="SpinBox" type="SpinBox" parent="CenterContainer/PanelContainer/VBoxContainer/Sensitivity"]
layout_mode = 2 layout_mode = 2
max_value = 0.1 max_value = 0.1
step = 0.001 step = 0.001
@ -41,21 +48,21 @@ value = 0.02
allow_greater = true allow_greater = true
allow_lesser = true allow_lesser = true
[node name="GameplayMainAudio" type="HBoxContainer" parent="VBoxContainer"] [node name="GameplayMainAudio" type="HBoxContainer" parent="CenterContainer/PanelContainer/VBoxContainer"]
layout_mode = 2 layout_mode = 2
[node name="Label" type="Label" parent="VBoxContainer/GameplayMainAudio"] [node name="Label" type="Label" parent="CenterContainer/PanelContainer/VBoxContainer/GameplayMainAudio"]
layout_mode = 2 layout_mode = 2
text = "Геймплейные звуки" text = "Геймплейные звуки"
[node name="GameplayMainSlider" type="HSlider" parent="VBoxContainer/GameplayMainAudio"] [node name="GameplayMainSlider" type="HSlider" parent="CenterContainer/PanelContainer/VBoxContainer/GameplayMainAudio"]
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 3 size_flags_horizontal = 3
max_value = 1.0 max_value = 1.0
step = 0.01 step = 0.01
value = 1.0 value = 1.0
[connection signal="toggled" from="VBoxContainer/FullscreenButton" to="." method="_on_check_button_toggled"] [connection signal="toggled" from="CenterContainer/PanelContainer/VBoxContainer/FullscreenButton" to="." method="_on_check_button_toggled"]
[connection signal="value_changed" from="VBoxContainer/Sensitivity/HSlider" to="." method="_on_h_slider_value_changed"] [connection signal="value_changed" from="CenterContainer/PanelContainer/VBoxContainer/Sensitivity/HSlider" to="." method="_on_h_slider_value_changed"]
[connection signal="value_changed" from="VBoxContainer/Sensitivity/SpinBox" to="." method="_on_spin_box_value_changed"] [connection signal="value_changed" from="CenterContainer/PanelContainer/VBoxContainer/Sensitivity/SpinBox" to="." method="_on_spin_box_value_changed"]
[connection signal="value_changed" from="VBoxContainer/GameplayMainAudio/GameplayMainSlider" to="." method="_on_gameplay_main_slider_value_changed"] [connection signal="value_changed" from="CenterContainer/PanelContainer/VBoxContainer/GameplayMainAudio/GameplayMainSlider" to="." method="_on_gameplay_main_slider_value_changed"]

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=81 format=4 uid="uid://dpsr6ug3pkb40"] [gd_scene load_steps=84 format=4 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://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://dalwlndejfdhm" path="res://scripts/player/crosshair.gd" id="3_dqkch"]
@ -23,7 +23,6 @@
[ext_resource type="Script" uid="uid://gan0amqbhi4i" path="res://scripts/gui/hud/player_ammo_display.gd" id="12_iortg"] [ext_resource type="Script" uid="uid://gan0amqbhi4i" path="res://scripts/gui/hud/player_ammo_display.gd" id="12_iortg"]
[ext_resource type="Script" uid="uid://bala54fa32e35" path="res://scripts/gui/hud/player_round_display.gd" id="13_x73hv"] [ext_resource type="Script" uid="uid://bala54fa32e35" path="res://scripts/gui/hud/player_round_display.gd" id="13_x73hv"]
[ext_resource type="Script" uid="uid://bos7nftlx8tv3" path="res://scripts/gui/hud/player_round_time.gd" id="13_xar7t"] [ext_resource type="Script" uid="uid://bos7nftlx8tv3" path="res://scripts/gui/hud/player_round_time.gd" id="13_xar7t"]
[ext_resource type="PackedScene" uid="uid://bv6ptrditssow" path="res://scenes/gui/client_settings.tscn" id="16_d267o"]
[ext_resource type="AudioStream" uid="uid://bd4iofirvmiu6" path="res://audio/step_wood.ogg" id="16_fbysy"] [ext_resource type="AudioStream" uid="uid://bd4iofirvmiu6" path="res://audio/step_wood.ogg" id="16_fbysy"]
[ext_resource type="Script" uid="uid://da0xv360va3b3" path="res://scripts/audio_system/multiplayer_audio_3d.gd" id="17_0cqlf"] [ext_resource type="Script" uid="uid://da0xv360va3b3" path="res://scripts/audio_system/multiplayer_audio_3d.gd" id="17_0cqlf"]
[ext_resource type="Script" uid="uid://xsgfbuyje35p" path="res://scripts/player/player_pickup.gd" id="17_fjvrb"] [ext_resource type="Script" uid="uid://xsgfbuyje35p" path="res://scripts/player/player_pickup.gd" id="17_fjvrb"]
@ -37,6 +36,8 @@
[ext_resource type="Script" uid="uid://b2djbdh05pbcn" path="res://scripts/player/team_color_switcher.gd" id="25_1mtds"] [ext_resource type="Script" uid="uid://b2djbdh05pbcn" path="res://scripts/player/team_color_switcher.gd" id="25_1mtds"]
[ext_resource type="Material" uid="uid://cjb0h3of85nc2" path="res://materials/players/molikman/mat_Molikman.tres" id="26_r2jxp"] [ext_resource type="Material" uid="uid://cjb0h3of85nc2" path="res://materials/players/molikman/mat_Molikman.tres" id="26_r2jxp"]
[ext_resource type="Texture2D" uid="uid://15mf4452fse0" path="res://textures/players/molikman/molikman_ingame_Molikman_blue.png" id="27_j3w78"] [ext_resource type="Texture2D" uid="uid://15mf4452fse0" path="res://textures/players/molikman/molikman_ingame_Molikman_blue.png" id="27_j3w78"]
[ext_resource type="Script" uid="uid://dsp1sq46c5i3y" path="res://scripts/player/player_interaction.gd" id="37_5amik"]
[ext_resource type="Script" uid="uid://dfvnx8f1v6m5g" path="res://scripts/multiplayer/player_input.gd" id="37_b2eak"]
[sub_resource type="ArrayMesh" id="ArrayMesh_lot4n"] [sub_resource type="ArrayMesh" id="ArrayMesh_lot4n"]
_surfaces = [{ _surfaces = [{
@ -7401,6 +7402,14 @@ _data = {
&"baked_sp_shoot_empty": SubResource("Animation_do7kw") &"baked_sp_shoot_empty": SubResource("Animation_do7kw")
} }
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_b2eak"]
properties/0/path = NodePath(".:rotation")
properties/0/spawn = true
properties/0/replication_mode = 1
properties/1/path = NodePath("..:rotation")
properties/1/spawn = true
properties/1/replication_mode = 1
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_g2els"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_g2els"]
height = 1.2958984 height = 1.2958984
@ -7411,18 +7420,21 @@ font_size = 32
properties/0/path = NodePath(".:position") properties/0/path = NodePath(".:position")
properties/0/spawn = true properties/0/spawn = true
properties/0/replication_mode = 1 properties/0/replication_mode = 1
properties/1/path = NodePath(".:rotation") properties/1/path = NodePath(".:hp")
properties/1/spawn = true properties/1/spawn = true
properties/1/replication_mode = 1 properties/1/replication_mode = 1
properties/2/path = NodePath("Camera3D:rotation") properties/2/path = NodePath(".:team")
properties/2/spawn = true properties/2/spawn = true
properties/2/replication_mode = 1 properties/2/replication_mode = 2
properties/3/path = NodePath(".:hp") properties/3/path = NodePath(".:player_id")
properties/3/spawn = true properties/3/spawn = true
properties/3/replication_mode = 1 properties/3/replication_mode = 0
properties/4/path = NodePath(".:team") properties/4/path = NodePath(".:collision_layer")
properties/4/spawn = true properties/4/spawn = true
properties/4/replication_mode = 2 properties/4/replication_mode = 0
properties/5/path = NodePath(".:collision_mask")
properties/5/spawn = true
properties/5/replication_mode = 0
[sub_resource type="Curve" id="Curve_fbysy"] [sub_resource type="Curve" id="Curve_fbysy"]
_data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(1, 1), 2.5229826, 0.0, 0, 0] _data = [Vector2(0, 0), 0.0, 0.0, 0, 0, Vector2(1, 1), 2.5229826, 0.0, 0, 0]
@ -7605,6 +7617,14 @@ _data = {
radius = 0.82177734 radius = 0.82177734
height = 3.7087402 height = 3.7087402
[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_5amik"]
properties/0/path = NodePath("PlayerInput:direction")
properties/0/spawn = true
properties/0/replication_mode = 1
properties/1/path = NodePath("PlayerInput:compressed_states")
properties/1/spawn = true
properties/1/replication_mode = 1
[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("weapon_models")] [node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("weapon_models")]
collision_layer = 2 collision_layer = 2
collision_mask = 3 collision_mask = 3
@ -8087,9 +8107,11 @@ mesh = SubResource("ArrayMesh_aj0lc")
skin = SubResource("Skin_53wat") skin = SubResource("Skin_53wat")
surface_material_override/0 = ExtResource("26_r2jxp") surface_material_override/0 = ExtResource("26_r2jxp")
[node name="VisibleEnabler" type="Node" parent="molikman_ingame"] [node name="PlayerBasedVisibility" type="Node" parent="molikman_ingame" node_paths=PackedStringArray("reference_player")]
script = ExtResource("4_smehm") script = ExtResource("4_smehm")
visible_for_others = true visible_for_others = true
reference_player = NodePath("../..")
metadata/_custom_type_script = "uid://dd5mp72dq43v6"
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
@ -8573,13 +8595,17 @@ libraries = {
&"": SubResource("AnimationLibrary_kyf2b") &"": SubResource("AnimationLibrary_kyf2b")
} }
[node name="VisibilityToggler" type="Node" parent="Camera3D/molikman_hands"] [node name="VisibilityToggler" type="Node" parent="Camera3D/molikman_hands" node_paths=PackedStringArray("reference_player")]
script = ExtResource("4_smehm") script = ExtResource("4_smehm")
reference_player = NodePath("../../..")
[node name="DeadSpectator" type="Camera3D" parent="Camera3D"] [node name="DeadSpectator" type="Camera3D" parent="Camera3D"]
fov = 90.0 fov = 90.0
script = ExtResource("8_rwwcc") script = ExtResource("8_rwwcc")
[node name="CameraSync" type="MultiplayerSynchronizer" parent="Camera3D"]
replication_config = SubResource("SceneReplicationConfig_b2eak")
[node name="StandArea" type="Area3D" parent="."] [node name="StandArea" type="Area3D" parent="."]
collision_layer = 0 collision_layer = 0
@ -8636,8 +8662,9 @@ crosses_width = 2.0
crosses_length = 6.0 crosses_length = 6.0
crosses_offset = 3.0 crosses_offset = 3.0
[node name="VisibleDisabler" type="Node" parent="HUD"] [node name="VisibleDisabler" type="Node" parent="HUD" node_paths=PackedStringArray("reference_player")]
script = ExtResource("4_smehm") script = ExtResource("4_smehm")
reference_player = NodePath("../..")
[node name="Healthbar" type="ProgressBar" parent="HUD"] [node name="Healthbar" type="ProgressBar" parent="HUD"]
layout_mode = 1 layout_mode = 1
@ -8690,19 +8717,7 @@ script = ExtResource("13_xar7t")
layout_mode = 2 layout_mode = 2
script = ExtResource("13_x73hv") script = ExtResource("13_x73hv")
[node name="CenterContainer" type="CenterContainer" parent="HUD"] [node name="PlayerPropertiesSync" type="MultiplayerSynchronizer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ClientSettings" parent="HUD/CenterContainer" instance=ExtResource("16_d267o")]
visible = false
layout_mode = 2
[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_qhqgy") replication_config = SubResource("SceneReplicationConfig_qhqgy")
[node name="StepAudio" type="AudioStreamPlayer3D" parent="."] [node name="StepAudio" type="AudioStreamPlayer3D" parent="."]
@ -8758,7 +8773,7 @@ script = ExtResource("8_f1ej7")
current_state = NodePath("Stand") current_state = NodePath("Stand")
metadata/_custom_type_script = "uid://3777rkbebgjm" metadata/_custom_type_script = "uid://3777rkbebgjm"
[node name="Crouch" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("stand_up_area", "player", "player_movement", "animation_player", "weapon_system")] [node name="Crouch" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("stand_up_area", "player", "player_movement", "player_input", "animation_player", "weapon_system")]
script = ExtResource("9_oprun") script = ExtResource("9_oprun")
max_speed = 3.0 max_speed = 3.0
acceleration = 50.0 acceleration = 50.0
@ -8766,36 +8781,39 @@ deceleration = 50.0
stand_up_area = NodePath("../../StandArea") stand_up_area = NodePath("../../StandArea")
player = NodePath("../..") player = NodePath("../..")
player_movement = NodePath("../../PlayerMovement") player_movement = NodePath("../../PlayerMovement")
player_input = NodePath("../../PlayerInput")
animation_player = NodePath("../../AnimationPlayer") animation_player = NodePath("../../AnimationPlayer")
weapon_system = NodePath("../../WeaponSystem") weapon_system = NodePath("../../WeaponSystem")
[node name="Stand" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("player", "player_movement", "weapon_system", "audio")] [node name="Stand" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("player", "player_movement", "player_input", "weapon_system", "audio")]
script = ExtResource("10_a8ls1") script = ExtResource("10_a8ls1")
max_speed = 6.0 max_speed = 6.0
acceleration = 100.0 acceleration = 100.0
deceleration = 50.0 deceleration = 50.0
JUMP_VELOCITY = 6.0
player = NodePath("../..")
player_movement = NodePath("../../PlayerMovement")
weapon_system = NodePath("../../WeaponSystem")
audio = NodePath("../../StepAudio")
step_delay = 0.25 step_delay = 0.25
step_speed_curve = SubResource("Curve_fbysy") step_speed_curve = SubResource("Curve_fbysy")
player = NodePath("../..")
player_movement = NodePath("../../PlayerMovement")
player_input = NodePath("../../PlayerInput")
weapon_system = NodePath("../../WeaponSystem")
audio = NodePath("../../StepAudio")
[node name="Walk" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("player", "player_movement", "weapon_system")] [node name="Walk" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("player", "player_movement", "player_input", "weapon_system")]
script = ExtResource("11_qfm1y") script = ExtResource("11_qfm1y")
max_speed = 3.0 max_speed = 3.0
acceleration = 50.0 acceleration = 50.0
deceleration = 50.0 deceleration = 50.0
player = NodePath("../..") player = NodePath("../..")
player_movement = NodePath("../../PlayerMovement") player_movement = NodePath("../../PlayerMovement")
player_input = NodePath("../../PlayerInput")
weapon_system = NodePath("../../WeaponSystem") weapon_system = NodePath("../../WeaponSystem")
[node name="Fall" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("player", "player_movement", "weapon_system", "land_sound")] [node name="Fall" type="Node" parent="BodyStateMachine" node_paths=PackedStringArray("player", "player_movement", "player_input", "weapon_system", "land_sound")]
script = ExtResource("12_fulsm") script = ExtResource("12_fulsm")
acceleration = 25.0
player = NodePath("../..") player = NodePath("../..")
player_movement = NodePath("../../PlayerMovement") player_movement = NodePath("../../PlayerMovement")
acceleration = 25.0 player_input = NodePath("../../PlayerInput")
weapon_system = NodePath("../../WeaponSystem") weapon_system = NodePath("../../WeaponSystem")
land_sound = NodePath("../../LandAudio") land_sound = NodePath("../../LandAudio")
@ -8803,15 +8821,18 @@ land_sound = NodePath("../../LandAudio")
script = ExtResource("19_rwwcc") script = ExtResource("19_rwwcc")
animation_player = NodePath("../../AnimationPlayer") animation_player = NodePath("../../AnimationPlayer")
[node name="PlayerMovement" type="Node" parent="." node_paths=PackedStringArray("player")] [node name="PlayerMovement" type="Node" parent="." node_paths=PackedStringArray("player", "player_input")]
script = ExtResource("19_70eug") script = ExtResource("19_70eug")
jump_velocity = 12.0
player = NodePath("..") player = NodePath("..")
player_input = NodePath("../PlayerInput")
[node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("animation_player", "camera", "player")] [node name="WeaponSystem" type="Node" parent="." node_paths=PackedStringArray("animation_player", "camera", "player", "player_input")]
script = ExtResource("4_qlg0r") script = ExtResource("4_qlg0r")
animation_player = NodePath("../Camera3D/molikman_hands/AnimationPlayer") animation_player = NodePath("../Camera3D/molikman_hands/AnimationPlayer")
camera = NodePath("../Camera3D") camera = NodePath("../Camera3D")
player = NodePath("..") player = NodePath("..")
player_input = NodePath("../PlayerInput")
[node name="WeaponSpawner" type="MultiplayerSpawner" parent="WeaponSystem"] [node name="WeaponSpawner" type="MultiplayerSpawner" parent="WeaponSystem"]
spawn_path = NodePath("..") spawn_path = NodePath("..")
@ -8829,9 +8850,9 @@ libraries = {
[node name="TeamUpdater" type="Node" parent="." node_paths=PackedStringArray("player")] [node name="TeamUpdater" type="Node" parent="." node_paths=PackedStringArray("player")]
script = ExtResource("7_a8ls1") script = ExtResource("7_a8ls1")
player = NodePath("..")
layer = true layer = true
inverse = true inverse = true
player = NodePath("..")
[node name="PickupRange" type="Area3D" parent="." node_paths=PackedStringArray("weapon_spawner", "weapon_system")] [node name="PickupRange" type="Area3D" parent="." node_paths=PackedStringArray("weapon_spawner", "weapon_system")]
collision_layer = 0 collision_layer = 0
@ -8847,15 +8868,21 @@ shape = SubResource("CapsuleShape3D_3xmak")
[node name="TeamMaterialSwitcher" type="Node" parent="." node_paths=PackedStringArray("player")] [node name="TeamMaterialSwitcher" type="Node" parent="." node_paths=PackedStringArray("player")]
script = ExtResource("25_1mtds") script = ExtResource("25_1mtds")
material = ExtResource("26_r2jxp") material = ExtResource("26_r2jxp")
player = NodePath("..")
blue_team_texture = ExtResource("27_j3w78") blue_team_texture = ExtResource("27_j3w78")
player = NodePath("..")
[node name="Interaction" type="Node" parent="."]
script = ExtResource("37_5amik")
[node name="PlayerInput" type="MultiplayerSynchronizer" parent="."]
replication_config = SubResource("SceneReplicationConfig_5amik")
script = ExtResource("37_b2eak")
[connection signal="died" from="." to="molikman_ingame/VisibleEnabler" method="reverse"]
[connection signal="died" from="." to="Camera3D" method="disable"] [connection signal="died" from="." to="Camera3D" method="disable"]
[connection signal="died" from="." to="Camera3D/DeadSpectator" method="set_active"] [connection signal="died" from="." to="Camera3D/DeadSpectator" method="set_active"]
[connection signal="died" from="." to="BodyStateMachine/Death" method="on_death"] [connection signal="died" from="." to="BodyStateMachine/Death" method="on_death"]
[connection signal="died" from="." to="PlayerMovement" method="disable"] [connection signal="died" from="." to="PlayerMovement" method="disable"]
[connection signal="died" from="." to="WeaponSystem" method="disable"] [connection signal="died" from="." to="WeaponSystem" method="disable"]
[connection signal="health_changed" from="." to="HUD/Healthbar" method="on_hp_changed"] [connection signal="health_changed" from="." to="HUD/Healthbar" method="on_hp_changed"]
[connection signal="spawned" from="." to="TeamUpdater" method="on_spawned"] [connection signal="interact_begin" from="PlayerInput" to="Interaction" method="on_player_start_interacting"]
[connection signal="ammo_updated" from="WeaponSystem" to="HUD/AmmoDisplay" method="on_ammo_updated"] [connection signal="interact_end" from="PlayerInput" to="Interaction" method="on_player_end_interacting"]

View file

@ -2,3 +2,6 @@ extends Node
var SENSITIVITY: float = 0.02 var SENSITIVITY: float = 0.02
var TOGGLE_CROUCH: bool = false
var TOGGLE_SCOPE: bool = false
var TOGGLE_WALK: bool = false

View file

@ -1,5 +1,6 @@
extends Control extends Control
var cached_mouse_state: Input.MouseMode
func _on_check_button_toggled(toggled_on: bool) -> void: func _on_check_button_toggled(toggled_on: bool) -> void:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN if toggled_on else DisplayServer.WINDOW_MODE_WINDOWED) DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN if toggled_on else DisplayServer.WINDOW_MODE_WINDOWED)
@ -17,7 +18,11 @@ func _on_spin_box_value_changed(value: float) -> void:
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
if event.is_action_pressed("menu_settings"): if event.is_action_pressed("menu_settings"):
visible = not visible visible = not visible
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE if visible else Input.MOUSE_MODE_CAPTURED if visible:
cached_mouse_state = Input.mouse_mode
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
else:
Input.mouse_mode = cached_mouse_state
func _on_gameplay_main_slider_value_changed(value: float) -> void: func _on_gameplay_main_slider_value_changed(value: float) -> void:

View file

@ -78,6 +78,20 @@ func set_teams(attack: Array[int],defence: Array[int],spectators: Array[int]):
func switch_team(team: int) -> void: func switch_team(team: int) -> void:
team_switch_notification.rpc(multiplayer.get_unique_id(),team) team_switch_notification.rpc(multiplayer.get_unique_id(),team)
func swap_teams() -> void:
if not multiplayer.is_server():
return
var temp_defenders = defence_team.duplicate()
for attacker in attack_team:
server_team_switch.rpc(attacker,Session.TEAMS.DEFENCE)
for defender in temp_defenders:
server_team_switch.rpc(defender,Session.TEAMS.ATTACK)
update_peers.rpc()
@rpc("any_peer","call_local","reliable") @rpc("any_peer","call_local","reliable")
func team_switch_notification(id: int, team: int) -> void: func team_switch_notification(id: int, team: int) -> void:
if (team == Session.TEAMS.DEFENCE and len(defence_team) > 4) or (team == Session.TEAMS.ATTACK and len(attack_team) > 4): if (team == Session.TEAMS.DEFENCE and len(defence_team) > 4) or (team == Session.TEAMS.ATTACK and len(attack_team) > 4):
@ -105,6 +119,32 @@ func team_switch_notification(id: int, team: int) -> void:
update_teams_state.emit() update_teams_state.emit()
@rpc("authority","call_local","reliable")
func server_team_switch(id: int, team: int) -> void:
if multiplayer.get_remote_sender_id() != 1 and not multiplayer.is_server():
return
if team == Session.TEAMS.DEFENCE:
if attack_team.has(id):
attack_team.erase(id)
if specators_team.has(id):
specators_team.erase(id)
defence_team.append(id)
if team == Session.TEAMS.ATTACK:
if defence_team.has(id):
defence_team.erase(id)
if specators_team.has(id):
specators_team.erase(id)
attack_team.append(id)
if team == Session.TEAMS.SPECTATE:
if attack_team.has(id):
attack_team.erase(id)
elif defence_team.has(id):
defence_team.erase(id)
specators_team.append(id)
@rpc("authority","call_local","reliable") @rpc("authority","call_local","reliable")
func start_game() -> void: func start_game() -> void:
get_tree().change_scene_to_file("res://levels/prototype_scene.tscn") get_tree().change_scene_to_file("res://levels/prototype_scene.tscn")
@ -121,3 +161,7 @@ func get_team() -> Session.TEAMS:
if specators_team.has(id): if specators_team.has(id):
return Session.TEAMS.SPECTATE return Session.TEAMS.SPECTATE
return Session.TEAMS.UNASSIGNED return Session.TEAMS.UNASSIGNED
@rpc("authority","call_local","reliable")
func update_peers():
update_teams_state.emit()

View file

@ -1,9 +1,12 @@
extends Node extends Node
class_name PlayerBasedVisibility
@export var visible_for_others: bool = false @export var visible_for_others: bool = false
@export var reference_player: Player
func _ready() -> void: func _ready() -> void:
get_parent().visible = (get_multiplayer_authority() != multiplayer.get_unique_id()) == visible_for_others get_parent().visible = (reference_player.player_id != multiplayer.get_unique_id()) == visible_for_others
func reverse() -> void: func reverse() -> void:
get_parent().visible = not get_parent().visible get_parent().visible = not get_parent().visible

View file

@ -0,0 +1,182 @@
extends MultiplayerSynchronizer
class_name PlayerInput
const SCOPE: int = 0b1
const CROUCH: int = 0b10
const WALK: int = 0b100
#region SYNC
@export var direction: Vector2
@export var compressed_states: int
#endregion
signal jumped
signal drop
signal switch_weapon(to_slot: StringName)
signal fire_begin
signal fire_end
signal alternate_state
signal switch_firemode
signal reload
signal scope_begin
signal scope_end
signal crouch_begin
signal crouch_end
signal walk_begin
signal walk_end
signal interact_begin
signal interact_end
func _process(_delta: float) -> void:
if not is_multiplayer_authority(): return
direction = Input.get_vector("plr_strafe_r","plr_strafe_l", "plr_back","plr_forward")
func _input(event: InputEvent) -> void:
if not is_multiplayer_authority(): return
if event.is_action_pressed("plr_ult"):
switch_on_server.rpc_id(1,"ultimate")
elif event.is_action_pressed("plr_bomb"):
switch_on_server.rpc_id(1,"bomb")
elif event.is_action_pressed("plr_primary"):
switch_on_server.rpc_id(1,"primary")
elif event.is_action_pressed("plr_active_first"):
switch_on_server.rpc_id(1,"ability_first")
elif event.is_action_pressed("plr_active_second"):
switch_on_server.rpc_id(1,"ability_second")
elif event.is_action_pressed("plr_active_third"):
switch_on_server.rpc_id(1,"ability_third")
elif event.is_action_pressed("plr_secondary"):
switch_on_server.rpc_id(1,"secondary")
elif event.is_action_pressed("plr_knife"):
switch_on_server.rpc_id(1,"knife")
if event.is_action_pressed("plr_fire"):
fire_on_server.rpc_id(1,false)
if event.is_action_released("plr_fire"):
fire_on_server.rpc_id(1,true)
if event.is_action_pressed("plr_scope"):
alternate_state_on_server.rpc_id(1)
if event.is_action_pressed("plr_firemode"):
switch_firemode_on_server.rpc_id(1)
if event.is_action_pressed("plr_drop"):
drop_on_server.rpc_id(1)
var crouching: bool = compressed_states & CROUCH
var walking: bool = compressed_states & WALK
var scoping: bool = compressed_states & SCOPE
if event.is_action_pressed("plr_crouch"):
if ClientSettings.TOGGLE_CROUCH:
crouch_on_server.rpc_id(1,crouching)
compressed_states ^= CROUCH
elif not crouching:
compressed_states |= CROUCH
crouch_on_server.rpc_id(1,false)
if event.is_action_released("plr_crouch") and not ClientSettings.TOGGLE_CROUCH and crouching:
compressed_states &= ~CROUCH
crouch_on_server.rpc_id(1,true)
if event.is_action_pressed("plr_walk"):
if ClientSettings.TOGGLE_WALK:
walk_on_server.rpc_id(1,walking)
compressed_states ^= WALK
elif not walking:
compressed_states |= WALK
walk_on_server.rpc_id(1,false)
if event.is_action_released("plr_walk") and not ClientSettings.TOGGLE_WALK and walking:
compressed_states &= ~WALK
walk_on_server.rpc_id(1,true)
if event.is_action_pressed("plr_scope"):
if ClientSettings.TOGGLE_SCOPE:
scope_on_server.rpc_id(1,scoping)
compressed_states ^= SCOPE
elif not scoping:
compressed_states |= SCOPE
scope_on_server.rpc_id(1,false)
if event.is_action_released("plr_scope") and not ClientSettings.TOGGLE_SCOPE and scoping:
compressed_states &= ~SCOPE
scope_on_server.rpc_id(1,true)
if event.is_action_pressed("plr_reload"):
reload_on_server.rpc_id(1)
if event.is_action_pressed("plr_interact"):
interact_on_server.rpc_id(1,false)
if event.is_action_released("plr_interact"):
interact_on_server.rpc_id(1,true)
if event.is_action_pressed("plr_jump"):
jump_on_server.rpc_id(1)
@rpc("authority","call_local","reliable")
func switch_on_server(slot: StringName) -> void:
if not multiplayer.is_server(): return
switch_weapon.emit(slot)
@rpc("authority","call_local","reliable")
func drop_on_server() -> void:
if not multiplayer.is_server(): return
drop.emit()
@rpc("authority","call_local","reliable")
func fire_on_server(end: bool) -> void:
if not multiplayer.is_server(): return
if end:
fire_end.emit()
else:
fire_begin.emit()
@rpc("authority","call_local","reliable")
func alternate_state_on_server() -> void:
if not multiplayer.is_server(): return
alternate_state.emit()
@rpc("authority","call_local","reliable")
func switch_firemode_on_server() -> void:
if not multiplayer.is_server(): return
switch_firemode.emit()
@rpc("authority","call_local","reliable")
func crouch_on_server(end: bool) -> void:
if not multiplayer.is_server(): return
if end:
crouch_end.emit()
else:
crouch_begin.emit()
@rpc("authority","call_local","reliable")
func walk_on_server(end: bool) -> void:
if not multiplayer.is_server(): return
if end:
walk_end.emit()
else:
walk_begin.emit()
@rpc("authority","call_local","reliable")
func scope_on_server(end: bool) -> void:
if not multiplayer.is_server(): return
if end:
scope_end.emit()
else:
scope_begin.emit()
@rpc("authority","call_local","reliable")
func reload_on_server() -> void:
if not multiplayer.is_server(): return
reload.emit()
@rpc("authority","call_local","reliable")
func interact_on_server(end: bool) -> void:
if not multiplayer.is_server(): return
if end:
interact_end.emit()
else:
interact_begin.emit()
@rpc("authority","call_local","reliable")
func jump_on_server() -> void:
if not multiplayer.is_server(): return
jumped.emit()

View file

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

View file

@ -86,7 +86,7 @@ func _process(_delta: float) -> void:
func update_clock(time: float): func update_clock(time: float):
reference_round_time = time reference_round_time = time
@rpc("any_peer","call_remote","reliable") @rpc("authority","call_remote","reliable")
func start_session() -> void: func start_session() -> void:
if not is_server_request(): if not is_server_request():
return return
@ -100,7 +100,7 @@ func start_session() -> void:
start_round() start_round()
@rpc("any_peer","call_remote","reliable") @rpc("authority","call_remote","reliable")
func end_session() -> void: func end_session() -> void:
if not is_server_request(): if not is_server_request():
return return
@ -114,7 +114,7 @@ func end_session() -> void:
session_started = false session_started = false
@rpc("any_peer","call_remote","reliable") @rpc("authority","call_remote","reliable")
func start_round() -> void: func start_round() -> void:
if not is_server_request(): if not is_server_request():
return return
@ -134,23 +134,26 @@ func start_round() -> void:
round_state = ROUND_STATES.BUY round_state = ROUND_STATES.BUY
round_state_changed.emit.call_deferred(round_state) round_state_changed.emit.call_deferred(round_state)
@rpc("any_peer","call_remote","reliable") @rpc("authority","call_remote","reliable")
func end_round(win_team: int) -> void: func end_round(win_team: int) -> void:
if not is_server_request(): if not is_server_request():
return return
if multiplayer.is_server(): if multiplayer.is_server():
get_tree().create_timer(5).timeout.connect(start_round) get_tree().create_timer(5).timeout.connect(start_round)
end_round.rpc(win_team) end_round.rpc(win_team)
if current_round == Lobby.half_rounds:
Lobby.swap_teams()
if win_team == TEAMS.DEFENCE: if win_team == TEAMS.DEFENCE:
defender_score += 1 defender_score += 1
elif win_team == TEAMS.ATTACK: elif win_team == TEAMS.ATTACK:
attacker_score += 1 attacker_score += 1
round_state = ROUND_STATES.AFTER_ROUND round_state = ROUND_STATES.AFTER_ROUND
round_state_changed.emit(round_state) round_state_changed.emit(round_state)
@rpc("any_peer","call_remote","reliable") @rpc("authority","call_remote","reliable")
func begin_main_stage() -> void: func begin_main_stage() -> void:
if not is_server_request(): if not is_server_request():
return return
@ -161,7 +164,7 @@ func begin_main_stage() -> void:
round_state = ROUND_STATES.ROUND round_state = ROUND_STATES.ROUND
round_state_changed.emit(round_state) round_state_changed.emit(round_state)
@rpc("any_peer","call_remote","reliable") @rpc("authority","call_remote","reliable")
func begin_bomb_stage() -> void: func begin_bomb_stage() -> void:
if not is_server_request(): if not is_server_request():
return return
@ -179,7 +182,6 @@ func defuse_win() -> void:
bomb_timer.stop() bomb_timer.stop()
end_round(TEAMS.DEFENCE) end_round(TEAMS.DEFENCE)
@rpc("any_peer","call_local","reliable")
func add_dead(team: int): func add_dead(team: int):
if multiplayer.is_server() == false: if multiplayer.is_server() == false:
return return
@ -204,12 +206,7 @@ func is_server_request() -> bool:
## ammo, remaining_ammo, slot - data for dropped weapon [br] ## ammo, remaining_ammo, slot - data for dropped weapon [br]
## for more, see dyn_objects_spawner.gd ## for more, see dyn_objects_spawner.gd
func spawn(data: Dictionary) -> void: 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: if multiplayer.is_server() == false:
printerr(str(multiplayer.get_remote_sender_id())+" tried to spawn internally on "+str(multiplayer.get_unique_id()))
return return
var object = dynamic_objects_spawner.spawn(data) var object = dynamic_objects_spawner.spawn(data)
@ -217,25 +214,14 @@ func spawn_internal(data: Dictionary) -> void:
if data.has("position"): if data.has("position"):
object.global_position = data.position object.global_position = data.position
func despawn(path: NodePath): func despawn(path: NodePath) -> void:
despawn_internal.rpc_id(1,path)
@rpc("any_peer","call_local","reliable")
func despawn_internal(path: NodePath) -> void:
if multiplayer.is_server() == false: if multiplayer.is_server() == false:
printerr(str(multiplayer.get_remote_sender_id())+" tried to despawn internally on "+str(multiplayer.get_unique_id())) printerr(str(multiplayer.get_remote_sender_id())+" tried to despawn internally on "+str(multiplayer.get_unique_id()))
return return
get_node(path).queue_free() get_node(path).queue_free()
func shoot(damage: int,distance: float = 100) -> void: func shoot(id:int , damage: int, distance: float) -> void:
if multiplayer.get_unique_id() == 1:
shoot_internal(1,damage,distance)
else:
shoot_internal.rpc_id(1,multiplayer.get_unique_id(),damage,distance)
@rpc("any_peer","call_local","reliable")
func shoot_internal(id:int , damage: int, distance: float) -> void:
if multiplayer.is_server() == false: if multiplayer.is_server() == false:
return return
@ -258,16 +244,10 @@ func shoot_internal(id:int , damage: int, distance: float) -> void:
var collision = space.intersect_ray(ray) var collision = space.intersect_ray(ray)
if collision != {} and collision["collider"] is Player: if collision != {} and collision["collider"] is Player:
collision["collider"].take_damage.rpc_id(int(collision["collider"].name),damage) collision["collider"].take_damage(damage)
func interact() -> void:
if multiplayer.get_unique_id() == 1:
interact_internal(1)
else:
interact_internal.rpc_id(1,multiplayer.get_unique_id())
@rpc("any_peer","call_local","reliable") func interact(id: int) -> void:
func interact_internal(id:int) -> void:
if multiplayer.is_server() == false: if multiplayer.is_server() == false:
return return
@ -285,27 +265,20 @@ func interact_internal(id:int) -> void:
if collision != {} and collision["collider"] is Interactible: if collision != {} and collision["collider"] is Interactible:
collision["collider"].interaction_start(id) collision["collider"].interaction_start(id)
func stop_interact(): func stop_interact(id: int) -> void:
if multiplayer.get_unique_id() == 1:
stop_interact_internal(1)
else:
stop_interact_internal.rpc_id(1,multiplayer.get_unique_id())
@rpc("any_peer","call_local","reliable")
func stop_interact_internal(id: int) -> void:
if multiplayer.is_server() == false: if multiplayer.is_server() == false:
return return
player_stopped_interacting.emit(id) player_stopped_interacting.emit(id)
func is_on_site() -> bool: func is_on_site(id: int) -> bool:
for plant in plants: for plant in plants:
if plant.is_player_on_site(multiplayer.get_unique_id()): if plant.is_player_on_site(id):
return true return true
return false return false
func get_site() -> PlantSite: func get_site(id: int) -> PlantSite:
for plant in plants: for plant in plants:
if plant.is_player_on_site(multiplayer.get_unique_id()): if plant.is_player_on_site(id):
return plant return plant
return null return null

View file

@ -15,6 +15,8 @@ func _exit_tree() -> void:
Session.round_started.disconnect(spawn) Session.round_started.disconnect(spawn)
func spawn(): func spawn():
if not multiplayer.is_server():
return
match team: match team:
Session.TEAMS.ATTACK: Session.TEAMS.ATTACK:
for attacker in Lobby.attack_team: for attacker in Lobby.attack_team:
@ -36,18 +38,22 @@ func spawn_player(id: int) -> void:
elif team == Session.TEAMS.ATTACK: elif team == Session.TEAMS.ATTACK:
Session.attackers_alive += 1 Session.attackers_alive += 1
deferred_setup.bind(inst,team).call_deferred() var distance = randf_range(0,spawn_radius)
var angle = randf_range(0,TAU)
var new_position = global_position + Vector3.RIGHT.rotated(Vector3.UP,angle) * distance
inst.player_id = id
inst.team = team
get_parent().add_child(inst)
inst.global_position = new_position
func spawn_spectator(id: int) -> void: func spawn_spectator(id: int) -> void:
var spectator: PackedScene = load("res://scenes/spectator.tscn") var spectator: PackedScene = load("res://scenes/spectator.tscn")
var inst = spectator.instantiate() var inst = spectator.instantiate()
inst.name = str(id) inst.name = str(id)
deferred_setup.bind(inst,Session.TEAMS.SPECTATE).call_deferred()
func deferred_setup(what: Node3D, new_team: Session.TEAMS):
get_parent().add_child(what,true)
var distance = randf_range(0,spawn_radius) var distance = randf_range(0,spawn_radius)
var angle = randf_range(0,TAU) var angle = randf_range(0,TAU)
var new_position = global_position + Vector3.RIGHT.rotated(Vector3.UP,angle) * distance var new_position = global_position + Vector3.RIGHT.rotated(Vector3.UP,angle) * distance
what.set_after_spawn.rpc_id(int(what.name),new_position,new_team) inst.team = team
get_parent().add_child(inst)
inst.global_position = new_position

View file

@ -7,17 +7,10 @@ extends Node
const ATTACK_LAYER: int = 0b10000 const ATTACK_LAYER: int = 0b10000
const DEFENCE_LAYER: int = 0b100000 const DEFENCE_LAYER: int = 0b100000
func on_spawned() -> void: func _ready() -> void:
if is_multiplayer_authority() == false: return
var mask = (ATTACK_LAYER if (player.team == Session.TEAMS.DEFENCE != inverse) else DEFENCE_LAYER) var mask = (ATTACK_LAYER if (player.team == Session.TEAMS.DEFENCE != inverse) else DEFENCE_LAYER)
if layer: if layer:
get_parent().collision_layer |= mask get_parent().collision_layer |= mask
else: else:
get_parent().collision_mask |= mask get_parent().collision_mask |= mask
global_update.rpc(layer,mask)
@rpc
func global_update(new_layer,mask) -> void:
if new_layer:
get_parent().collision_layer |= mask
else:
get_parent().collision_mask |= mask

View file

@ -4,9 +4,8 @@ extends Camera3D
var active: bool var active: bool
func _ready() -> void: func _enter_tree() -> void:
if not is_multiplayer_authority(): set_multiplayer_authority(int(get_parent().get_parent().name))
return
func set_active() -> void: func set_active() -> void:
if not is_multiplayer_authority(): if not is_multiplayer_authority():

View file

@ -4,10 +4,14 @@ class_name Player
@export var team: Session.TEAMS @export var team: Session.TEAMS
@export var weapon_models: Dictionary[StringName,Node3D] @export var weapon_models: Dictionary[StringName,Node3D]
@export var player_id: int = 1:
set(id):
player_id = id
$PlayerInput.set_multiplayer_authority(id)
$Camera3D.set_multiplayer_authority(id)
var passived: bool = false var passived: bool = false
signal spawned
signal health_changed(to: int) signal health_changed(to: int)
signal died signal died
@ -26,52 +30,24 @@ const MAX_HP = 100
get: get:
return hp return hp
func _enter_tree() -> void:
set_multiplayer_authority(str(name).to_int())
func _physics_process(_delta: float) -> void: func _physics_process(_delta: float) -> void:
if not is_multiplayer_authority(): if not multiplayer.is_server():
return return
move_and_slide() move_and_slide()
func die() -> void: func die() -> void:
if (not is_multiplayer_authority()): if (not multiplayer.is_server()):
return return
Session.add_dead.rpc(team) Session.add_dead(team)
died.emit() died.emit()
passived = true passived = true
@rpc("any_peer","call_local","reliable")
func passive() -> void: func passive() -> void:
passived = true passived = true
@rpc("any_peer","call_local","reliable")
func depassive() -> void: func depassive() -> void:
passived = false passived = false
@rpc("any_peer","call_local","reliable")
func kill_request() -> void:
if multiplayer.get_remote_sender_id() != 1:
return
die()
@rpc("any_peer","call_local","reliable")
func set_after_spawn(start_position: Vector3,new_team: int):
global_position = start_position
team = new_team as Session.TEAMS
spawned.emit()
@rpc("any_peer","call_local","reliable")
func take_damage(damage: int): func take_damage(damage: int):
hp -= damage hp -= damage
$DamageAudio.multiplayer_play()
func _input(event: InputEvent) -> void:
if not is_multiplayer_authority():
return
if event.is_action_pressed("plr_interact"):
Session.interact()
if event.is_action_released("plr_interact"):
Session.stop_interact()

View file

@ -0,0 +1,8 @@
extends Node
func on_player_start_interacting():
Session.interact(get_parent().player_id)
func on_player_end_interacting():
Session.stop_interact(get_parent().player_id)

View file

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

View file

@ -3,6 +3,9 @@ extends Node
class_name PlayerMovement class_name PlayerMovement
@export var player: Player @export var player: Player
@export var player_input: PlayerInput
@export var jump_velocity: float
var disabled: bool var disabled: bool
func disable() -> void: func disable() -> void:
@ -15,7 +18,7 @@ func process_movement(max_speed: float,acceleration: float,deceleration: float,d
player.velocity.x = 0 player.velocity.x = 0
player.velocity.z = 0 player.velocity.z = 0
return return
var input_dir := Input.get_vector("plr_strafe_r","plr_strafe_l", "plr_back","plr_forward") var input_dir := player_input.direction
var direction := (player.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() var direction := (player.transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction: if direction:
player.velocity.x = clamp(player.velocity.x + direction.x * acceleration * delta,-max_speed*abs(direction.x),max_speed*abs(direction.x)) player.velocity.x = clamp(player.velocity.x + direction.x * acceleration * delta,-max_speed*abs(direction.x),max_speed*abs(direction.x))
@ -23,3 +26,6 @@ func process_movement(max_speed: float,acceleration: float,deceleration: float,d
else: else:
player.velocity.x = move_toward(player.velocity.x, 0, deceleration*delta) player.velocity.x = move_toward(player.velocity.x, 0, deceleration*delta)
player.velocity.z = move_toward(player.velocity.z, 0, deceleration*delta) player.velocity.z = move_toward(player.velocity.z, 0, deceleration*delta)
func jump() -> void:
player.velocity.y = jump_velocity

View file

@ -8,22 +8,22 @@ extends State
@export var stand_up_area: Area3D @export var stand_up_area: Area3D
@export var player: Player @export var player: Player
@export var player_movement: PlayerMovement @export var player_movement: PlayerMovement
@export var player_input: PlayerInput
@export var animation_player: AnimationPlayer @export var animation_player: AnimationPlayer
@export var crouch_time: float = 0.1 @export var crouch_time: float = 0.1
@export var weapon_system: WeaponSystem @export var weapon_system: WeaponSystem
func enter() -> void: func enter() -> void:
animation_player.play("crouch",-1,1/crouch_time) animation_player.play("crouch",-1,1/crouch_time)
player_input.crouch_end.connect(try_end_crouch)
func exit() -> void: func exit() -> void:
animation_player.play("crouch",-1,-1/crouch_time,true) animation_player.play("crouch",-1,-1/crouch_time,true)
player_input.crouch_end.disconnect(try_end_crouch)
func physics_update(delta: float) -> void: func physics_update(delta: float) -> void:
if not is_multiplayer_authority(): if not is_multiplayer_authority():
return return
if Input.is_action_just_pressed("plr_jump") and player.is_on_floor() and toggle:
transition.emit("Stand")
return
if not player.is_on_floor(): if not player.is_on_floor():
transition.emit("Fall") transition.emit("Fall")
@ -31,7 +31,6 @@ func physics_update(delta: float) -> void:
player_movement.process_movement(max_speed * weapon_system.get_speed_modifier(),acceleration,deceleration,delta) player_movement.process_movement(max_speed * weapon_system.get_speed_modifier(),acceleration,deceleration,delta)
func state_input(event: InputEvent) -> void: func try_end_crouch() -> void:
if (toggle == true and event.is_action_pressed("plr_crouch")) or (toggle == false and event.is_action_released("plr_crouch")): if player.is_on_floor() and stand_up_area.has_overlapping_bodies() == false:
if stand_up_area.has_overlapping_bodies() == false: transition.emit("Stand")
transition.emit("Stand")

View file

@ -2,6 +2,7 @@ extends State
@export var player: Player @export var player: Player
@export var player_movement: PlayerMovement @export var player_movement: PlayerMovement
@export var player_input: PlayerInput
@export var max_speed: float = 5.0 @export var max_speed: float = 5.0
@export var acceleration: float @export var acceleration: float
@export var weapon_system: WeaponSystem @export var weapon_system: WeaponSystem
@ -18,7 +19,12 @@ func physics_update(delta: float) -> void:
if not is_multiplayer_authority(): if not is_multiplayer_authority():
return return
if player.is_on_floor(): if player.is_on_floor():
transition.emit("Stand") if player_input.compressed_states & PlayerInput.CROUCH:
transition.emit("Crouch")
elif player_input.compressed_states & PlayerInput.WALK:
transition.emit("Walk")
else:
transition.emit("Stand")
land_sound.multiplayer_play() land_sound.multiplayer_play()
player.velocity += player.get_gravity() * delta player.velocity += player.get_gravity() * delta

View file

@ -3,9 +3,9 @@ extends State
@export var max_speed: float = 5.0 @export var max_speed: float = 5.0
@export var acceleration: float = 2.0 @export var acceleration: float = 2.0
@export var deceleration: float = 200.0 @export var deceleration: float = 200.0
@export var JUMP_VELOCITY: float = 4.5
@export var player: Player @export var player: Player
@export var player_movement: PlayerMovement @export var player_movement: PlayerMovement
@export var player_input: PlayerInput
@export var weapon_system: WeaponSystem @export var weapon_system: WeaponSystem
@export var audio: MultiplayerAudio3D @export var audio: MultiplayerAudio3D
@export var step_delay: float @export var step_delay: float
@ -14,18 +14,19 @@ extends State
var step_time: float var step_time: float
func enter() -> void: func enter() -> void:
pass player_input.jumped.connect(on_jumped)
player_input.crouch_begin.connect(begin_crouch)
player_input.walk_begin.connect(begin_walk)
func exit() -> void: func exit() -> void:
player_input.jumped.disconnect(on_jumped)
player_input.crouch_begin.disconnect(begin_crouch)
player_input.walk_begin.disconnect(begin_walk)
step_time = 0 step_time = 0
func physics_update(delta: float) -> void: func physics_update(delta: float) -> void:
if not is_multiplayer_authority(): if not is_multiplayer_authority():
return return
if Input.is_action_just_pressed("plr_jump") and player.is_on_floor():
player.velocity.y = JUMP_VELOCITY * sign(weapon_system.get_speed_modifier())
transition.emit("Fall")
return
if not player.is_on_floor(): if not player.is_on_floor():
transition.emit("Fall") transition.emit("Fall")
@ -38,9 +39,13 @@ func physics_update(delta: float) -> void:
player_movement.process_movement(max_speed * weapon_system.get_speed_modifier(),acceleration,deceleration,delta) player_movement.process_movement(max_speed * weapon_system.get_speed_modifier(),acceleration,deceleration,delta)
func state_input(event: InputEvent) -> void: func on_jumped() -> void:
if event.is_action_pressed("plr_crouch"): if player.is_on_floor():
transition.emit("Crouch") player_movement.jump()
transition.emit("Fall")
if event.is_action_pressed("plr_walk"):
transition.emit("Walk") func begin_walk() -> void:
transition.emit("Walk")
func begin_crouch() -> void:
transition.emit("Crouch")

View file

@ -6,21 +6,22 @@ extends State
@export var JUMP_VELOCITY: float = 4.5 @export var JUMP_VELOCITY: float = 4.5
@export var player: Player @export var player: Player
@export var player_movement: PlayerMovement @export var player_movement: PlayerMovement
@export var player_input: PlayerInput
@export var weapon_system: WeaponSystem @export var weapon_system: WeaponSystem
func enter() -> void: func enter() -> void:
pass player_input.crouch_begin.connect(begin_crouch)
player_input.walk_end.connect(end_walk)
player_input.jumped.connect(on_jumped)
func exit() -> void: func exit() -> void:
pass player_input.crouch_begin.disconnect(begin_crouch)
player_input.walk_end.disconnect(end_walk)
player_input.jumped.disconnect(on_jumped)
func physics_update(delta: float) -> void: func physics_update(delta: float) -> void:
if not is_multiplayer_authority(): if not is_multiplayer_authority():
return return
if Input.is_action_just_pressed("plr_jump") and player.is_on_floor():
player.velocity.y = JUMP_VELOCITY
transition.emit("Fall")
return
if not player.is_on_floor(): if not player.is_on_floor():
transition.emit("Fall") transition.emit("Fall")
@ -28,9 +29,13 @@ func physics_update(delta: float) -> void:
player_movement.process_movement(max_speed * weapon_system.get_speed_modifier(),acceleration,deceleration,delta) player_movement.process_movement(max_speed * weapon_system.get_speed_modifier(),acceleration,deceleration,delta)
func state_input(event: InputEvent) -> void: func on_jumped() -> void:
if event.is_action_released("plr_walk"): if player.is_on_floor():
transition.emit("Stand") player_movement.jump()
transition.emit("Fall")
if event.is_action_pressed("plr_crouch"):
transition.emit("Crouch") func end_walk() -> void:
transition.emit("Stand")
func begin_crouch() -> void:
transition.emit("Crouch")

View file

@ -5,8 +5,5 @@ extends Node
@export var blue_team_texture: Texture2D @export var blue_team_texture: Texture2D
func _ready() -> void: func _ready() -> void:
get_tree().create_timer(1).timeout.connect(on_player_spawned)
func on_player_spawned() -> void:
if player.team == Session.TEAMS.DEFENCE: if player.team == Session.TEAMS.DEFENCE:
material.albedo_texture = blue_team_texture material.albedo_texture = blue_team_texture

View file

@ -13,6 +13,7 @@ func _ready() -> void:
else: else:
push_warning("Child of state machine is not state") push_warning("Child of state machine is not state")
current_state.enter()
func on_transition_required(to: StringName): func on_transition_required(to: StringName):
if is_multiplayer_authority() == false: if is_multiplayer_authority() == false:
@ -30,7 +31,7 @@ func change_state(to_state: State) -> void:
current_state = to_state current_state = to_state
current_state.enter() current_state.enter()
@rpc @rpc("authority","call_local","reliable")
func change_state_to_name(to_name: StringName): func change_state_to_name(to_name: StringName):
if current_state != null: if current_state != null:
current_state.exit() current_state.exit()

View file

@ -40,10 +40,10 @@ func interaction_start(player_id: int):
super(player_id) super(player_id)
defuse_timer.start() defuse_timer.start()
$DefuseAudio.multiplayer_play() $DefuseAudio.multiplayer_play()
Session.player_nodes[player_id].passive.rpc_id(player_id) Session.player_nodes[player_id].passive()
func interaction_end(): func interaction_end():
Session.player_nodes[interacted_id].depassive.rpc_id(interacted_id) Session.player_nodes[interacted_id].depassive()
super() super()
defuse_timer.stop() defuse_timer.stop()

View file

@ -7,6 +7,6 @@ func enter() -> void:
func exit() -> void: func exit() -> void:
pass pass
func state_input(event: InputEvent) -> void: func use_begin() -> void:
if event.is_action("plr_bomb") and Session.is_on_site(): if Session.is_on_site(machine.player.player_id):
transition.emit("Plant") transition.emit("Plant")

View file

@ -3,8 +3,9 @@ extends WeaponState
func enter(): func enter():
machine.animation_player.play(machine.animation_prefix+"plant") machine.animation_player.play(machine.animation_prefix+"plant")
machine.animation_player.animation_finished.connect(on_animation_finished) machine.animation_player.animation_finished.connect(on_animation_finished)
machine.speed_modifier = 0.0 if is_multiplayer_authority():
machine.player.get_node("PlantAudio").multiplayer_play() machine.speed_modifier = 0.0
machine.player.get_node("PlantAudio").multiplayer_play()
func exit(): func exit():
machine.animation_player.animation_finished.disconnect(on_animation_finished) machine.animation_player.animation_finished.disconnect(on_animation_finished)
@ -14,15 +15,13 @@ func on_animation_finished(animation: StringName):
if is_multiplayer_authority() == false: if is_multiplayer_authority() == false:
return return
if animation == machine.animation_prefix + "plant": if animation == machine.animation_prefix + "plant":
Session.spawn({"type": "object","spawn_name": "active_bomb", "position": machine.player_camera.get_parent().global_position,"plant": Session.get_site(machine.player.player_id).name})
Session.spawn({"type": "object","spawn_name": "active_bomb", "position": machine.player_camera.get_parent().global_position,"plant": Session.get_site().name})
machine.ammo -= 1 machine.ammo -= 1
return_to_previous.emit() return_to_previous.emit()
func state_input(event: InputEvent) -> void: func use_end() -> void:
if is_multiplayer_authority() == false: if is_multiplayer_authority() == false:
return return
if event.is_action_released("plr_bomb"): transition.emit("Idle")
transition.emit("Idle") machine.player.get_node("PlantAudio").multiplayer_stop()
machine.player.get_node("PlantAudio").multiplayer_stop()

View file

@ -4,15 +4,10 @@ extends WeaponState
func enter() -> void: func enter() -> void:
machine.animation_player.play(with_morphems("idle")) machine.animation_player.play(with_morphems("idle"))
machine.player.get_node("PlayerInput").reload.connect(init_reload)
func exit() -> void: func exit() -> void:
pass machine.player.get_node("PlayerInput").reload.disconnect(init_reload)
func state_input(event: InputEvent) -> void:
if not machine.is_multiplayer_authority() or Input.mouse_mode != Input.MouseMode.MOUSE_MODE_CAPTURED: return
if event.is_action_pressed("plr_reload"):
init_reload.rpc()
func use_begin() -> void: func use_begin() -> void:
if machine.ammo > 0: if machine.ammo > 0:

View file

@ -31,7 +31,6 @@ func use_begin() -> void:
func fire() -> void: func fire() -> void:
if machine.ammo == 0 or fire_timer.time_left > 0: if machine.ammo == 0 or fire_timer.time_left > 0:
return return
machine.player.get_node("ShootAudio").multiplayer_play()
machine.ammo -= 1 machine.ammo -= 1
bullets_shot += 1 bullets_shot += 1
@ -39,7 +38,8 @@ func fire() -> void:
machine.animation_player.play(with_morphems("shoot")) machine.animation_player.play(with_morphems("shoot"))
if is_multiplayer_authority(): if is_multiplayer_authority():
Session.shoot(damage,shoot_distance) Session.shoot(int(machine.player.name),damage,shoot_distance)
machine.player.get_node("ShootAudio").multiplayer_play()
fire_timer.start() fire_timer.start()
machine.player_camera.recoil(horizontal_curve.sample(bullets_shot),vertical_curve.sample(bullets_shot)) machine.player_camera.recoil(horizontal_curve.sample(bullets_shot),vertical_curve.sample(bullets_shot))

View file

@ -14,7 +14,7 @@ func exit() -> void:
func attack() -> void: func attack() -> void:
if is_multiplayer_authority(): if is_multiplayer_authority():
Session.shoot(damage,1.5) Session.shoot(int(machine.player.name),damage,1.5)
func on_animation_finished(animation): func on_animation_finished(animation):
if animation == machine.animation_prefix + "attack": if animation == machine.animation_prefix + "attack":

View file

@ -12,7 +12,7 @@ func exit() -> void:
func attack() -> void: func attack() -> void:
if is_multiplayer_authority(): if is_multiplayer_authority():
Session.shoot(damage,1.5) Session.shoot(int(machine.player.name),damage,1.5)
func on_animation_finished(animation): func on_animation_finished(animation):
if animation == machine.animation_prefix + "heavy_attack": if animation == machine.animation_prefix + "heavy_attack":

View file

@ -64,6 +64,7 @@ func exit() -> void:
@rpc("authority","call_local","reliable") @rpc("authority","call_local","reliable")
func use_begin() -> void: func use_begin() -> void:
current_state.use_begin() current_state.use_begin()
@rpc("authority","call_local","reliable") @rpc("authority","call_local","reliable")
func use_end() -> void: func use_end() -> void:
current_state.use_end() current_state.use_end()

View file

@ -5,6 +5,7 @@ class_name WeaponSystem
@export var animation_player: AnimationPlayer @export var animation_player: AnimationPlayer
@export var camera: PlayerCamera @export var camera: PlayerCamera
@export var player: Player @export var player: Player
@export var player_input: PlayerInput
var current_state: WeaponSubStateMachine var current_state: WeaponSubStateMachine
var last_slot: StringName var last_slot: StringName
@ -27,6 +28,12 @@ signal ammo_updated(ammo: int, remaining_ammo: int)
func _ready() -> void: func _ready() -> void:
$WeaponSpawner.spawn_function = pick_up_weapon $WeaponSpawner.spawn_function = pick_up_weapon
player_input.drop.connect(drop_current)
player_input.fire_begin.connect(use_begin)
player_input.fire_end.connect(use_end)
player_input.switch_weapon.connect(switch)
player_input.alternate_state.connect(alternate_state)
player_input.switch_firemode.connect(switch_mode)
func get_speed_modifier() -> float: func get_speed_modifier() -> float:
if current_state == null: if current_state == null:
@ -64,8 +71,9 @@ func add(state: WeaponSubStateMachine, slot: StringName,ignore_parent: bool = fa
ammo_updated.emit(current_state.ammo,current_state.remaining_ammo) ammo_updated.emit(current_state.ammo,current_state.remaining_ammo)
state.enter.call_deferred() state.enter.call_deferred()
@rpc("authority","call_remote","reliable")
func switch(to: StringName, exit: bool = true): func switch(to: StringName, exit: bool = true):
if slots.has(to) == false or slots[to] == null or slots[to] == current_state or is_multiplayer_authority() == false: if slots.has(to) == false or slots[to] == null or slots[to] == current_state or (multiplayer.get_remote_sender_id() != 1 and is_multiplayer_authority() == false):
return return
if current_state != null and exit: if current_state != null and exit:
current_state.exit() current_state.exit()
@ -78,8 +86,8 @@ func switch(to: StringName, exit: bool = true):
ammo_updated.emit(current_state.ammo,current_state.remaining_ammo) ammo_updated.emit(current_state.ammo,current_state.remaining_ammo)
switched_to.emit(current_state) switched_to.emit(current_state)
if is_multiplayer_authority():
update_remotes.rpc(to,exit) switch.rpc(to,exit)
func return_to_previous(exit: bool = true): func return_to_previous(exit: bool = true):
if last_slot != "": if last_slot != "":
@ -87,19 +95,12 @@ func return_to_previous(exit: bool = true):
else: else:
switch("knife", exit) switch("knife", exit)
@rpc("authority","call_remote","reliable")
func update_remotes(to: StringName,exit: bool):
if current_state != null and exit:
current_state.exit()
current_state = slots[to]
current_state.enter()
switched_to.emit(current_state)
func drop_current(): func drop_current():
drop(current_state) drop(current_state)
func drop(weapon: WeaponSubStateMachine) -> void: func drop(weapon: WeaponSubStateMachine) -> void:
if not is_multiplayer_authority():
return
if slots.find_key(weapon) == "knife": if slots.find_key(weapon) == "knife":
return return
var drop_data: Dictionary = {} var drop_data: Dictionary = {}
@ -174,39 +175,14 @@ func _physics_process(delta: float) -> void:
return return
current_state.physics_update(delta) current_state.physics_update(delta)
func _input(event: InputEvent) -> void: func use_begin() -> void:
if is_multiplayer_authority() == false or disabled: return current_state.use_begin.rpc()
if current_state != null: func use_end() -> void:
current_state.state_input(event) current_state.use_end.rpc()
if event.is_action_pressed("plr_ult"): func alternate_state() -> void:
switch("ultimate") current_state.alternate_state()
elif event.is_action_pressed("plr_bomb"):
switch("bomb") func switch_mode() -> void:
elif event.is_action_pressed("plr_primary"): current_state.switch_mode()
switch("primary")
elif event.is_action_pressed("plr_active_first"):
switch("ability_first")
elif event.is_action_pressed("plr_active_second"):
switch("ability_second")
elif event.is_action_pressed("plr_active_third"):
switch("ability_third")
elif event.is_action_pressed("plr_secondary"):
switch("secondary")
elif event.is_action_pressed("plr_knife"):
switch("knife")
if not Session.round_state == Session.ROUND_STATES.BUY and not player.passived:
if event.is_action_pressed("plr_fire"):
current_state.use_begin.rpc()
if event.is_action_released("plr_fire"):
current_state.use_end.rpc()
if event.is_action_pressed("plr_scope"):
current_state.alternate_state()
if event.is_action_pressed("plr_firemode"):
current_state.switch_mode()
if event.is_action_pressed("plr_drop"):
drop_current()