diff --git a/components/flag_carry_component.gd b/components/flag_carry_component.gd index d3235e3..5b0980e 100644 --- a/components/flag_carry_component.gd +++ b/components/flag_carry_component.gd @@ -1,6 +1,24 @@ +# This file is part of open-fpsz. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . class_name FlagCarryComponent extends Node +## This component allows its entity to grab, carry and throw flags +## +## To work correctly the owner MUST set an attachment point for carried flags +## and a sensor to detect when flags are within grab range -@export var throw_velocity : float = 10.0 +@export var max_throw_speed : float = 10.0 @export var attachment : Node3D @export var sensor : Area3D @@ -20,11 +38,12 @@ func _grab(flag : Flag): flag.grab() _carried_flag = flag -func throw(): +@rpc("call_local") +func _drop(throw_speed : float): if _is_carrying(): _carried_flag.drop() - _carried_flag.linear_velocity = attachment.global_basis.z * throw_velocity _carried_flag.rotation_degrees.x = 0.0 + _carried_flag.linear_velocity = attachment.global_basis.z * throw_speed _carried_flag = null func _is_carrying() -> bool: @@ -33,3 +52,9 @@ func _is_carrying() -> bool: func _sensor_on_body_entered(collider): if collider is Flag: _grab.rpc(collider) + +func drop(): + _drop.rpc(0.0) + +func throw(): + _drop.rpc(max_throw_speed) diff --git a/components/health_component.gd b/components/health_component.gd index 15daa99..1d13446 100644 --- a/components/health_component.gd +++ b/components/health_component.gd @@ -1,15 +1,15 @@ # This file is part of open-fpsz. -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . class_name HealthComponent extends Area3D diff --git a/components/health_component.tscn b/components/health_component.tscn index 8f7350a..6dd6121 100644 --- a/components/health_component.tscn +++ b/components/health_component.tscn @@ -1,12 +1,8 @@ -[gd_scene load_steps=3 format=3 uid="uid://bof3mg7wgxrmn"] +[gd_scene load_steps=2 format=3 uid="uid://bof3mg7wgxrmn"] [ext_resource type="Script" path="res://components/health_component.gd" id="1_00xis"] -[ext_resource type="Shape3D" uid="uid://dkwljsgaflf31" path="res://entities/player/collision_shape.res" id="2_sgbmt"] [node name="HealthComponent" type="Area3D"] collision_layer = 4 collision_mask = 0 script = ExtResource("1_00xis") - -[node name="CollisionShape3D" type="CollisionShape3D" parent="."] -shape = ExtResource("2_sgbmt") diff --git a/entities/player/collision_shape.res b/entities/player/collision_shape.res deleted file mode 100644 index 16a86b7..0000000 Binary files a/entities/player/collision_shape.res and /dev/null differ diff --git a/entities/player/collision_shape.tres b/entities/player/collision_shape.tres new file mode 100644 index 0000000..0195e9e --- /dev/null +++ b/entities/player/collision_shape.tres @@ -0,0 +1,4 @@ +[gd_resource type="CapsuleShape3D" format=3 uid="uid://cb8esdlnottdn"] + +[resource] +radius = 0.25 diff --git a/entities/player/player.gd b/entities/player/player.gd index 759905e..29ebb6d 100644 --- a/entities/player/player.gd +++ b/entities/player/player.gd @@ -36,6 +36,7 @@ enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD } set(id): player_id = id $PlayerInput.set_multiplayer_authority(id) +@export var nickname : String @onready var input : PlayerInput = $PlayerInput @onready var camera = $SpringArm3D/Camera3D @@ -45,7 +46,7 @@ enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD } @onready var weapon = $SpringArm3D/Inventory/SpaceGun @onready var animation_player : AnimationPlayer = $AnimationPlayer @onready var health_component = $HealthComponent -@onready var flag_carry_component = $FlagCarryComponent +@onready var flag_carry_component : FlagCarryComponent = $FlagCarryComponent @onready var spring_arm_height = $SpringArm3D.position.y @onready var _original_weapon_transform : Transform3D = weapon.transform @onready var flag_carry_attachment = $SpringArm3D/FlagCarryAttachment @@ -65,7 +66,6 @@ func _ready(): health_component.health_zeroed.connect(_die) if _is_first_person(): camera.current = true - flag_carry_attachment.hide() remove_child($ThirdPerson) else: remove_child($HUD) @@ -214,6 +214,11 @@ func _die(): if _is_first_person(): animation_player.stop() ) + flag_carry_component.drop() + +@rpc("call_local") +func set_nickname(value): + nickname = value func respawn(location): linear_velocity = Vector3() diff --git a/entities/player/player.tscn b/entities/player/player.tscn index ae12017..d17c267 100644 --- a/entities/player/player.tscn +++ b/entities/player/player.tscn @@ -1,8 +1,8 @@ [gd_scene load_steps=21 format=3 uid="uid://cbhx1xme0sb7k"] [ext_resource type="Script" path="res://entities/player/player.gd" id="1_mk68k"] -[ext_resource type="Shape3D" uid="uid://dkwljsgaflf31" path="res://entities/player/collision_shape.res" id="2_8rtw3"] [ext_resource type="PackedScene" uid="uid://drbefw6akui2v" path="res://entities/player/assets/vanguard.tscn" id="2_beyex"] +[ext_resource type="Shape3D" uid="uid://cb8esdlnottdn" path="res://entities/player/collision_shape.tres" id="2_vjqny"] [ext_resource type="PackedScene" uid="uid://bcv81ku26xo" path="res://interfaces/hud/hud.tscn" id="3_ccety"] [ext_resource type="PackedScene" uid="uid://c8co0qa2omjmh" path="res://weapons/space_gun/space_gun.tscn" id="4_lhn5w"] [ext_resource type="PackedScene" uid="uid://dn1tcakam5egs" path="res://weapons/space_gun/projectile.tscn" id="5_lvaut"] @@ -180,6 +180,9 @@ properties/3/replication_mode = 2 properties/4/path = NodePath(".:player_state") properties/4/spawn = true properties/4/replication_mode = 2 +properties/5/path = NodePath(".:nickname") +properties/5/spawn = true +properties/5/replication_mode = 2 [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_5j4ew"] properties/0/path = NodePath(".:direction") @@ -210,11 +213,11 @@ visible = false mesh = SubResource("CapsuleMesh_vmqfq") [node name="CollisionShape3D" type="CollisionShape3D" parent="."] -shape = ExtResource("2_8rtw3") +shape = ExtResource("2_vjqny") [node name="ShapeCast3D" type="ShapeCast3D" parent="."] transform = Transform3D(1.05, 0, 0, 0, 1.05, 0, 0, 0, 1.05, 0, 0, 0) -shape = ExtResource("2_8rtw3") +shape = ExtResource("2_vjqny") target_position = Vector3(0, 0, 0) collision_mask = 2147483656 collide_with_areas = true @@ -225,7 +228,7 @@ collision_mask = 8 monitorable = false [node name="CollisionShape3D" type="CollisionShape3D" parent="Sensor"] -shape = ExtResource("2_8rtw3") +shape = ExtResource("2_vjqny") [node name="HUD" parent="." instance=ExtResource("3_ccety")] @@ -252,8 +255,10 @@ transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 0, -0. [node name="HealthComponent" parent="." instance=ExtResource("5_t6i6e")] +[node name="CollisionShape3D" type="CollisionShape3D" parent="HealthComponent"] +shape = ExtResource("2_vjqny") + [node name="FlagCarryComponent" parent="." node_paths=PackedStringArray("attachment", "sensor") instance=ExtResource("7_e7s1a")] -throw_velocity = 20.0 attachment = NodePath("../SpringArm3D/FlagCarryAttachment") sensor = NodePath("../Sensor") diff --git a/interfaces/hud/iff.gd b/interfaces/hud/iff.gd index e064c21..41d0941 100644 --- a/interfaces/hud/iff.gd +++ b/interfaces/hud/iff.gd @@ -1,15 +1,15 @@ # This file is part of open-fpsz. -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . extends Node2D @@ -28,7 +28,7 @@ func _process(_delta): else: _v_box_container.show() - _player_name_label.text = player.name + _player_name_label.text = player.nickname position = camera.unproject_position(attach_point.global_position) var viewport_size : Vector2 = get_viewport_rect().size position.x = clampf(position.x, 0, viewport_size.x - _v_box_container.size.x) diff --git a/interfaces/menus/boot/boot.tscn b/interfaces/menus/boot/boot.tscn index 82c6d8d..d752e80 100644 --- a/interfaces/menus/boot/boot.tscn +++ b/interfaces/menus/boot/boot.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=7 format=3 uid="uid://bjctlqvs33nqy"] +[gd_scene load_steps=6 format=3 uid="uid://bjctlqvs33nqy"] [ext_resource type="Texture2D" uid="uid://c1tjamjm8qjog" path="res://interfaces/menus/boot/background.webp" id="1_ph586"] @@ -10,6 +10,13 @@ signal start_demo func _on_demo_pressed(): start_demo.emit() + +func _on_multiplayer_pressed(): + $Main.hide() + $Multiplayer.show() + +func _on_quit_pressed(): + get_tree().quit() " [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_krqeq"] @@ -20,9 +27,11 @@ script/source = "class_name MultiplayerPanel extends PanelContainer const DEFAULT_HOST : String = \"localhost\" const DEFAULT_PORT : int = 9000 +const CONFIG_FILE_PATH : String = \"user://settings.cfg\" -var _join_address = RegEx.new() -var _registered_ports = RegEx.new() +var _join_address : RegEx = RegEx.new() +var _registered_ports : RegEx = RegEx.new() +var _config_file : ConfigFile = ConfigFile.new() signal start_server(port) signal join_server(host, port) @@ -34,8 +43,21 @@ func _ready(): # see https://datatracker.ietf.org/doc/html/rfc1700 _registered_ports.compile(r'^(?:102[4-9]|10[3-9]\\d|1[1-9]\\d{2}|[2-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])$') _join_address.compile(r'^(?[a-zA-Z0-9.-]+)(:(?:102[4-9]|10[3-9]\\d|1[1-9]\\d{2}|[2-9]\\d{3}|[1-5]\\d{4}|6[0-4]\\d{3}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5]))?$') + _load_config() hide() # start hidden +func _load_config(): + var error : Error = _config_file.load(CONFIG_FILE_PATH) + if error != OK: + return + + var profile_name : String = _config_file.get_value(\"profile\", \"name\", \"Newblood\") + %ProfileName.text = profile_name + +func _on_save_pressed(): + _config_file.set_value(\"profile\", \"name\", %ProfileName.text) + _config_file.save(CONFIG_FILE_PATH) + func _on_menu_pressed(): hide() owner.get_node(\"Main\").show() @@ -53,8 +75,8 @@ func _on_host_pressed(): else: # port is not valid push_warning(\"A valid port number in the range 1024-65535 is required.\") return - - start_server.emit(port) + + start_server.emit(port, %ProfileName.text) func _on_join_pressed(): var addr = [DEFAULT_HOST, DEFAULT_PORT] @@ -66,7 +88,7 @@ func _on_join_pressed(): if rport: addr[1] = int(rport) $Modal.show() - join_server.emit(addr[0], addr[1]) + join_server.emit(addr[0], addr[1], %ProfileName.text) func _on_connected_to_server(): $Modal.hide() @@ -79,17 +101,6 @@ func _on_connection_failed(): [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_snh7i"] bg_color = Color(0, 0.5, 0.5, 0.25) -[sub_resource type="GDScript" id="GDScript_yqbr7"] -script/source = "extends PanelContainer - -func _on_multiplayer_pressed(): - hide() - owner.get_node(\"Multiplayer\").show() - -func _on_quit_pressed(): - get_tree().quit() -" - [node name="BootMenu" type="CanvasLayer"] script = SubResource("GDScript_jd8xf") @@ -156,6 +167,10 @@ layout_mode = 2 disabled = true text = "Delete" +[node name="Save" type="Button" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"] +layout_mode = 2 +text = "Save" + [node name="Spacer" type="MarginContainer" parent="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox"] layout_mode = 2 size_flags_vertical = 3 @@ -313,7 +328,6 @@ offset_right = 313.0 grow_vertical = 2 size_flags_horizontal = 0 theme_override_styles/panel = SubResource("StyleBoxFlat_snh7i") -script = SubResource("GDScript_yqbr7") [node name="MarginContainer" type="MarginContainer" parent="Main"] layout_mode = 2 @@ -342,6 +356,7 @@ text = "Quit" [connection signal="join_server" from="Multiplayer" to="." method="_on_multiplayer_join_server"] [connection signal="start_server" from="Multiplayer" to="." method="_on_multiplayer_start_server"] +[connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Save" to="Multiplayer" method="_on_save_pressed"] [connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Menu" to="Multiplayer" method="_on_menu_pressed"] [connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Profile/MarginContainer/HBoxContainer/LeftBox/Quit" to="Multiplayer" method="_on_quit_pressed"] [connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Join/MarginContainer/HBoxContainer/LeftBox/Join" to="Multiplayer" method="_on_join_pressed"] @@ -352,5 +367,5 @@ text = "Quit" [connection signal="pressed" from="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/LeftBox/Quit" to="Multiplayer" method="_on_quit_pressed"] [connection signal="text_changed" from="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox/ServerPort" to="Multiplayer/MarginContainer/TabContainer/Host/MarginContainer/HBoxContainer/RightBox/ServerPort" method="_on_text_changed"] [connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Demo" to="." method="_on_demo_pressed"] -[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Multiplayer" to="Main" method="_on_multiplayer_pressed"] -[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Quit" to="Main" method="_on_quit_pressed"] +[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Multiplayer" to="." method="_on_multiplayer_pressed"] +[connection signal="pressed" from="Main/MarginContainer/VBoxContainer/Quit" to="." method="_on_quit_pressed"] diff --git a/main.tscn b/main.tscn index 10288e1..2fa6731 100644 --- a/main.tscn +++ b/main.tscn @@ -24,20 +24,20 @@ func _start_demo(): add_child(mode) $BootMenu.hide() -func _start_server(port): +func _start_server(port, nickname): if mode: mode.queue_free() mode = MULTIPLAYER.instantiate() add_child(mode) - mode.start_server(port) + mode.start_server(port, nickname) $BootMenu.hide() -func _join_server(host, port): +func _join_server(host, port, nickname): if mode: mode.queue_free() mode = MULTIPLAYER.instantiate() add_child(mode) mode.connected_to_server.connect($BootMenu/Multiplayer._on_connected_to_server) mode.connection_failed.connect($BootMenu/Multiplayer._on_connection_failed) - mode.join_server(host, port) + mode.join_server(host, port, nickname) func _unhandled_input(event): # exit the program diff --git a/modes/multiplayer.tscn b/modes/multiplayer.tscn index a2d3e5a..8d9f249 100644 --- a/modes/multiplayer.tscn +++ b/modes/multiplayer.tscn @@ -23,7 +23,7 @@ signal connection_failed func load_map(scene : PackedScene): map.add_child(scene.instantiate()) -func start_server(port): +func start_server(port, nickname): var peer = ENetMultiplayerPeer.new() peer.create_server(port, MAX_CLIENTS) @@ -34,23 +34,21 @@ func start_server(port): multiplayer.peer_connected.connect(add_player) multiplayer.peer_disconnected.connect(remove_player) - for id in multiplayer.get_peers(): - add_player(id) - if DisplayServer.get_name() != \"headless\": - add_player(1) + add_player(1, nickname) add_flag() -func join_server(host, port): +func join_server(host, port, nickname): var peer = ENetMultiplayerPeer.new() peer.create_client(host, port) - multiplayer.connected_to_server.connect(_on_connected_to_server) + multiplayer.connected_to_server.connect(_on_connected_to_server.bind(nickname)) multiplayer.connection_failed.connect(_on_connection_failed) multiplayer.multiplayer_peer = peer -func _on_connected_to_server(): +func _on_connected_to_server(nickname): connected_to_server.emit() + _join_match.rpc(nickname) func _on_connection_failed(): connection_failed.emit() @@ -58,10 +56,11 @@ func _on_connection_failed(): func respawn_player(player): player.respawn(Vector3(0.0, 150.0, 0.0)) -func add_player(peer_id : int): +func add_player(peer_id : int, nickname : String): var player : Player = PLAYER.instantiate() player.name = str(peer_id) player.player_id = peer_id + player.nickname = nickname player.position = Vector3(0.0, 150.0, 0.0) players.add_child(player) player.died.connect(respawn_player) @@ -73,6 +72,12 @@ func remove_player(peer_id : int): players.get_node(node_name).queue_free() print(\"Peer `%s` disconnected\" % node_name) +@rpc(\"any_peer\") +func _join_match(nickname): + if multiplayer.is_server(): + add_player(multiplayer.get_remote_sender_id(), nickname) + + func add_flag(): var flag : Flag = FLAG.instantiate() flag.position = Vector3(5.0, 100.0, 0.0) diff --git a/weapons/space_gun/projectile_trail.gd b/weapons/space_gun/projectile_trail.gd index 1296fe8..ac8606a 100644 --- a/weapons/space_gun/projectile_trail.gd +++ b/weapons/space_gun/projectile_trail.gd @@ -1,15 +1,15 @@ # This file is part of open-fpsz. -# +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# +# # You should have received a copy of the GNU General Public License # along with this program. If not, see . class_name Trail3D extends MeshInstance3D @@ -54,7 +54,7 @@ func _process(delta): if(_old_pos - get_global_transform().origin).length() > _motion_delta and _trail_enabled: _append_point() # Create new point _old_pos = get_global_transform().origin # Update previous position to current position coordinates - + # Update the lifespan var p = 0 var max_points = _points.size() @@ -64,29 +64,29 @@ func _process(delta): _remove_point(p) p -= 1 if (p < 0): p = 0 - + max_points = _points.size() p += 1 - + mesh.clear_surfaces() - + # If less than 2 points, stop rendering trail if _points.size() < 2: return - + # Render new mesh for each point mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP) - + for i in range(_points.size()): var t = float(i) / (_points.size() - 1.0) var curr_color = _start_color.lerp(_end_color, 1 - t) mesh.surface_set_color(curr_color) - + var curr_width = _widths[i][0] - pow(1 - t, _scale_acceleration) * _widths[i][1] - + var t0 = i / _points.size() var t1 = t - + mesh.surface_set_uv(Vector2(t0, 0)) mesh.surface_add_vertex(to_local(_points[i] + curr_width)) mesh.surface_set_uv(Vector2(t1, 1))