commit fadea22b9d0043a29c29cd43ea1b67bb4c92ffaa Author: Patrick_Pluto Date: Fri Jul 18 19:32:37 2025 +0100 0.0.1 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f28239b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +charset = utf-8 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..8ad74f7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0af181c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# Godot 4+ specific ignores +.godot/ +/android/ diff --git a/entities/coffin.gd b/entities/coffin.gd new file mode 100644 index 0000000..78e1a6d --- /dev/null +++ b/entities/coffin.gd @@ -0,0 +1,22 @@ +class_name Coffin +extends StaticBody3D + +var caught_player: Player = null + +func _on_dropoff(body: Node3D) -> void: + if multiplayer.is_server() and body is Player: + var player: Player = body + if player.caught_player and !caught_player: + caught_player = player.caught_player + player.caught_player.get_imprisoned.rpc_id(player.caught_player.get_multiplayer_authority(), get_path()) + player.released_player.rpc_id(player.get_multiplayer_authority()) + (player.get_node("ReleaseTimer") as Timer).stop() + ($DamageTimer as Timer).start() + elif !player.hunter and player.visible and caught_player and caught_player.health > 0: + caught_player.go_free.rpc_id(caught_player.get_multiplayer_authority()) + caught_player = null + ($DamageTimer as Timer).stop() + +func _on_damage_timer_timeout() -> void: + if multiplayer.is_server() and caught_player.health > 0: + caught_player.damage_player.rpc_id(caught_player.get_multiplayer_authority()) diff --git a/entities/coffin.gd.uid b/entities/coffin.gd.uid new file mode 100644 index 0000000..5dfe13b --- /dev/null +++ b/entities/coffin.gd.uid @@ -0,0 +1 @@ +uid://oaxiyitfsq2q diff --git a/entities/coffin.tscn b/entities/coffin.tscn new file mode 100644 index 0000000..0ea9160 --- /dev/null +++ b/entities/coffin.tscn @@ -0,0 +1,32 @@ +[gd_scene load_steps=4 format=3 uid="uid://dx0yaqaccakh"] + +[ext_resource type="Script" uid="uid://oaxiyitfsq2q" path="res://entities/coffin.gd" id="1_0x4dk"] + +[sub_resource type="BoxShape3D" id="BoxShape3D_0x4dk"] +size = Vector3(3, 1.2, 1.4) + +[sub_resource type="BoxShape3D" id="BoxShape3D_cvqjw"] +size = Vector3(4, 1.4, 2.4) + +[node name="Coffin" type="StaticBody3D"] +script = ExtResource("1_0x4dk") + +[node name="Mesh" type="CSGBox3D" parent="."] +size = Vector3(3, 1.2, 1.4) + +[node name="Collision" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape3D_0x4dk") + +[node name="DropoffZone" type="Area3D" parent="."] + +[node name="Collision" type="CollisionShape3D" parent="DropoffZone"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) +shape = SubResource("BoxShape3D_cvqjw") + +[node name="DamageTimer" type="Timer" parent="."] + +[node name="RespawnPoint" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0.75, 0) + +[connection signal="body_entered" from="DropoffZone" to="." method="_on_dropoff"] +[connection signal="timeout" from="DamageTimer" to="." method="_on_damage_timer_timeout"] diff --git a/entities/player.gd b/entities/player.gd new file mode 100644 index 0000000..777e02d --- /dev/null +++ b/entities/player.gd @@ -0,0 +1,147 @@ +class_name Player +extends CharacterBody3D + +const SPEED: float = 5.0 +const JUMP_VELOCITY: float = 4.5 + +@onready var camera_x: Node3D = $ViewY/ViewX +@onready var camera: Camera3D = $ViewY/ViewX/View +@onready var syringe: Node3D = $Syringe +@onready var needle: Area3D = $Syringe/SyringeNeedle +@onready var bag: Node3D = $Bag +@onready var captured: Node3D = $Bag/Captured + +var hunter: bool = true +var caught_player: Player = null +var new_spawn: Vector3 + +@export var health: int = 100 + +func _ready() -> void: + if is_multiplayer_authority(): + camera.current = true + ($HUD as Control).visible = true + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + if hunter: + syringe.visible = true + bag.visible = true + else: + needle.monitoring = false + +func _physics_process(delta: float) -> void: + # Zoom + if Input.is_action_just_released("zoom_in") and camera.position.z > 0: + camera.position.z += -1 + elif Input.is_action_just_released("zoom_out"): + camera.position.z += 1 + + if is_multiplayer_authority(): + # Focus + if Input.is_action_just_pressed("unfocus"): + Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) + elif Input.is_action_just_pressed("focus"): + Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) + pass + + if visible: + # Gravity + if not is_on_floor(): + velocity += get_gravity() * delta + + # Jumping + if Input.is_action_just_pressed("jump") and is_on_floor(): + velocity.y = JUMP_VELOCITY + + # Movement + var input_dir: Vector2 = Input.get_vector("move_left", "move_right", "move_forwards", "move_backwards") + var direction: Vector3 = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() + + velocity.x = direction.x * SPEED + velocity.z = direction.z * SPEED + + # Hunter specific + if hunter: + if Input.is_action_pressed("stab"): + syringe.position.z -= 0.1 + else: + syringe.position.z += 0.1 + syringe.position.z = clampf(syringe.position.z, -0.8, -0.3) + + if move_and_slide(): + pass + +func _unhandled_input(event: InputEvent) -> void: + # Camera Movement + if event is InputEventMouseMotion: + var mouse_event: InputEventMouseMotion = event + if is_multiplayer_authority(): + rotate_y(deg_to_rad(-mouse_event.relative.x)) + else: + ($ViewY as Node3D).rotate_y(deg_to_rad(-mouse_event.relative.x)) + camera_x.rotate_x(deg_to_rad(-mouse_event.relative.y)) + camera_x.rotation.x = clampf(camera_x.rotation.x, -1.6, 1.6) + + # Gets called when the Player gets stabbed by the syringe. +func _on_stab(body: Node3D) -> void: + if multiplayer.is_server() and body is Player and body.visible == true: + var player: Player = body + caught_player = player + player.get_caught.rpc_id(player.get_multiplayer_authority(), camera.get_path()) + capture_player.rpc_id(get_multiplayer_authority(), player.get_path()) + ($ReleaseTimer as Timer).start() + +# Player gets released through the timer +func _on_release() -> void: + if multiplayer.is_server(): + caught_player.go_free.rpc_id(caught_player.get_multiplayer_authority()) + released_player.rpc_id(get_multiplayer_authority()) + +# This is called on any player that was just stabbed/caught. +@rpc("any_peer", "call_local", "reliable") +func get_caught(spectator_camera_path: NodePath) -> void: + if multiplayer.get_remote_sender_id() == 1: + var spectator_camera: Camera3D = get_node(spectator_camera_path) + visible = false + ($Collision as CollisionShape3D).disabled = true + spectator_camera.current = true + new_spawn = position + +# This is called on any player when they go free. +@rpc("any_peer", "call_local", "reliable") +func go_free() -> void: + if multiplayer.get_remote_sender_id() == 1: + camera.current = true + visible = true + ($Collision as CollisionShape3D).disabled = false + position = new_spawn + +# This is called on any player when they go free. +@rpc("any_peer", "call_local", "reliable") +func get_imprisoned(coffin_path: NodePath) -> void: + if multiplayer.get_remote_sender_id() == 1: + var coffin: Coffin = get_node(coffin_path) + camera.current = true + position = coffin.position + new_spawn = (coffin.get_node("RespawnPoint") as Node3D).position + +# This is called on any player that has just stabbed/caught another. +@rpc("any_peer", "call_local", "reliable") +func capture_player(player_path: NodePath) -> void: + if multiplayer.get_remote_sender_id() == 1: + var player: Player = get_node(player_path) + caught_player = player + captured.visible = true + +# This is called on any player that was just stabbed/caught. +@rpc("any_peer", "call_local", "reliable") +func released_player() -> void: + if multiplayer.get_remote_sender_id() == 1: + caught_player = null + captured.visible = false + +# Damages the player +@rpc("any_peer", "call_local", "reliable") +func damage_player() -> void: + if multiplayer.get_remote_sender_id() == 1: + health -= 2 + ($HUD/Health as Label).text = "Health: " + str(health) diff --git a/entities/player.gd.uid b/entities/player.gd.uid new file mode 100644 index 0000000..a7498f8 --- /dev/null +++ b/entities/player.gd.uid @@ -0,0 +1 @@ +uid://dtlssj0xohnpc diff --git a/entities/player.tscn b/entities/player.tscn new file mode 100644 index 0000000..d8976b7 --- /dev/null +++ b/entities/player.tscn @@ -0,0 +1,99 @@ +[gd_scene load_steps=6 format=3 uid="uid://4hmftsrl305n"] + +[ext_resource type="Script" uid="uid://dtlssj0xohnpc" path="res://entities/player.gd" id="1_merdl"] + +[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_u3f3p"] +radius = 0.4 +height = 1.8 + +[sub_resource type="CapsuleMesh" id="CapsuleMesh_merdl"] +radius = 0.4 +height = 1.8 + +[sub_resource type="CylinderShape3D" id="CylinderShape3D_merdl"] +height = 0.2 +radius = 0.05 + +[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_merdl"] +properties/0/path = NodePath(".:position") +properties/0/spawn = true +properties/0/replication_mode = 1 +properties/1/path = NodePath(".:rotation") +properties/1/spawn = true +properties/1/replication_mode = 1 +properties/2/path = NodePath("Syringe:position") +properties/2/spawn = true +properties/2/replication_mode = 1 +properties/3/path = NodePath(".:visible") +properties/3/spawn = true +properties/3/replication_mode = 1 +properties/4/path = NodePath(".:health") +properties/4/spawn = true +properties/4/replication_mode = 1 + +[node name="Player" type="CharacterBody3D"] +script = ExtResource("1_merdl") + +[node name="Collision" type="CollisionShape3D" parent="."] +shape = SubResource("CapsuleShape3D_u3f3p") + +[node name="Mesh" type="MeshInstance3D" parent="."] +mesh = SubResource("CapsuleMesh_merdl") + +[node name="Syringe" type="CSGCylinder3D" parent="."] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0.4, 0, -0.3) +visible = false +radius = 0.05 +height = 1.0 + +[node name="SyringeNeedle" type="Area3D" parent="Syringe"] + +[node name="Collision" type="CollisionShape3D" parent="Syringe/SyringeNeedle"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.4, 0) +shape = SubResource("CylinderShape3D_merdl") + +[node name="Bag" type="CSGCylinder3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.8) +visible = false +radius = 0.4 +height = 1.0 + +[node name="Captured" type="CSGSphere3D" parent="Bag"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.5, 0) +visible = false +radius = 0.3 + +[node name="ViewY" type="Node3D" parent="."] + +[node name="ViewX" type="Node3D" parent="ViewY"] +transform = Transform3D(1, 0, 0, 0, 0.866025, 0.5, 0, -0.5, 0.866025, 0, 0.5, 0) + +[node name="View" type="Camera3D" parent="ViewY/ViewX"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 4) +size = 5.0 + +[node name="MultiplayerSynchronizer" type="MultiplayerSynchronizer" parent="."] +replication_config = SubResource("SceneReplicationConfig_merdl") + +[node name="ReleaseTimer" type="Timer" parent="."] +wait_time = 30.0 +one_shot = true + +[node name="HUD" type="Control" parent="."] +visible = false +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 1 + +[node name="Health" type="Label" parent="HUD"] +layout_mode = 1 +offset_right = 88.0 +offset_bottom = 23.0 +text = "Health: 100" + +[connection signal="body_entered" from="Syringe/SyringeNeedle" to="." method="_on_stab"] +[connection signal="timeout" from="ReleaseTimer" to="." method="_on_release"] diff --git a/entities/player_spawner.gd b/entities/player_spawner.gd new file mode 100644 index 0000000..c4c24d8 --- /dev/null +++ b/entities/player_spawner.gd @@ -0,0 +1,21 @@ +class_name PlayerSpawner +extends Node3D + +const PLAYER_SCENE: PackedScene = preload("res://entities/player.tscn") + +func _spawn_player(player: Dictionary) -> CharacterBody3D: + var player_instance: Player = PLAYER_SCENE.instantiate() + var id: int = player.id + player_instance.position = position + player_instance.hunter = player.hunter + player_instance.set_multiplayer_authority(id) + return player_instance + +func _ready() -> void: + if $MultiplayerSpawner is MultiplayerSpawner: + ($MultiplayerSpawner as MultiplayerSpawner).spawn_function = _spawn_player + +func spawn_player(player: Dictionary) -> void: + if $MultiplayerSpawner is MultiplayerSpawner: + if ($MultiplayerSpawner as MultiplayerSpawner).spawn(player) == null: + print("Failed to spawn player.") diff --git a/entities/player_spawner.gd.uid b/entities/player_spawner.gd.uid new file mode 100644 index 0000000..35ea03f --- /dev/null +++ b/entities/player_spawner.gd.uid @@ -0,0 +1 @@ +uid://rhk1kmfu2hjo diff --git a/entities/player_spawner.tscn b/entities/player_spawner.tscn new file mode 100644 index 0000000..83bdf69 --- /dev/null +++ b/entities/player_spawner.tscn @@ -0,0 +1,9 @@ +[gd_scene load_steps=2 format=3 uid="uid://cu1d6uwha7jm2"] + +[ext_resource type="Script" uid="uid://rhk1kmfu2hjo" path="res://entities/player_spawner.gd" id="1_q56n2"] + +[node name="PlayerSpawner" type="Node3D"] +script = ExtResource("1_q56n2") + +[node name="MultiplayerSpawner" type="MultiplayerSpawner" parent="."] +spawn_path = NodePath("../..") diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..9fcb100 --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,41 @@ +[preset.0] + +name="Linux" +platform="Linux" +runnable=true +advanced_options=false +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="../../FreeFTF.x86_64" +patches=PackedStringArray() +encryption_include_filters="" +encryption_exclude_filters="" +seed=0 +encrypt_pck=false +encrypt_directory=false +script_export_mode=2 + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=true +texture_format/s3tc_bptc=true +texture_format/etc2_astc=false +binary_format/architecture="x86_64" +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="#!/usr/bin/env bash +export DISPLAY=:0 +unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\" +\"{temp_dir}/{exe_name}\" {cmd_args}" +ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash +kill $(pgrep -x -f \"{temp_dir}/{exe_name} {cmd_args}\") +rm -rf \"{temp_dir}\"" diff --git a/global/multiplayer.gd b/global/multiplayer.gd new file mode 100644 index 0000000..496d9f1 --- /dev/null +++ b/global/multiplayer.gd @@ -0,0 +1,81 @@ +class_name MultiplayerClass +extends Node + +const ADDRESS: String = "127.0.0.1" +const PORT: int = 4516 + +var peer: ENetMultiplayerPeer = null +var players: Array = [] + +## Host Specific + +# Hosts server +func host_server() -> void: + peer = ENetMultiplayerPeer.new() + if peer.create_server(PORT) != OK: + peer = null + return + multiplayer.multiplayer_peer = peer + if multiplayer.peer_connected.connect(_on_player_joined) != OK: + print("Failed to connect signal") + if multiplayer.peer_disconnected.connect(_on_player_left) != OK: + print("Failed to connect signal") + _on_player_joined(multiplayer.get_unique_id()) + +# Runs when player joins +func _on_player_joined(id: int) -> void: + players.push_back({ + "id": id, + "loaded": false, + "hunter": false, + }) + +# Runs when player leaves +func _on_player_left(id: int) -> void: + players = players.filter(func (player: Dictionary) -> bool: return player.id != id) + +# Switches the scene, and waits until everyone is fully loaded. +@rpc("authority", "call_local", "reliable") +func switch_scene(path: String) -> void: + if multiplayer.is_server(): + _scene_loaded.rpc_id(1) + while true: + var loaded: bool = true + for player: Dictionary in players: + if player.loaded == false: + loaded = false + break + if loaded: + break + await get_tree().create_timer(0.1).timeout + if get_tree().change_scene_to_file(path) != OK: + print("Failed to change to scene.") + else: + if get_tree().change_scene_to_file(path) != OK: + print("Failed to change to scene.") + _scene_loaded.rpc_id(1) + +# Callback to switch_scene from the remote peer +@rpc("any_peer", "call_local", "reliable") +func _scene_loaded() -> void: + var id: int = multiplayer.get_remote_sender_id() + if multiplayer.is_server(): + for i: int in range(players.size()): + if players[i].id == multiplayer.get_remote_sender_id(): + players[i].loaded = true + +## Client Specific + +# Joins a server +func join_server() -> void: + peer = ENetMultiplayerPeer.new() + if peer.create_client(ADDRESS, PORT) != OK: + peer = null + return + multiplayer.multiplayer_peer = peer + +## Shared + +# Terminates all Multiplayer functionality. +func terminate_multiplayer() -> void: + multiplayer.multiplayer_peer = null diff --git a/global/multiplayer.gd.uid b/global/multiplayer.gd.uid new file mode 100644 index 0000000..6e53327 --- /dev/null +++ b/global/multiplayer.gd.uid @@ -0,0 +1 @@ +uid://dabrayl0y4v2g diff --git a/maps/map.gd b/maps/map.gd new file mode 100644 index 0000000..1e421cd --- /dev/null +++ b/maps/map.gd @@ -0,0 +1,12 @@ +class_name Map +extends Node3D + +func _ready() -> void: + if multiplayer.is_server(): + randomize() + Multiplayer.players[randi_range(0, Multiplayer.players.size() - 1)].hunter = true + for i: int in $PlayerSpawners.get_children().size(): + if i < Multiplayer.players.size(): + var spawner: PlayerSpawner = $PlayerSpawners.get_child(i) + var player: Dictionary = Multiplayer.players[i] + spawner.spawn_player(player) diff --git a/maps/map.gd.uid b/maps/map.gd.uid new file mode 100644 index 0000000..9ca8534 --- /dev/null +++ b/maps/map.gd.uid @@ -0,0 +1 @@ +uid://btt55t6akawwc diff --git a/maps/test_map.tscn b/maps/test_map.tscn new file mode 100644 index 0000000..16eef78 --- /dev/null +++ b/maps/test_map.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=4 format=3 uid="uid://dn53itmhhlru8"] + +[ext_resource type="Script" uid="uid://btt55t6akawwc" path="res://maps/map.gd" id="1_6slyc"] +[ext_resource type="PackedScene" uid="uid://cu1d6uwha7jm2" path="res://entities/player_spawner.tscn" id="2_b71ab"] +[ext_resource type="PackedScene" uid="uid://dx0yaqaccakh" path="res://entities/coffin.tscn" id="3_pwco0"] + +[node name="TestMap" type="Node3D"] +script = ExtResource("1_6slyc") + +[node name="PlayerSpawners" type="Node3D" parent="."] + +[node name="0" parent="PlayerSpawners" instance=ExtResource("2_b71ab")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 3, 0) + +[node name="1" parent="PlayerSpawners" instance=ExtResource("2_b71ab")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -10, 3, 0) + +[node name="2" parent="PlayerSpawners" instance=ExtResource("2_b71ab")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, 10) + +[node name="3" parent="PlayerSpawners" instance=ExtResource("2_b71ab")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3, -10) + +[node name="Map" type="CSGBox3D" parent="."] +use_collision = true +size = Vector3(25, 1, 25) + +[node name="Sky" type="DirectionalLight3D" parent="."] +transform = Transform3D(0.866025, 0.433012, -0.25, 0, 0.5, 0.866025, 0.5, -0.75, 0.433013, 0, 0, 0) +shadow_enabled = true + +[node name="Coffin" parent="." instance=ExtResource("3_pwco0")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.1, 0) diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..795616b --- /dev/null +++ b/project.godot @@ -0,0 +1,131 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="FreeFTF" +run/main_scene="uid://dbap0wfqfu12h" +config/features=PackedStringArray("4.4", "Forward Plus") +boot_splash/bg_color=Color(0, 0, 0, 1) +boot_splash/show_image=false + +[autoload] + +Multiplayer="*res://global/multiplayer.gd" + +[debug] + +gdscript/warnings/unassigned_variable=2 +gdscript/warnings/unassigned_variable_op_assign=2 +gdscript/warnings/unused_variable=2 +gdscript/warnings/unused_local_constant=2 +gdscript/warnings/unused_private_class_variable=2 +gdscript/warnings/unused_parameter=2 +gdscript/warnings/unused_signal=2 +gdscript/warnings/shadowed_variable=2 +gdscript/warnings/shadowed_variable_base_class=2 +gdscript/warnings/shadowed_global_identifier=2 +gdscript/warnings/unreachable_code=2 +gdscript/warnings/unreachable_pattern=2 +gdscript/warnings/standalone_expression=2 +gdscript/warnings/standalone_ternary=2 +gdscript/warnings/incompatible_ternary=2 +gdscript/warnings/untyped_declaration=2 +gdscript/warnings/inferred_declaration=2 +gdscript/warnings/unsafe_property_access=2 +gdscript/warnings/unsafe_method_access=2 +gdscript/warnings/unsafe_cast=2 +gdscript/warnings/unsafe_call_argument=2 +gdscript/warnings/unsafe_void_return=2 +gdscript/warnings/return_value_discarded=2 +gdscript/warnings/static_called_on_instance=2 +gdscript/warnings/missing_tool=2 +gdscript/warnings/redundant_static_unload=2 +gdscript/warnings/redundant_await=2 +gdscript/warnings/assert_always_true=2 +gdscript/warnings/assert_always_false=2 +gdscript/warnings/integer_division=2 +gdscript/warnings/narrowing_conversion=2 +gdscript/warnings/int_as_enum_without_cast=2 +gdscript/warnings/int_as_enum_without_match=2 +gdscript/warnings/enum_variable_without_default=2 +gdscript/warnings/empty_file=2 +gdscript/warnings/deprecated_keyword=2 +gdscript/warnings/confusable_identifier=2 +gdscript/warnings/confusable_local_declaration=2 +gdscript/warnings/confusable_local_usage=2 +gdscript/warnings/confusable_capture_reassignment=2 +gdscript/warnings/property_used_as_function=2 +gdscript/warnings/constant_used_as_function=2 +gdscript/warnings/function_used_as_property=2 + +[display] + +window/size/viewport_width=640 +window/size/viewport_height=480 +window/stretch/mode="canvas_items" +window/stretch/aspect="expand" + +[input] + +move_left={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null) +] +} +move_right={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null) +] +} +move_forwards={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null) +] +} +move_backwards={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) +] +} +jump={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"location":0,"echo":false,"script":null) +] +} +zoom_in={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":4,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} +zoom_out={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":5,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} +stab={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} +unfocus={ +"deadzone": 0.2, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194305,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null) +] +} +focus={ +"deadzone": 0.2, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null) +] +} + +[rendering] + +environment/defaults/default_clear_color=Color(0, 0, 0, 1) diff --git a/ui/host_game.gd b/ui/host_game.gd new file mode 100644 index 0000000..a99b1a2 --- /dev/null +++ b/ui/host_game.gd @@ -0,0 +1,5 @@ +class_name HostGame +extends Control + +func _on_start_game_button_pressed() -> void: + Multiplayer.switch_scene.rpc("res://maps/test_map.tscn") diff --git a/ui/host_game.gd.uid b/ui/host_game.gd.uid new file mode 100644 index 0000000..f4a2bc2 --- /dev/null +++ b/ui/host_game.gd.uid @@ -0,0 +1 @@ +uid://cuumy3t2hkgcu diff --git a/ui/host_game.tscn b/ui/host_game.tscn new file mode 100644 index 0000000..7ff71c8 --- /dev/null +++ b/ui/host_game.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=2 format=3 uid="uid://corjvfihg047u"] + +[ext_resource type="Script" uid="uid://cuumy3t2hkgcu" path="res://ui/host_game.gd" id="1_fg6en"] + +[node name="HostGame" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_fg6en") + +[node name="StartGameButton" type="Button" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -48.0 +offset_top = -15.5 +offset_right = 48.0 +offset_bottom = 15.5 +grow_horizontal = 2 +grow_vertical = 2 +text = "Start Game" + +[connection signal="pressed" from="StartGameButton" to="." method="_on_start_game_button_pressed"] diff --git a/ui/join_game.tscn b/ui/join_game.tscn new file mode 100644 index 0000000..1dc3483 --- /dev/null +++ b/ui/join_game.tscn @@ -0,0 +1,9 @@ +[gd_scene format=3 uid="uid://dpxam8lwgsd6q"] + +[node name="JoinGame" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/ui/main_menu.gd b/ui/main_menu.gd new file mode 100644 index 0000000..d117fd0 --- /dev/null +++ b/ui/main_menu.gd @@ -0,0 +1,12 @@ +class_name MainMenu +extends Control + +func _on_host_game_button_pressed() -> void: + Multiplayer.host_server() + if get_tree().change_scene_to_file("res://ui/host_game.tscn") != OK: + print("Failed to change to scene.") + +func _on_join_game_button_pressed() -> void: + Multiplayer.join_server() + if get_tree().change_scene_to_file("res://ui/join_game.tscn") != OK: + print("Failed to change to scene.") diff --git a/ui/main_menu.gd.uid b/ui/main_menu.gd.uid new file mode 100644 index 0000000..cc73f24 --- /dev/null +++ b/ui/main_menu.gd.uid @@ -0,0 +1 @@ +uid://d1s1dnvvro0ij diff --git a/ui/main_menu.tscn b/ui/main_menu.tscn new file mode 100644 index 0000000..941939f --- /dev/null +++ b/ui/main_menu.tscn @@ -0,0 +1,42 @@ +[gd_scene load_steps=2 format=3 uid="uid://dbap0wfqfu12h"] + +[ext_resource type="Script" uid="uid://d1s1dnvvro0ij" path="res://ui/main_menu.gd" id="1_t7e0r"] + +[node name="MainMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_t7e0r") + +[node name="MainContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -47.0 +offset_top = -33.0 +offset_right = 47.0 +offset_bottom = 33.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Label" type="Label" parent="MainContainer"] +layout_mode = 2 +text = "FreeFTF" +horizontal_alignment = 1 + +[node name="HostGameButton" type="Button" parent="MainContainer"] +layout_mode = 2 +text = "Host Game" + +[node name="JoinGameButton" type="Button" parent="MainContainer"] +layout_mode = 2 +text = "Join Game" + +[connection signal="pressed" from="MainContainer/HostGameButton" to="." method="_on_host_game_button_pressed"] +[connection signal="pressed" from="MainContainer/JoinGameButton" to="." method="_on_join_game_button_pressed"]