Merge branch 'feat/settings' into 'develop'

🔧 Settings, Maps and Environments management

See merge request open-fpsz/open-fpsz!79
This commit is contained in:
anyreso 2024-04-28 06:15:19 +00:00
commit 0cf558f436
31 changed files with 1917 additions and 381 deletions

View file

@ -3,24 +3,21 @@ class_name MatchParticipantComponent extends MultiplayerSynchronizer
signal player_id_changed(new_player_id : int)
signal nickname_changed(new_nickname : String)
@export var nickname : String = "<Newblood>":
set(value):
nickname = value
nickname_changed.emit(nickname)
@export var player_id : int:
set(value):
player_id = value
player_id_changed.emit(player_id)
@export var team_id : int = 1
@export var nickname : String = "<Newblood>":
set(value):
nickname = value
nickname_changed.emit(nickname)
func _ready() -> void:
replication_config = SceneReplicationConfig.new()
root_path = "."
_set_replication_for(NodePath("player_id").get_as_property_path())
_set_replication_for(NodePath("team_id").get_as_property_path())
_set_replication_for(NodePath("nickname").get_as_property_path())
func _set_replication_for(property_node_path : NodePath) -> void:
replication_config.add_property(property_node_path)
replication_config.property_set_replication_mode(property_node_path, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE)
replication_config = SceneReplicationConfig.new()
for prop : String in ["player_id", "team_id", "nickname"]:
var prop_path : NodePath = NodePath(prop).get_as_property_path()
replication_config.add_property(prop_path)
replication_config.property_set_replication_mode(
prop_path, SceneReplicationConfig.REPLICATION_MODE_ON_CHANGE)

View file

@ -1,3 +1,17 @@
# 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 <https://www.gnu.org/licenses/>.
class_name Flag extends Node3D
enum FlagState { FLAG_STATE_ON_STAND, FLAG_STATE_DROPPED, FLAG_STATE_TAKEN }

View file

@ -48,7 +48,6 @@ enum PlayerState { PLAYER_ALIVE, PLAYER_DEAD }
@onready var spring_arm_height : float = $Smoothing/SpringArm3D.position.y
@onready var _original_weapon_transform : Transform3D = weapon.transform
@onready var tp_player : Vanguard = $Smoothing/ThirdPerson/PlayerMesh
@onready var _game_settings : Settings = get_node("/root/GlobalSettings")
@onready var jetpack_particles : Array = $Smoothing/ThirdPerson/PlayerMesh/JetpackFX.get_children()
@onready var match_participant_component : MatchParticipantComponent = $MatchParticipantComponent
@ -74,13 +73,13 @@ func _ready() -> void:
input.jumped.connect(_jump)
input.throwed_flag.connect(_throw_flag)
input.MOUSE_SENSITIVITY = _game_settings.mouse_sensitivity
input.inverted_y_axis = _game_settings.inverted_y_axis
input.MOUSE_SENSITIVITY = Settings.get_value("controls", "mouse_sensitivity")
input.inverted_y_axis = Settings.get_value("controls", "inverted_y_axis")
func _setup_pawn(_new_player_id : int) -> void:
if _is_pawn():
camera.current = true
camera.fov = _game_settings.fov
camera.fov = Settings.get_value("video", "fov")
pawn_player = self
# set the spring arm translation to be about head height level
$Smoothing/SpringArm3D.transform = Transform3D().translated(Vector3(0, collision_shape.shape.height / 2, 0) * 0.9)
@ -154,7 +153,7 @@ func _process(_delta : float) -> void:
if not _is_pawn():
tp_player.global_transform.basis = Basis.from_euler(Vector3(0.0, input.camera_rotation.x + PI, 0.0))
elif not %Inventory/SpaceGun/Mesh/AnimationPlayer.is_playing():
%Inventory/SpaceGun/Mesh/AnimationPlayer.play("idle")
%Inventory/SpaceGun/Mesh/AnimationPlayer.play("idle")
%SpringArm3D.global_transform.basis = Basis.from_euler(Vector3(input.camera_rotation.y, input.camera_rotation.x, 0.0))
func _physics_process(delta : float) -> void:

View file

