diff --git a/scenes/entities/npc.tscn b/scenes/entities/npc.tscn index 7257ba7..97f8fb3 100644 --- a/scenes/entities/npc.tscn +++ b/scenes/entities/npc.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=5 format=3 uid="uid://cvnjpnvchvakj"] +[gd_scene load_steps=6 format=3 uid="uid://cvnjpnvchvakj"] [ext_resource type="Script" path="res://scripts/entities/npc.gd" id="1_jvyx6"] @@ -10,6 +10,9 @@ material = SubResource("StandardMaterial3D_e5nrh") [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_am313"] +[sub_resource type="BoxShape3D" id="BoxShape3D_wyrst"] +size = Vector3(3, 2, 3) + [node name="Npc" type="CharacterBody3D"] script = ExtResource("1_jvyx6") @@ -30,3 +33,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.25, 0) pixel_size = 0.01 billboard = 1 no_depth_test = true + +[node name="Area3D" type="Area3D" parent="."] + +[node name="CollisionShape3D" type="CollisionShape3D" parent="Area3D"] +shape = SubResource("BoxShape3D_wyrst") diff --git a/scenes/maps/testmap.tscn b/scenes/maps/testmap.tscn index 822930b..7b61e8e 100644 --- a/scenes/maps/testmap.tscn +++ b/scenes/maps/testmap.tscn @@ -1,10 +1,11 @@ -[gd_scene load_steps=10 format=3 uid="uid://cbyee7drds7qu"] +[gd_scene load_steps=11 format=3 uid="uid://cbyee7drds7qu"] [ext_resource type="Script" path="res://scripts/maps/map.gd" id="1_4npcs"] [ext_resource type="Script" path="res://scripts/maps/objectives/hungry.gd" id="2_qrp84"] [ext_resource type="PackedScene" uid="uid://bsghm187n6ykx" path="res://scenes/objects/closet.tscn" id="2_yvpvm"] [ext_resource type="PackedScene" uid="uid://cvnjpnvchvakj" path="res://scenes/entities/npc.tscn" id="3_x3gyc"] [ext_resource type="PackedScene" uid="uid://ctpubhh2gsccb" path="res://scenes/maps/elements/guncase.tscn" id="5_k7k8h"] +[ext_resource type="PackedScene" uid="uid://bghvogpaly2a6" path="res://scenes/objects/food/burger.tscn" id="6_rpxne"] [sub_resource type="Environment" id="Environment_pq0iv"] @@ -50,6 +51,9 @@ script = ExtResource("2_qrp84") [node name="Closet" parent="NPCCarryables" instance=ExtResource("2_yvpvm")] transform = Transform3D(0.642788, -0.766044, 0, 0.766044, 0.642788, 0, 0, 0, 1, 29, 10, -30) +[node name="NPCExit" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 44) + [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(-0.899519, 0.375, 0.224144, -0.224144, -0.836516, 0.5, 0.375, 0.399519, 0.836516, 0, 0, 0) @@ -75,3 +79,6 @@ shape = SubResource("BoxShape3D_rnmx0") [node name="Guncase" parent="." instance=ExtResource("5_k7k8h")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 24, 1, 0) + +[node name="Burger" parent="." instance=ExtResource("6_rpxne")] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5.99429, 3.5, 15.1689) diff --git a/scenes/objects/food/burger.tscn b/scenes/objects/food/burger.tscn new file mode 100644 index 0000000..51af013 --- /dev/null +++ b/scenes/objects/food/burger.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=7 format=3 uid="uid://bghvogpaly2a6"] + +[ext_resource type="Script" path="res://scripts/player_interactables/food/burger.gd" id="1_nd3af"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ntjpg"] +albedo_color = Color(0.765272, 0.371996, 0, 1) + +[sub_resource type="BoxMesh" id="BoxMesh_366d1"] +material = SubResource("StandardMaterial3D_ntjpg") +size = Vector3(0.2, 0.05, 0.2) + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_6edt3"] +albedo_color = Color(0.432741, 0.166278, 0, 1) + +[sub_resource type="BoxMesh" id="BoxMesh_7qoyo"] +material = SubResource("StandardMaterial3D_6edt3") +size = Vector3(0.2, 0.05, 0.2) + +[sub_resource type="BoxShape3D" id="BoxShape3D_cksw3"] +size = Vector3(0.2, 0.15, 0.2) + +[node name="Burger" type="RigidBody3D"] +mass = 0.5 +script = ExtResource("1_nd3af") + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.05, 0) +mesh = SubResource("BoxMesh_366d1") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_7qoyo") +skeleton = NodePath("../MeshInstance3D") + +[node name="MeshInstance3D3" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.05, 0) +mesh = SubResource("BoxMesh_366d1") +skeleton = NodePath("../MeshInstance3D2") + +[node name="CollisionShape3D" type="CollisionShape3D" parent="."] +shape = SubResource("BoxShape3D_cksw3") diff --git a/scenes/ui/main_menu.tscn b/scenes/ui/main_menu.tscn new file mode 100644 index 0000000..127229b --- /dev/null +++ b/scenes/ui/main_menu.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=2 format=3 uid="uid://dca627msg6a0i"] + +[ext_resource type="Script" path="res://scripts/ui/main_menu.gd" id="1_ffbt7"] + +[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_ffbt7") + +[node name="VBoxContainer" 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 = -20.0 +offset_top = -20.0 +offset_right = 20.0 +offset_bottom = 20.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Title" type="Label" parent="VBoxContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 48 +text = "Hotel Madness" + +[node name="Join" type="Button" parent="VBoxContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +text = "Create/Join Room" + +[node name="Settings" type="Button" parent="VBoxContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +text = "Settings" diff --git a/scenes/ui/settings.tscn b/scenes/ui/settings.tscn new file mode 100644 index 0000000..b03a416 --- /dev/null +++ b/scenes/ui/settings.tscn @@ -0,0 +1,68 @@ +[gd_scene load_steps=2 format=3 uid="uid://tax7d1r2lvay"] + +[ext_resource type="Script" path="res://scripts/ui/settings.gd" id="1_nw44a"] + +[node name="Settings" 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_nw44a") + +[node name="VBoxContainer" 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 = -115.0 +offset_top = -50.5 +offset_right = 115.0 +offset_bottom = 50.5 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Title" type="Label" parent="VBoxContainer"] +layout_mode = 2 +theme_override_font_sizes/font_size = 32 +text = "Settings:" + +[node name="DefaultServerIP" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/DefaultServerIP"] +layout_mode = 2 +text = "Default Server IP: " + +[node name="LineEdit" type="LineEdit" parent="VBoxContainer/DefaultServerIP"] +custom_minimum_size = Vector2(300, 0) +layout_mode = 2 + +[node name="DefaultUsername" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/DefaultUsername"] +layout_mode = 2 +text = "Default Username: " + +[node name="LineEdit" type="LineEdit" parent="VBoxContainer/DefaultUsername"] +custom_minimum_size = Vector2(300, 0) +layout_mode = 2 + +[node name="DefaultRoomname" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/DefaultRoomname"] +layout_mode = 2 +text = "Default Roomname: " + +[node name="LineEdit" type="LineEdit" parent="VBoxContainer/DefaultRoomname"] +custom_minimum_size = Vector2(300, 0) +layout_mode = 2 + +[node name="Return" type="Button" parent="VBoxContainer"] +layout_mode = 2 +text = "Save and Return" diff --git a/scripts/entities/bullet.gd b/scripts/entities/bullet.gd index b0f2218..898259a 100644 --- a/scripts/entities/bullet.gd +++ b/scripts/entities/bullet.gd @@ -1,7 +1,10 @@ +## SPDX-License-Identifier: GPL-3.0-or-later +## Copyright (c) 2024 interstellardevelopment.org + class_name Bullet extends CharacterBody3D -const SPEED: int = 20 +const SPEED: int = 40 func _ready() -> void: if ($Timer as Timer).timeout.connect(_on_timeout): diff --git a/scripts/entities/npc.gd b/scripts/entities/npc.gd index 3c6e051..29b05f5 100644 --- a/scripts/entities/npc.gd +++ b/scripts/entities/npc.gd @@ -15,6 +15,7 @@ var carrying: bool = false # 1 - wait # 2 - get carryable object # 3 - chase a player +# 4 - leave the building var phase: int = 0 @onready var timer: Timer = $Timer @@ -24,23 +25,29 @@ var skip: bool = false @onready var navigation_agent: NavigationAgent3D = $NavigationAgent3D func _ready() -> void: + if ($Area3D as Area3D).body_entered.connect(_on_body_entered): + pass if Networking.isManager: if timer.timeout.connect(_timer_done): pass find_objective() +func _on_body_entered(body: Node) -> void: + if body is Player and target is Objective: + (body as Player).serve_chance(target as Objective, self) + func _timer_done() -> void: - if angry_meter > 0: + if angry_meter > 0 and target is Objective: angry_meter -= 1 - if target is Objective: - Networking.npc_text_sync_call("%s %ds left" % [(target as Objective).displayed, angry_meter], self) + Networking.npc_text_sync_call("I want a %s! (%ds left)" % [(target as Objective).subtype, angry_meter], target as Objective, self) else: - Networking.npc_text_sync_call("", self) (target as Objective).occupied = false + Networking.npc_text_sync_call("", target as Objective, self) timer.stop() phase = 2 -func set_text(text: String) -> void: +func set_text_and_target(text: String, new_target: Objective) -> void: + target = new_target ($Label3D as Label3D).text = text # determines the closest resting place and navigates to it. @@ -93,14 +100,22 @@ func set_down(node: Carryable) -> void: find_player(99999999999) phase = 0 +func served() -> void: + set_text_and_target("", null) + phase = 4 + func _physics_process(_delta: float) -> void: if Networking.isManager and phase != 1: if phase == 3: find_player(position.distance_to(target.position)) - elif phase == 2 and target is Objective: + elif phase == 2 and target == null: find_carryable() elif phase == 0 and target is Player: find_objective() + elif phase == 4 and target == null: + target = get_tree().root.get_node("/root/"+Game.mapname+"/NPCExit") + navigation_agent.set_target_position(target.position) + timer.stop() if navigation_agent.is_navigation_finished(): if phase == 0: @@ -112,6 +127,8 @@ func _physics_process(_delta: float) -> void: angry_meter = (target as Objective).time + 1 _timer_done() timer.start() + if phase == 4: + Networking.npc_free_sync_call(self) return var current_agent_position: Vector3 = global_position diff --git a/scripts/entities/player.gd b/scripts/entities/player.gd index b659568..8693304 100644 --- a/scripts/entities/player.gd +++ b/scripts/entities/player.gd @@ -4,7 +4,6 @@ class_name Player extends CharacterBody3D - const SPEED: float = 5.0 const JUMP_VELOCITY: float = 4.5 @@ -12,7 +11,7 @@ var activated: bool = false var freecam: bool = false var incapacitated: bool = false var interaction: String -var revival_target: Player +var target: Node3D var carrying_gun: bool = false @onready var camera: Camera3D = $Camera3D @@ -56,10 +55,10 @@ func _physics_process(delta: float) -> void: ($CollisionShape3D as CollisionShape3D).disabled = !($CollisionShape3D as CollisionShape3D).disabled if Input.is_action_just_pressed("interact") and interaction != null: - if interaction == "revive" and revival_target != null: - Networking.revive_sync_call(revival_target) + if interaction == "revive" and target != null: + Networking.revive_sync_call(target as Player) ($InteractDialog as Label).text = "" - revival_target = null + target = null if interaction == "gun": var guncase: Guncase = get_node("/root/%s/Guncase" % Game.mapname) if !guncase.held: @@ -70,7 +69,11 @@ func _physics_process(delta: float) -> void: carrying_gun = false ($InteractDialog as Label).text = "" Networking.guncase_sync_call(false, self) - + if interaction == "serve": + Networking.npc_served_sync_call(target as NPC) + ($InteractDialog as Label).text = "" + target = null + if Input.is_action_just_pressed("shoot") and carrying_gun: Networking.bullet_sync_call(position + (transform.basis * Vector3(0, 0, -1)).normalized(), rotation) @@ -78,15 +81,10 @@ func _physics_process(delta: float) -> void: var direction: Vector3 = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized() #TODO: Hacky solution -> Also can be exploited to revive everyone in the game constantly. - if revival_target != null and position.distance_to(revival_target.position) > 3: + if target != null and position.distance_to(target.position) > 3: ($InteractDialog as Label).text = "" interaction = "" - revival_target = null - - if interaction == "gun": - if position.distance_to((get_node("/root/%s/Guncase" % Game.mapname) as Guncase).position) > 3: - ($InteractDialog as Label).text = "" - interaction = "" + target = null if direction: velocity.x = direction.x * SPEED @@ -126,9 +124,9 @@ func incapacitate() -> void: func revive_chance(body: Player) -> void: if activated: - revival_target = body + target = body interaction = "revive" - ($InteractDialog as Label).text = "Press E to revive %s." % revival_target.name + ($InteractDialog as Label).text = "Press E to revive %s." % target.name func revive() -> void: rotation.x = 0 @@ -137,6 +135,7 @@ func revive() -> void: func gun_chance() -> void: if activated: interaction = "gun" + target = get_node("/root/%s/Guncase" % Game.mapname) as Guncase if carrying_gun: ($InteractDialog as Label).text = "Press E to set down gun." else: @@ -147,3 +146,9 @@ func show_gun() -> void: func hide_gun() -> void: ($Gun as MeshInstance3D).hide() + +func serve_chance(objective: Objective, npc: NPC) -> void: + if activated: + interaction = "serve" + target = npc + ($InteractDialog as Label).text = "Press E to serve the guest a %s." % objective.subtype diff --git a/scripts/maps/carryable/carryable.gd b/scripts/maps/carryable/carryable.gd index 4fc4afa..ebd5204 100644 --- a/scripts/maps/carryable/carryable.gd +++ b/scripts/maps/carryable/carryable.gd @@ -1,3 +1,6 @@ +## SPDX-License-Identifier: GPL-3.0-or-later +## Copyright (c) 2024 interstellardevelopment.org + class_name Carryable extends RigidBody3D diff --git a/scripts/maps/guncase.gd b/scripts/maps/guncase.gd index 19c477d..8582679 100644 --- a/scripts/maps/guncase.gd +++ b/scripts/maps/guncase.gd @@ -1,3 +1,6 @@ +## SPDX-License-Identifier: GPL-3.0-or-later +## Copyright (c) 2024 interstellardevelopment.org + class_name Guncase extends StaticBody3D diff --git a/scripts/maps/objectives/hungry.gd b/scripts/maps/objectives/hungry.gd index bd4ce39..eedefba 100644 --- a/scripts/maps/objectives/hungry.gd +++ b/scripts/maps/objectives/hungry.gd @@ -1,6 +1,16 @@ +## SPDX-License-Identifier: GPL-3.0-or-later +## Copyright (c) 2024 interstellardevelopment.org + class_name Hungry extends Objective func _ready() -> void: - displayed = "Hungry" - time = 5 + type = "hungry" + match randi() % 2: + 0: + subtype = "burger" + 1: + subtype = "burger" + 2: + subtype = "impossible" + time = 20 diff --git a/scripts/maps/objectives/objective.gd b/scripts/maps/objectives/objective.gd index 4a10a05..2d031ec 100644 --- a/scripts/maps/objectives/objective.gd +++ b/scripts/maps/objectives/objective.gd @@ -6,4 +6,5 @@ extends Node3D var occupied: bool = false var time: int -var displayed: String +var type: String +var subtype: String diff --git a/scripts/player_interactables/food/burger.gd b/scripts/player_interactables/food/burger.gd new file mode 100644 index 0000000..8079c40 --- /dev/null +++ b/scripts/player_interactables/food/burger.gd @@ -0,0 +1,7 @@ +## SPDX-License-Identifier: GPL-3.0-or-later +## Copyright (c) 2024 interstellardevelopment.org + +extends Food + +func _ready() -> void: + food_name = "burger" diff --git a/scripts/player_interactables/food/food.gd b/scripts/player_interactables/food/food.gd new file mode 100644 index 0000000..3280633 --- /dev/null +++ b/scripts/player_interactables/food/food.gd @@ -0,0 +1,7 @@ +## SPDX-License-Identifier: GPL-3.0-or-later +## Copyright (c) 2024 interstellardevelopment.org + +class_name Food +extends RigidBody3D + +var food_name: String = "Placeholder" diff --git a/scripts/ui/create_room.gd b/scripts/ui/create_room.gd index 153e0e5..75d3d95 100644 --- a/scripts/ui/create_room.gd +++ b/scripts/ui/create_room.gd @@ -4,6 +4,8 @@ extends Control func _ready() -> void: + ($VBoxContainer/UsernameHBox/LineEdit as LineEdit).text = Game.username + ($VBoxContainer/RoomnameHBox/LineEdit as LineEdit).text = Game.roomname if ($VBoxContainer/SendButton as Button).pressed.connect(_on_send_button_pressed): pass diff --git a/scripts/ui/main_menu.gd b/scripts/ui/main_menu.gd new file mode 100644 index 0000000..b87e1aa --- /dev/null +++ b/scripts/ui/main_menu.gd @@ -0,0 +1,15 @@ +extends Control + +func _ready() -> void: + if ($VBoxContainer/Join as Button).pressed.connect(_on_join_clicked): + pass + if ($VBoxContainer/Settings as Button).pressed.connect(_on_settings_clicked): + pass + +func _on_join_clicked() -> void: + if get_tree().change_scene_to_file("res://scenes/ui/create_room.tscn") != OK: + Log.error("Couldn't change to the create room scene! Closing application.", "Couldn't change to the create room scene!") + +func _on_settings_clicked() -> void: + if get_tree().change_scene_to_file("res://scenes/ui/settings.tscn") != OK: + Log.error("Couldn't change to the settings scene! Closing application.", "Couldn't change to the settings scene!") diff --git a/scripts/ui/settings.gd b/scripts/ui/settings.gd new file mode 100644 index 0000000..03b9629 --- /dev/null +++ b/scripts/ui/settings.gd @@ -0,0 +1,16 @@ +extends Control + +func _ready() -> void: + ($VBoxContainer/DefaultServerIP/LineEdit as LineEdit).text = Game.ip + ($VBoxContainer/DefaultUsername/LineEdit as LineEdit).text = Game.username + ($VBoxContainer/DefaultRoomname/LineEdit as LineEdit).text = Game.roomname + if ($VBoxContainer/Return as Button).pressed.connect(_on_return_clicked): + pass + +func _on_return_clicked() -> void: + Game.ip = ($VBoxContainer/DefaultServerIP/LineEdit as LineEdit).text + Game.username = ($VBoxContainer/DefaultUsername/LineEdit as LineEdit).text + Game.roomname = ($VBoxContainer/DefaultRoomname/LineEdit as LineEdit).text + Game.save_settings() + if get_tree().change_scene_to_file("res://scenes/ui/main_menu.tscn") != OK: + Log.error("Couldn't change to the main menu scene! Closing application.", "Couldn't change to the main menu scene!") diff --git a/scripts/utils/game.gd b/scripts/utils/game.gd index 1584445..8e94016 100644 --- a/scripts/utils/game.gd +++ b/scripts/utils/game.gd @@ -15,14 +15,16 @@ var ip: String = "127.0.0.1" var port: int = 25262 var max_clients: int = 1024 -var roomname: String = "sample" -var username: String = "sample" +var roomname: String = "" +var username: String = "" var mapname: String = "Testmap" var launchmode: int = 0 func _ready() -> void: Log.info("Running on: %s %s (%s)" % [OS.get_distribution_name(), OS.get_version(), OS.get_name()]) + randomize() + load_settings() var args: PackedStringArray = OS.get_cmdline_args() var skip: bool = false for i: int in range(args.size()): @@ -55,8 +57,8 @@ func _ready() -> void: match launchmode: 0: # Menu - if get_tree().change_scene_to_file("res://scenes/ui/create_room.tscn") != OK: - Log.error("Couldn't change to the create room scene! Closing application.", "Couldn't change to the create room scene!") + if get_tree().change_scene_to_file("res://scenes/ui/main_menu.tscn") != OK: + Log.error("Couldn't change to the main menu scene! Closing application.", "Couldn't change to the main menu scene!") 1: # Client with direct join Networking.join_room() @@ -64,3 +66,31 @@ func _ready() -> void: # Server if Networking.start_server() != OK: Log.error("Failed to start server! Closing application.", "Failed to start server!") + +func save_settings() -> void: + var to_save: Dictionary = { + "ip": ip, + "roomname": roomname, + "username": username, + } + var to_save_string: String = JSON.stringify(to_save) + var save_file: FileAccess = FileAccess.open("user://save.json", FileAccess.WRITE) + if save_file == null: + Log.warning("Couldn't save the json.") + return + save_file.store_string(to_save_string) + +func load_settings() -> void: + var save_file: FileAccess = FileAccess.open("user://save.json", FileAccess.READ) + if save_file == null: + Log.warning("Couldn't open the json save.") + return + var json_string: String = save_file.get_as_text() + var json: JSON = JSON.new() + if json.parse(json_string) != OK: + Log.warning("Couldn't parse the json save.") + return + var data: Dictionary = json.data + ip = data["ip"] + roomname = data["roomname"] + username = data["username"] diff --git a/scripts/utils/networking.gd b/scripts/utils/networking.gd index acfec59..d35d5ff 100644 --- a/scripts/utils/networking.gd +++ b/scripts/utils/networking.gd @@ -7,6 +7,9 @@ # The peers are untrusted. They may cheat, or try something stupid. If at all possible, Direct peer to peer communication should be prevented. # Rather, such a thing should be done through the game manager if possible. +#TODO: All instances, where any peer can send something, we have to extensively check it, else it may crash somebodys game! Especially NodePaths! +#TODO: Non affiliated peer log messages! + extends Node signal playerlist_changed() @@ -328,19 +331,22 @@ func object_sync(position: Vector3, rotation: Vector3, node_name: String) -> voi else: Log.warning("Non-manager peer tried to send a manager only request: object_sync") +func npc_text_sync_call(text: String, target: Objective, npc: NPC) -> void: + for peer: int in Networking.get_ids(): + if rpc_id(peer, "npc_text_sync", text, target.get_path(), npc.get_path()) != OK: + Log.warning("Couldn't send RPC to %d!" % peer) + # Synchronizes the text above the npc. @rpc("any_peer", "call_local", "reliable") -func npc_text_sync(text: String, npc: NodePath) -> void: +func npc_text_sync(text: String, target: NodePath, npc: NodePath) -> void: if managerID == multiplayer.get_remote_sender_id(): - (get_node(npc) as NPC).set_text(text) + if text == "": + (get_node(npc) as NPC).set_text_and_target(text, null) + else: + (get_node(npc) as NPC).set_text_and_target(text, get_node(target) as Objective) else: Log.warning("Non-manager peer tried to send a manager only request: npc_text_sync") -func npc_text_sync_call(text: String, npc: NPC) -> void: - for peer: int in Networking.get_ids(): - if rpc_id(peer, "npc_text_sync", text, npc.get_path()) != OK: - Log.warning("Couldn't send RPC to %d!" % peer) - func pick_up_sync_call(npc: NPC, carryable: Carryable) -> void: # We need to get the path before we send out sync calls. This is because the value changes depending on whether or not it already ran locally. var carryable_path: NodePath = carryable.get_path() @@ -407,7 +413,10 @@ func guncase_sync(status: bool, player_path: NodePath) -> void: #TODO: Anti-Cheat -> Check if the gun is even available! if verify_id(multiplayer.get_remote_sender_id()): (get_node("/root/%s/Guncase" % Game.mapname) as Guncase).held = status - (get_node(player_path) as Player).show_gun() + if status == true: + (get_node(player_path) as Player).show_gun() + else: + (get_node(player_path) as Player).hide_gun() func bullet_sync_call(position: Vector3, rotation: Vector3) -> void: for peer: int in Networking.get_ids(): @@ -423,3 +432,32 @@ func bullet_sync(position: Vector3, rotation: Vector3) -> void: bullet_instance.position = position bullet_instance.rotation = rotation get_node("/root/"+Game.mapname).add_child(bullet_instance) + +func npc_free_sync_call(npc: NPC) -> void: + var npc_path: NodePath = npc.get_path() + for peer: int in Networking.get_ids(): + if rpc_id(peer, "npc_free_sync", npc_path) != OK: + Log.warning("Couldn't send RPC to %d!" % peer) + +# Synchronizes the npc removal. +@rpc("any_peer", "call_local", "reliable") +func npc_free_sync(npc_path: NodePath) -> void: + if managerID == multiplayer.get_remote_sender_id(): + get_node(npc_path).queue_free() + else: + Log.warning("Non-manager peer tried to send a manager only request: npc_free_sync") + +func npc_served_sync_call(npc: NPC) -> void: + var npc_path: NodePath = npc.get_path() + for peer: int in Networking.get_ids(): + if rpc_id(peer, "npc_served_sync", npc_path) != OK: + Log.warning("Couldn't send RPC to %d!" % peer) + +# Synchronizes when the npc was served. +@rpc("any_peer", "call_local", "reliable") +func npc_served_sync(npc_path: NodePath) -> void: + #TODO: Anti-Cheat -> Prevent unauthorized serving! + if verify_id(multiplayer.get_remote_sender_id()): + (get_node(npc_path) as NPC).served() + else: + Log.warning("Non-manager peer tried to send a manager only request: npc_served_sync")