@ -36,7 +36,6 @@ func update_multiplayer_authority(player_id : int) -> void:
func _unhandled_input(event: InputEvent) -> void:
var mouse_mode : Input.MouseMode = Input.get_mouse_mode()
# isolate mouse events
if event is InputEventMouseMotion:
if mouse_mode == Input.MOUSE_MODE_CAPTURED:
@ -44,14 +43,15 @@ func _unhandled_input(event: InputEvent) -> void:
_update_camera(event.relative)
func _update_camera(relative_motion : Vector2) -> void:
# clamp vertical rotation (head motion)
# reverse y axis
if inverted_y_axis:
relative_motion.y *= -1.0
# clamp vertical rotation (head motion)
camera_rotation.y -= relative_motion.y * MOUSE_SENSITIVITY / 100
camera_rotation.y = clamp(camera_rotation.y, deg_to_rad(-90.0),deg_to_rad(90.0))
camera_rotation.y = clamp(camera_rotation.y, deg_to_rad(-90.0), deg_to_rad(90.0))
# wrap horizontal rotation (to prevent accumulation)
camera_rotation.x -= relative_motion.x * MOUSE_SENSITIVITY / 100
camera_rotation.x = wrapf(camera_rotation.x, deg_to_rad(0.0),deg_to_rad(360.0))
camera_rotation.x = wrapf(camera_rotation.x, deg_to_rad(0.0), deg_to_rad(360.0))
func _process(_delta : float) -> void:
direction = Input.get_vector("left", "right", "forward", "backward")

View file

@ -4,7 +4,21 @@
[ext_resource type="StyleBox" uid="uid://bq7rjpm38pao7" path="res://interfaces/hud/vitals/health_foreground.tres" id="2_6ejsl"]
[sub_resource type="GDScript" id="GDScript_2vxif"]
script/source = "class_name HUD extends CanvasLayer
script/source = "# 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 <https://www.gnu.org/licenses/>.
class_name HUD extends CanvasLayer
@export_category(\"Vitals\")
@export var _health_bar : ProgressBar
@ -39,15 +53,15 @@ func _ready() -> void:
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta : float) -> void:
var velocity_xz : Vector3 = player.linear_velocity
velocity_xz.y = 0
text = \"\"
text += \"fps: %s\\n\" % str(Engine.get_frames_per_second())
text += \"fps: %d (%.2f mspf)\\n\" % [Engine.get_frames_per_second(), 1000.0 / Engine.get_frames_per_second()]
text += \"position: %d, %d, %d\\n\" % [player.position.x, player.position.y, player.position.z]
text += \"speed: %d km/h\\n\" % (player.linear_velocity.length() * 3.6)
var velocity_xz := Vector3(player.linear_velocity.x, 0., player.linear_velocity.z)
text += \"speed_xz: %d km/h\\n\" % (velocity_xz.length() * 3.6)
var viewport_render_size : Vector2i = get_viewport().size * get_viewport().scaling_3d_scale
text += \"3D viewport resolution: %d × %d (%d%%)\\n\" \\
% [viewport_render_size.x, viewport_render_size.y, round(get_viewport().scaling_3d_scale * 100)]
"
[sub_resource type="Shader" id="Shader_gaah5"]

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,26 @@
[gd_scene load_steps=6 format=3 uid="uid://ma1if3sjox6i"]
[ext_resource type="PackedScene" uid="uid://boviiugcnfyrj" path="res://modes/demo.tscn" id="1_50a80"]
[ext_resource type="PackedScene" uid="uid://boviiugcnfyrj" path="res://modes/singleplayer/demo.tscn" id="1_50a80"]
[ext_resource type="PackedScene" uid="uid://bjctlqvs33nqy" path="res://interfaces/menus/boot/boot.tscn" id="1_acy5o"]
[ext_resource type="PackedScene" uid="uid://bvwxfgygm2xb8" path="res://modes/multiplayer.tscn" id="2_g8xeb"]
[ext_resource type="PackedScene" uid="uid://bvwxfgygm2xb8" path="res://modes/multiplayer/multiplayer.tscn" id="2_g8xeb"]
[ext_resource type="Resource" uid="uid://dut5f1sq0wfeb" path="res://maps/maps.tres" id="3_1ipir"]
[sub_resource type="GDScript" id="GDScript_e61dq"]
script/source = "class_name Game extends Node3D
script/source = "# 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 <https://www.gnu.org/licenses/>.
class_name Game extends Node3D
@export_category(\"Modes\")
@export var SINGLEPLAYER : PackedScene
@ -32,10 +46,15 @@ var mode : Node:
else:
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
func _ready() -> void:
$BootMenu.start_demo.connect(_start_demo)
$BootMenu/Multiplayer.start_server.connect(_start_server)
$BootMenu/Multiplayer.join_server.connect(_join_server)
$BootMenu/MultiplayerPanelContainer.start_server.connect(_start_server)
$BootMenu/MultiplayerPanelContainer.join_server.connect(_join_server)
# do not set initial window mode for debug build
if not OS.is_debug_build():
DisplayServer.window_set_mode(Settings.get_value(\"video\", \"window_mode\"))
func _unhandled_input(event : InputEvent) -> void:
if event.is_action_pressed(\"exit\"):
@ -70,14 +89,14 @@ func _start_server(port : int, nickname : String) -> void:
mode.start_server({
\"port\": port,
\"nickname\": nickname,
\"map\": maps[clamp($BootMenu/Multiplayer.map_selector.selected, 0, len(maps))]
\"map\": maps[clamp($BootMenu/MultiplayerPanelContainer.map_selector.selected, 0, len(maps))]
})
$BootMenu.hide()
func _join_server(host : String, port : int, nickname : String) -> void:
mode = MULTIPLAYER.instantiate()
mode.connected_to_server.connect($BootMenu/Multiplayer._on_connected_to_server)
mode.connection_failed.connect($BootMenu/Multiplayer._on_connection_failed)
mode.connected_to_server.connect($BootMenu/MultiplayerPanelContainer._on_connected_to_server)
mode.connection_failed.connect($BootMenu/MultiplayerPanelContainer._on_connection_failed)
mode.join_server(host, port, nickname)
"

Binary file not shown.

View file

Before

Width:  |  Height:  |  Size: 2.5 MiB

After

Width:  |  Height:  |  Size: 2.5 MiB

View file

@ -3,7 +3,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cngjywcua4vv8"
path.bptc="res://.godot/imported/ground054_alb_ht.png-c1e6560e1b831d8f5772408a395cdf1b.bptc.ctex"
path.bptc="res://.godot/imported/ground054_alb_ht.png-460d3ac5c09d7955ca61b8b57742b1a9.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
@ -11,8 +11,8 @@ metadata={
[deps]
source_file="res://maps/desert/textures/ground054_alb_ht.png"
dest_files=["res://.godot/imported/ground054_alb_ht.png-c1e6560e1b831d8f5772408a395cdf1b.bptc.ctex"]
source_file="res://maps/desert/assets/textures/ground054_alb_ht.png"
dest_files=["res://.godot/imported/ground054_alb_ht.png-460d3ac5c09d7955ca61b8b57742b1a9.bptc.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

View file

@ -3,7 +3,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cbk7l6hs0yrcc"
path.bptc="res://.godot/imported/ground054_nrm_rgh.png-70f079690ff8219938f9079109780fc1.bptc.ctex"
path.bptc="res://.godot/imported/ground054_nrm_rgh.png-9ea209f1a7f6e48624db85005a037890.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
@ -11,8 +11,8 @@ metadata={
[deps]
source_file="res://maps/desert/textures/ground054_nrm_rgh.png"
dest_files=["res://.godot/imported/ground054_nrm_rgh.png-70f079690ff8219938f9079109780fc1.bptc.ctex"]
source_file="res://maps/desert/assets/textures/ground054_nrm_rgh.png"
dest_files=["res://.godot/imported/ground054_nrm_rgh.png-9ea209f1a7f6e48624db85005a037890.bptc.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 2.3 MiB

View file

@ -3,7 +3,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dwk8islw7ebab"
path.bptc="res://.godot/imported/rock029_alb_ht.png-a5e0a4f98f29bdeb159f1e749d7737b1.bptc.ctex"
path.bptc="res://.godot/imported/rock029_alb_ht.png-dd746789bc129bafaa8d1cc908de0e3e.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
@ -11,8 +11,8 @@ metadata={
[deps]
source_file="res://maps/desert/textures/rock029_alb_ht.png"
dest_files=["res://.godot/imported/rock029_alb_ht.png-a5e0a4f98f29bdeb159f1e749d7737b1.bptc.ctex"]
source_file="res://maps/desert/assets/textures/rock029_alb_ht.png"
dest_files=["res://.godot/imported/rock029_alb_ht.png-dd746789bc129bafaa8d1cc908de0e3e.bptc.ctex"]
[params]

View file

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 3.2 MiB

View file

@ -3,7 +3,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://lgfhdcsb2ryx"
path.bptc="res://.godot/imported/rock029_nrm_rgh.png-21134283f9adb86493d1d72a4f30e20a.bptc.ctex"
path.bptc="res://.godot/imported/rock029_nrm_rgh.png-3bf029664d0f58a1c79abd2d6666ba90.bptc.ctex"
metadata={
"imported_formats": ["s3tc_bptc"],
"vram_texture": true
@ -11,8 +11,8 @@ metadata={
[deps]
source_file="res://maps/desert/textures/rock029_nrm_rgh.png"
dest_files=["res://.godot/imported/rock029_nrm_rgh.png-21134283f9adb86493d1d72a4f30e20a.bptc.ctex"]
source_file="res://maps/desert/assets/textures/rock029_nrm_rgh.png"
dest_files=["res://.godot/imported/rock029_nrm_rgh.png-3bf029664d0f58a1c79abd2d6666ba90.bptc.ctex"]
[params]

View file

@ -1,27 +1,23 @@
[gd_scene load_steps=6 format=3 uid="uid://btlkog4b87p4x"]
[gd_scene load_steps=5 format=3 uid="uid://btlkog4b87p4x"]
[ext_resource type="Terrain3DStorage" uid="uid://wgmg245njt8e" path="res://maps/desert/resources/storage.res" id="1_7nbyj"]
[ext_resource type="Environment" uid="uid://nw62ce5cglvs" path="res://environments/desert.tres" id="1_e1o3u"]
[ext_resource type="Terrain3DMaterial" uid="uid://c3isipd4wqxpk" path="res://maps/desert/resources/material.tres" id="2_psdr0"]
[ext_resource type="Terrain3DTextureList" uid="uid://d1j24k8sq8qpj" path="res://maps/desert/resources/textures.tres" id="3_aowug"]
[ext_resource type="Script" path="res://maps/map.gd" id="4_cl7fm"]
[ext_resource type="Environment" uid="uid://nw62ce5cglvs" path="res://maps/desert/resources/env.tres" id="5_4l4vc"]
[node name="Desert" type="Terrain3D" node_paths=PackedStringArray("_flagstand", "_player_spawns_root")]
[node name="Desert" type="Terrain3D"]
storage = ExtResource("1_7nbyj")
material = ExtResource("2_psdr0")
texture_list = ExtResource("3_aowug")
collision_layer = 2147483648
collision_mask = 2147483648
script = ExtResource("4_cl7fm")
_flagstand = NodePath("FlagStand")
_player_spawns_root = NodePath("PlayerSpawns")
[node name="Sunlight" type="DirectionalLight3D" parent="."]
transform = Transform3D(0.5, 0.55667, -0.663414, 0, 0.766044, 0.642788, 0.866025, -0.321394, 0.383022, -1613.38, 2730.74, 446.64)
shadow_enabled = true
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = ExtResource("1_e1o3u")
environment = ExtResource("5_4l4vc")
[node name="PlayerSpawns" type="Node" parent="."]
@ -33,3 +29,6 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1161.42, 174.535, 909.901)
[node name="FlagStand" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 878.613, 134.55, 916.185)
[node name="Camera3D" type="Camera3D" parent="."]
transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 1024, 920, 1024)

View file

@ -1,23 +1,23 @@
[gd_resource type="Terrain3DTextureList" load_steps=7 format=3 uid="uid://d1j24k8sq8qpj"]
[ext_resource type="Texture2D" uid="uid://cngjywcua4vv8" path="res://maps/desert/textures/ground054_alb_ht.png" id="1_rh7of"]
[ext_resource type="Texture2D" uid="uid://cbk7l6hs0yrcc" path="res://maps/desert/textures/ground054_nrm_rgh.png" id="2_xt1tc"]
[ext_resource type="Texture2D" uid="uid://dwk8islw7ebab" path="res://maps/desert/textures/rock029_alb_ht.png" id="3_elstl"]
[ext_resource type="Texture2D" uid="uid://lgfhdcsb2ryx" path="res://maps/desert/textures/rock029_nrm_rgh.png" id="4_6h5db"]
[ext_resource type="Texture2D" uid="uid://dwk8islw7ebab" path="res://maps/desert/assets/textures/rock029_alb_ht.png" id="1_v6d2c"]
[ext_resource type="Texture2D" uid="uid://lgfhdcsb2ryx" path="res://maps/desert/assets/textures/rock029_nrm_rgh.png" id="2_06nlf"]
[ext_resource type="Texture2D" uid="uid://cngjywcua4vv8" path="res://maps/desert/assets/textures/ground054_alb_ht.png" id="3_ik3f2"]
[ext_resource type="Texture2D" uid="uid://cbk7l6hs0yrcc" path="res://maps/desert/assets/textures/ground054_nrm_rgh.png" id="4_waajq"]
[sub_resource type="Terrain3DTexture" id="Terrain3DTexture_wue72"]
name = "Rock"
albedo_color = Color(0.921569, 0.890196, 0.933333, 1)
albedo_texture = ExtResource("3_elstl")
normal_texture = ExtResource("4_6h5db")
albedo_texture = ExtResource("1_v6d2c")
normal_texture = ExtResource("2_06nlf")
uv_scale = 0.05
[sub_resource type="Terrain3DTexture" id="Terrain3DTexture_dkh73"]
name = "Sand"
texture_id = 1
albedo_color = Color(0.792157, 0.72549, 0.694118, 1)
albedo_texture = ExtResource("1_rh7of")
normal_texture = ExtResource("2_xt1tc")
albedo_texture = ExtResource("3_ik3f2")
normal_texture = ExtResource("4_waajq")
uv_scale = 0.15
[resource]

View file

@ -1,21 +1,24 @@
[gd_scene load_steps=6 format=3 uid="uid://chbno00ugl6te"]
[gd_scene load_steps=5 format=3 uid="uid://chbno00ugl6te"]
[ext_resource type="Environment" uid="uid://d2ahijqqspw5f" path="res://environments/default.tres" id="1_3nr12"]
[ext_resource type="Script" path="res://maps/map.gd" id="1_6ysiv"]
[ext_resource type="Terrain3DStorage" uid="uid://dyon4xda4k40d" path="res://maps/genesis/resources/storage.res" id="1_a88qe"]
[ext_resource type="Terrain3DMaterial" uid="uid://bd4lr5sxu8xu" path="res://maps/genesis/resources/material.res" id="2_o2y3d"]
[ext_resource type="Terrain3DTextureList" uid="uid://dnqa8kxgm3xuw" path="res://maps/genesis/resources/textures.res" id="3_1cww7"]
[ext_resource type="Environment" uid="uid://d2ahijqqspw5f" path="res://maps/genesis/resources/env.tres" id="5_3klr3"]
[node name="Genesis" type="Terrain3D" node_paths=PackedStringArray("_flagstand", "_player_spawns_root")]
[node name="Genesis" type="Terrain3D"]
storage = ExtResource("1_a88qe")
material = ExtResource("2_o2y3d")
texture_list = ExtResource("3_1cww7")
collision_layer = 2147483648
collision_mask = 2147483648
mesh_size = 24
script = ExtResource("1_6ysiv")
_flagstand = NodePath("FlagPillar/CSGCylinder3D/FlagStand")
_player_spawns_root = NodePath("PlayerSpawns")
[node name="Sunlight" type="DirectionalLight3D" parent="."]
transform = Transform3D(-0.866024, -0.433016, 0.25, 0, 0.499998, 0.866027, -0.500003, 0.75, -0.43301, 0, 100, 0)
shadow_enabled = true
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = ExtResource("5_3klr3")
[node name="PlayerSpawns" type="Node" parent="."]
@ -39,12 +42,5 @@ size = Vector3(0.5, 6, 0.5)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.42967, 0)
height = 5.0
[node name="FlagStand" type="Marker3D" parent="FlagPillar/CSGCylinder3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.53822, 0)
[node name="Sunlight" type="DirectionalLight3D" parent="."]
transform = Transform3D(-0.866024, -0.433016, 0.25, 0, 0.499998, 0.866027, -0.500003, 0.75, -0.43301, 0, 100, 0)
shadow_enabled = true
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = ExtResource("1_3nr12")
[node name="FlagStand" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 108.644, 0)

View file

@ -1,15 +0,0 @@
class_name Map extends Terrain3D
@export var _flagstand : Node3D
@export var _player_spawns_root : Node
var _rng : RandomNumberGenerator = RandomNumberGenerator.new()
func get_flagstand() -> Node3D:
return _flagstand
func get_player_spawn() -> Node3D:
var spawn_count : int = _player_spawns_root.get_child_count()
var spawn_index : int = _rng.randi_range(0, spawn_count - 1)
var spawn_selected : Node3D = _player_spawns_root.get_child(spawn_index)
return spawn_selected

View file

@ -25,8 +25,6 @@ class_name Multiplayer extends Node
@onready var map : Node = $Map
@onready var scoreboard : Scoreboard = $Scoreboard
var _map_manager : Map
signal connected_to_server
signal connection_failed
@ -65,19 +63,18 @@ func _on_player_died(player : Player, _killer_id : int) -> void:
respawn_player(player)
func respawn_player(player : Player) -> void:
var spawn_location : Vector3 = _map_manager.get_player_spawn().position
var spawn_location : Vector3 = MapsManager.get_player_spawn().position
player.respawn.rpc(spawn_location)
func add_player(peer_id : int, nickname : String) -> void:
var match_participant_component : MatchParticipantComponent = MatchParticipantComponent.new()
var player : Player = PLAYER.instantiate()
player.died.connect(_on_player_died)
player.name = str(peer_id)
player.died.connect(_on_player_died)
players.add_child(player)
player.global_position = _map_manager.get_player_spawn().position
player.match_participant_component.player_id = peer_id
player.match_participant_component.team_id = ($RabbitScoringComponent as RabbitScoringComponent)._team_chasers.team_id
player.match_participant_component.nickname = nickname
player.global_position = MapsManager.get_player_spawn().position
$DeathmatchScoringComponent.subscribe_player(player)
scoreboard.add_participant(player.match_participant_component)
print("Peer `%s` connected" % player.name)
@ -94,8 +91,8 @@ func remove_player(peer_id : int) -> void:
func _load_map(scene : PackedScene, nickname : String) -> void:
var map_scene : Node = scene.instantiate()
MapsManager.current_map = map_scene
map_scene.ready.connect(_add_flag)
_map_manager = map_scene
map.add_child(map_scene)
if DisplayServer.get_name() != "headless":
add_player(1, nickname)
@ -104,7 +101,9 @@ func _add_flag() -> void:
var flag : Flag = FLAG.instantiate()
$RabbitScoringComponent.setup(flag)
objectives.add_child(flag)
flag.global_position = _map_manager.get_flagstand().global_position
var flagstand : Marker3D = MapsManager.current_map.get_node("FlagStand")
if flagstand:
flag.global_position = flagstand.global_position
@rpc("any_peer", "reliable")
func _join_match(nickname : String) -> void:

View file

@ -1,6 +1,6 @@
[gd_scene load_steps=7 format=3 uid="uid://bvwxfgygm2xb8"]
[ext_resource type="Script" path="res://modes/multiplayer.gd" id="1_r1kd6"]
[ext_resource type="Script" path="res://modes/multiplayer/multiplayer.gd" id="1_r1kd6"]
[ext_resource type="PackedScene" uid="uid://cbhx1xme0sb7k" path="res://entities/player/player.tscn" id="2_og1vb"]
[ext_resource type="PackedScene" uid="uid://c88l3h0ph00c7" path="res://entities/flag/flag.tscn" id="3_h0rie"]
[ext_resource type="Script" path="res://maps/components/rabbit_scoring_component.gd" id="5_7woao"]
@ -15,7 +15,7 @@ FLAG = ExtResource("3_h0rie")
[node name="Map" type="Node" parent="."]
[node name="MapSpawner" type="MultiplayerSpawner" parent="."]
_spawnable_scenes = PackedStringArray("res://maps/genesis/genesis.tscn")
_spawnable_scenes = PackedStringArray("res://maps/genesis/genesis.tscn", "res://maps/desert/desert.tscn")
spawn_path = NodePath("../Map")
spawn_limit = 1

View file

@ -0,0 +1,27 @@
# 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 <https://www.gnu.org/licenses/>.
class_name Singleplayer extends Node
@onready var player_node : Player = $Player
@onready var target_dummy : RigidBody3D = $TargetDummy
@onready var player_respawn_location : Vector3 = player_node.position
func _ready() -> void:
player_node.died.connect(respawn_player)
player_node.match_participant_component.player_id = 1
MapsManager.current_map = $Desert
func respawn_player(player : Player, _killer_id : int) -> void:
player.respawn(player_respawn_location)

View file

@ -1,36 +1,21 @@
[gd_scene load_steps=7 format=3 uid="uid://boviiugcnfyrj"]
[ext_resource type="Script" path="res://modes/singleplayer/demo.gd" id="1_kkjqs"]
[ext_resource type="PackedScene" uid="uid://cbhx1xme0sb7k" path="res://entities/player/player.tscn" id="2_6wbjq"]
[ext_resource type="PackedScene" uid="uid://dpnu1lvfncx6q" path="res://entities/target_dummy/target_dummy.tscn" id="3_fkq5v"]
[ext_resource type="PackedScene" uid="uid://c88l3h0ph00c7" path="res://entities/flag/flag.tscn" id="4_1j2pw"]
[ext_resource type="PackedScene" uid="uid://btlkog4b87p4x" path="res://maps/desert/desert.tscn" id="4_dogmv"]
[sub_resource type="GDScript" id="GDScript_iv0l6"]
script/source = "extends Node
@onready var player_node : Player = $Player
@onready var target_dummy : RigidBody3D = $TargetDummy
@onready var player_respawn_location : Vector3 = player_node.position
func _ready() -> void:
player_node.died.connect(respawn_player)
player_node.match_participant_component.player_id = 1
func respawn_player(player : Player, _killer_id : int) -> void:
player.respawn(player_respawn_location)
"
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_c5jqv"]
resource_local_to_scene = true
bounce = 1.0
absorbent = true
[node name="Demo" type="Node"]
script = SubResource("GDScript_iv0l6")
script = ExtResource("1_kkjqs")
[node name="Player" parent="." instance=ExtResource("2_6wbjq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 589.786, 210.119, 853.632)
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 589.786, 209.119, 853.632)
physics_material_override = SubResource("PhysicsMaterial_c5jqv")
[node name="TargetDummy" parent="." instance=ExtResource("3_fkq5v")]

View file

@ -1,6 +0,0 @@
class_name Team extends Object
var team_id : int
func _init(id : int) -> void:
team_id = id

View file

@ -17,7 +17,8 @@ config/icon="res://icon.svg"
[autoload]
GlobalSettings="*res://systems/settings.gd"
Settings="*res://systems/settings.gd"
MapsManager="*res://systems/maps_manager.gd"
[debug]

59
systems/maps_manager.gd Normal file
View file

@ -0,0 +1,59 @@
# 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 <https://www.gnu.org/licenses/>.
## Manage environment settings and terrain maps within a scene.
extends Node
## The default [Environment] used by the current scene in case the [Terrain3D]
## node does not have a [WorldEnvironment] as one of its children.
var environment := Environment.new()
## Random number generator instance
var _rng := RandomNumberGenerator.new()
## Reference to the current terrain map in the scene
var current_map : Terrain3D = null:
set(new_map):
if current_map != null:
current_map.queue_free()
current_map = new_map
# forward user environment settings to current scene environment
var world : World3D = get_viewport().find_world_3d()
if world.environment:
world.environment.sdfgi_enabled = MapsManager.environment.sdfgi_enabled
world.environment.glow_enabled = MapsManager.environment.glow_enabled
world.environment.ssao_enabled = MapsManager.environment.ssao_enabled
world.environment.ssr_enabled = MapsManager.environment.ssr_enabled
world.environment.ssr_max_steps = MapsManager.environment.ssr_max_steps
world.environment.ssil_enabled = MapsManager.environment.ssil_enabled
world.environment.volumetric_fog_enabled = MapsManager.environment.volumetric_fog_enabled
func get_player_spawn() -> Node3D:
if current_map == null:
push_error("MapsManager.current_map is null")
return null
if not current_map.has_node("PlayerSpawns"):
push_warning("PlayerSpawns node not found in MapsManager.current_map")
return null
var player_spawns : Node = current_map.get_node("PlayerSpawns")
var spawn_count : int = player_spawns.get_child_count()
if spawn_count == 0:
push_error("PlayerSpawns has no children (%s)" % current_map.name)
return null
var spawn_index : int = _rng.randi_range(0, spawn_count - 1)
var random_spawn : Marker3D = player_spawns.get_child(spawn_index)
return random_spawn

View file

@ -1,37 +1,65 @@
class_name Settings extends Node
# 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 <https://www.gnu.org/licenses/>.
extends Node
var _config_file : ConfigFile = ConfigFile.new()
var fov : int = 90
var mouse_sensitivity : float = 0.6
var inverted_y_axis : bool = false
var fullscreen : bool = false
const SETTINGS_FILE_PATH : String = "user://settings.cfg"
var _file : ConfigFile = ConfigFile.new()
const path : String = "user://settings.cfg"
func _ready() -> void:
var error : Error = _config_file.load(SETTINGS_FILE_PATH)
# make sure we load most recent core settings
self.reset()
# merge core settings with user-defined settings
var err : Error = _file.load(self.path)
if err == ERR_FILE_CANT_OPEN:
push_warning("settings not found, using defaults")
# apply state
self.apply()
fov = _config_file.get_value("gameplay", "fov", fov)
mouse_sensitivity = _config_file.get_value("gameplay", "mouse_sensitivity", mouse_sensitivity)
inverted_y_axis = _config_file.get_value("gameplay", "inverted_y_axis", inverted_y_axis)
fullscreen = _config_file.get_value("graphics", "fullscreen", fullscreen)
_update_screen()
if error != OK:
print("Settings not found, using defaults")
save_to_file()
func get_value(section: String, key: String, default: Variant = null) -> Variant:
return _file.get_value(section, key, default)
func save_to_file() -> void:
_config_file.set_value("gameplay", "fov", fov)
_config_file.set_value("gameplay", "mouse_sensitivity", mouse_sensitivity)
_config_file.set_value("gameplay", "inverted_y_axis", inverted_y_axis)
_config_file.set_value("graphics", "fullscreen", fullscreen)
_update_screen()
_config_file.save(SETTINGS_FILE_PATH)
func set_value(section: String, key: String, value: Variant) -> void:
return _file.set_value(section, key, value)
func _update_screen() -> void:
if fullscreen:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN)
else:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_WINDOWED)
func reset() -> void:
_file.clear()
# video settings
_file.set_value("ui", "scale", 2)
_file.set_value("video", "quality", 1.125)
_file.set_value("video", "filter", 0)
_file.set_value("video", "fsr_sharpness", 0)
_file.set_value("video", "window_mode", 2)
_file.set_value("video", "vsync", 0)
_file.set_value("video", "taa", 0)
_file.set_value("video", "msaa", 0)
_file.set_value("video", "fxaa", 0)
_file.set_value("video", "fov", 90)
# controls settings
_file.set_value("controls", "mouse_sensitivity", .6)
_file.set_value("controls", "inverted_y_axis", false)
# quality settings
_file.set_value("quality", "shadow_size", 3)
_file.set_value("quality", "shadow_filter", 2)
_file.set_value("quality", "mesh_lod", 2)
# environment settings
_file.set_value("environment", "sdfgi", 0)
_file.set_value("environment", "glow", 0)
_file.set_value("environment", "ssao", 0)
_file.set_value("environment", "ssr", 0)
_file.set_value("environment", "ssil", 0)
_file.set_value("environment", "volumetric_fog", 0)
func apply() -> void:
_file.save(self.path)

20
systems/teams.gd Normal file
View file

@ -0,0 +1,20 @@
# 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 <https://www.gnu.org/licenses/>.
class_name Team extends Object
var team_id : int
func _init(id : int) -> void:
team_id = id