diff --git a/project.godot b/project.godot index 1ac88d8..4ed6e33 100644 --- a/project.godot +++ b/project.godot @@ -77,5 +77,13 @@ walk={ rendering_device/fallback_to_vulkan=false rendering_device/fallback_to_d3d12=false -renderer/rendering_method="mobile" +lights_and_shadows/directional_shadow/size.mobile=4096 +lights_and_shadows/directional_shadow/soft_shadow_filter_quality=3 +lights_and_shadows/directional_shadow/soft_shadow_filter_quality.mobile=3 +lights_and_shadows/positional_shadow/soft_shadow_filter_quality=3 +lights_and_shadows/positional_shadow/soft_shadow_filter_quality.mobile=3 environment/defaults/default_clear_color=Color(0, 0, 0, 1) +anti_aliasing/quality/msaa_2d=1 +anti_aliasing/quality/msaa_3d=1 +anti_aliasing/quality/use_debanding=true +lights_and_shadows/positional_shadow/atlas_size.mobile=4096 diff --git a/scenes/chaser.tscn b/scenes/chaser.tscn index f80b167..dd12763 100644 --- a/scenes/chaser.tscn +++ b/scenes/chaser.tscn @@ -44,7 +44,7 @@ height = 1.8 [sub_resource type="SphereShape3D" id="SphereShape3D_wsx1k"] -[node name="Runner" type="CharacterBody3D" node_paths=PackedStringArray("state_machine")] +[node name="Chaser" type="CharacterBody3D" node_paths=PackedStringArray("state_machine")] script = ExtResource("1_hjhpa") state_machine = NodePath("StateMachine") diff --git a/scenes/house.tscn b/scenes/house.tscn index 9a8388d..f1a16d2 100644 --- a/scenes/house.tscn +++ b/scenes/house.tscn @@ -143,12 +143,12 @@ mesh = SubResource("BoxMesh_lm401") [node name="FirstFloorLight" type="OmniLight3D" parent="Lights"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 4, 0) +light_energy = 0.5 shadow_enabled = true omni_range = 40.0 -omni_attenuation = 1.5 [node name="SecondFloorLight" type="OmniLight3D" parent="Lights"] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 9, 0) +light_energy = 0.5 shadow_enabled = true omni_range = 40.0 -omni_attenuation = 1.5 diff --git a/scenes/in_game.tscn b/scenes/in_game.tscn index ae5119f..6fca3fd 100644 --- a/scenes/in_game.tscn +++ b/scenes/in_game.tscn @@ -10,9 +10,14 @@ background_mode = 1 ambient_light_source = 2 ambient_light_color = Color(1, 1, 1, 1) ambient_light_energy = 0.01 +tonemap_mode = 3 sdfgi_read_sky_light = false glow_enabled = true glow_normalized = true +volumetric_fog_enabled = true +volumetric_fog_albedo = Color(0.381703, 0.381703, 0.381703, 1) +volumetric_fog_emission = Color(0.314009, 2.89988e-06, 1.52815e-06, 1) +volumetric_fog_emission_energy = 0.25 [sub_resource type="WorldBoundaryShape3D" id="WorldBoundaryShape3D_1l61b"] diff --git a/scenes/runner.tscn b/scenes/runner.tscn index 4dd0ffd..e1cff05 100644 --- a/scenes/runner.tscn +++ b/scenes/runner.tscn @@ -15,18 +15,24 @@ properties/0/spawn = true properties/0/replication_mode = 2 properties/1/path = NodePath(".:server_position") properties/1/spawn = true -properties/1/replication_mode = 2 +properties/1/replication_mode = 1 properties/2/path = NodePath(".:server_rotation") properties/2/spawn = true -properties/2/replication_mode = 2 +properties/2/replication_mode = 1 [sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_1agtp"] properties/0/path = NodePath("Input:direction") properties/0/spawn = true -properties/0/replication_mode = 2 -properties/1/path = NodePath("Input:walking") +properties/0/replication_mode = 1 +properties/1/path = NodePath("Input:walk") properties/1/spawn = true -properties/1/replication_mode = 2 +properties/1/replication_mode = 1 +properties/2/path = NodePath("Input:primary_interact") +properties/2/spawn = true +properties/2/replication_mode = 1 +properties/3/path = NodePath("Input:secondary_interact") +properties/3/spawn = true +properties/3/replication_mode = 1 [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_j6tb3"] radius = 0.3 diff --git a/scripts/in_game.gd b/scripts/in_game.gd index 118e9c6..94e8580 100644 --- a/scripts/in_game.gd +++ b/scripts/in_game.gd @@ -9,16 +9,24 @@ var _ping := 0.0 @onready var _runners_node: Node3D = %Runners func spawn_player(player_id: int, runner: bool) -> void: - if multiplayer.is_server(): - var player = runner_scene.instantiate() if runner else chaser_scene.instantiate() - player.player_id = player_id - player.name = str(player_id) + if not multiplayer.is_server(): return - _runners_node.add_child(player) if runner else _chasers_node.add_child(player) + var player = runner_scene.instantiate() if runner else chaser_scene.instantiate() + player.player_id = player_id + player.name = str(player_id) + + _runners_node.add_child(player) if runner else _chasers_node.add_child(player) + +func despawn_player(player_id: int) -> void: + if not multiplayer.is_server(): return + + var player_id_str := str(player_id) + for runner_or_chaser in _runners_node.get_children() + _chasers_node.get_children(): + if runner_or_chaser.name == player_id_str: + runner_or_chaser.queue_free() func _process(_delta: float) -> void: - if DisplayServer.get_name() == "headless": - return + if DisplayServer.get_name() == "headless": return %StatsLabel.text = statsTemplate % [ Engine.get_frames_per_second(), diff --git a/scripts/main.gd b/scripts/main.gd index 659e43a..87c401e 100644 --- a/scripts/main.gd +++ b/scripts/main.gd @@ -5,3 +5,6 @@ var gravity_vector: Vector3 = ProjectSettings.get_setting("physics/3d/default_gr var physics_tickrate = Engine.get_physics_ticks_per_second() var terminal_velocity: float = 150.0 var gravity_velocity: Vector3 = (gravity_vector * gravity) / (physics_tickrate as float) + +func is_server_or_predicting(player_id: int, client_prediction: bool = false): + return multiplayer.is_server() or (multiplayer.get_unique_id() == player_id and client_prediction) diff --git a/scripts/multiplayer/input.gd b/scripts/multiplayer/input.gd index bf3898b..207d89e 100644 --- a/scripts/multiplayer/input.gd +++ b/scripts/multiplayer/input.gd @@ -1,7 +1,9 @@ extends MultiplayerSynchronizer @export var direction: Vector2 = Vector2.ZERO -@export var walking: bool = false +@export var walk: bool = false +@export var primary_interact: bool = false +@export var secondary_interact: bool = false @onready var _camera_pivot: Node3D = %CameraPivot @@ -9,10 +11,9 @@ func _ready() -> void: if multiplayer.is_server() or get_multiplayer_authority() != multiplayer.get_unique_id(): set_process(false) set_physics_process(false) - return func _physics_process(_delta: float) -> void: var directional_input := Input.get_vector("move_right", "move_left", "move_forward", "move_back") var camera_adjusted: Vector3 = (directional_input.x * _camera_pivot.global_basis.z) + (directional_input.y * _camera_pivot.global_basis.x) direction = Vector2(camera_adjusted.x, camera_adjusted.z).rotated(PI / 2.0).normalized() - walking = Input.is_action_pressed("walk") + walk = Input.is_action_pressed("walk") diff --git a/scripts/multiplayer/multiplayer_manager.gd b/scripts/multiplayer/multiplayer_manager.gd index accdcd1..5012a80 100644 --- a/scripts/multiplayer/multiplayer_manager.gd +++ b/scripts/multiplayer/multiplayer_manager.gd @@ -26,9 +26,8 @@ func _ready() -> void: get_tree().change_scene_to_packed.call_deferred(main_menu_scene) func connect_to_ip(runner: bool = true, ip: String = "") -> void: - if ip.is_empty(): - ip = IP_ADDRESS - + if ip.is_empty(): ip = IP_ADDRESS + runner_client_selection = runner print("Connecting to: %s" % ip) @@ -46,25 +45,23 @@ func _on_connect(id: int) -> void: func _on_disconnect(id: int) -> void: print("Client ID #%s disconnected" % id) - pass + if not multiplayer.is_server(): return + + get_tree().get_current_scene().despawn_player(id) func _on_connect_client() -> void: request_is_runner.rpc_id(1, runner_client_selection) print("[%s] Connected to server" % multiplayer.get_unique_id()) - pass func _on_disconnect_client() -> void: print("[%s] Disconnected" % multiplayer.get_unique_id()) - pass func _on_server_closed_client() -> void: print("[%s] Server closed" % multiplayer.get_unique_id()) - pass @rpc("any_peer", "call_remote", "reliable") func request_is_runner(runner: bool) -> void: - if not multiplayer.is_server(): - return + if not multiplayer.is_server(): return var id := multiplayer.get_remote_sender_id() runner_dict[id] = runner diff --git a/scripts/runner.gd b/scripts/runner.gd index e3b7301..6ad1032 100644 --- a/scripts/runner.gd +++ b/scripts/runner.gd @@ -43,8 +43,7 @@ var predicted_rotation := Vector3.ZERO func _ready() -> void: state_machine.set_subject(self) - if multiplayer.is_server(): - return + if multiplayer.is_server(): return if multiplayer.get_unique_id() == player_id: %Camera.make_current() @@ -52,8 +51,7 @@ func _ready() -> void: %Camera.clear_current(false) func _input(event: InputEvent) -> void: - if multiplayer.get_unique_id() != player_id: - return + if multiplayer.get_unique_id() != player_id: return if event.is_action_pressed("mouse_capture"): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED @@ -65,13 +63,14 @@ func _input(event: InputEvent) -> void: camera_input_direction += event.screen_relative * mouse_sensitivity func _process(delta: float) -> void: - if multiplayer.get_unique_id() == player_id: - _camera_platform.global_rotation = _camera_pivot.global_rotation + if multiplayer.get_unique_id() != player_id: return - if smooth_camera: - _camera_platform.global_position = lerp(_camera_platform.global_position, _camera_pivot.global_position, camera_follow_speed * delta) - else: - _camera_platform.global_position = _camera_pivot.global_position + _camera_platform.global_rotation = _camera_pivot.global_rotation + + if smooth_camera: + _camera_platform.global_position = lerp(_camera_platform.global_position, _camera_pivot.global_position, camera_follow_speed * delta) + else: + _camera_platform.global_position = _camera_pivot.global_position func _physics_process(delta: float) -> void: state_machine.process_physics(delta) @@ -100,7 +99,6 @@ func _physics_process(delta: float) -> void: if multiplayer.is_server(): server_position = position server_rotation = skin.global_rotation - pass func _on_sync_delta_synchronized() -> void: if client_prediction and server_position.distance_to(predicted_position) > client_prediction_tolerance: diff --git a/scripts/states/fall.gd b/scripts/states/fall.gd index 4c22ecd..7cf9505 100644 --- a/scripts/states/fall.gd +++ b/scripts/states/fall.gd @@ -1,22 +1,14 @@ extends State func process_physics(delta: float) -> State: - if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction): - return + if not Main.is_server_or_predicting(subject.player_id, subject.client_prediction): return var target_velocity = Vector3(0, subject.velocity.y, 0) subject.velocity = subject.velocity.move_toward(target_velocity, subject.air_deceleration * delta) subject.velocity += Main.gravity_velocity subject.move_and_slide() - if subject.is_on_floor(): - var input_direction = %Input.direction - if input_direction.length() < 0.05: - return %Idle - - if %Input.walking: - return %Walk - - return %Run - - return + if not subject.is_on_floor(): return + if %Input.direction.length() < 0.05: return %Idle + if %Input.walk: return %Walk + return %Run diff --git a/scripts/states/idle.gd b/scripts/states/idle.gd index 415463d..870b645 100644 --- a/scripts/states/idle.gd +++ b/scripts/states/idle.gd @@ -1,19 +1,16 @@ extends State func process_physics(delta: float) -> State: - if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction): - return + if not Main.is_server_or_predicting(subject.player_id, subject.client_prediction): return var target_velocity = Vector3(0, subject.velocity.y, 0) subject.velocity = subject.velocity.move_toward(target_velocity, subject.acceleration * delta) subject.velocity += Main.gravity_velocity subject.move_and_slide() - if not subject.is_on_floor(): - return %Fall + if not subject.is_on_floor(): return %Fall var input_direction = %Input.direction - if input_direction.length() < 0.05: - return + if input_direction.length() < 0.05: return return %Run diff --git a/scripts/states/run.gd b/scripts/states/run.gd index da26f49..ce42721 100644 --- a/scripts/states/run.gd +++ b/scripts/states/run.gd @@ -1,12 +1,10 @@ extends State func process_physics(delta: float) -> State: - if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction): - return + if not Main.is_server_or_predicting(subject.player_id, subject.client_prediction): return var input_direction = %Input.direction - if input_direction.length() < 0.05: - return %Idle + if input_direction.length() < 0.05: return %Idle var move_direction = Vector3(input_direction.x, 0, input_direction.y) var target_velocity = Vector3(move_direction.x * subject.run_speed, subject.velocity.y, move_direction.z * subject.run_speed) @@ -19,10 +17,6 @@ func process_physics(delta: float) -> State: var target_angle := Vector3.FORWARD.signed_angle_to(subject.last_direction, Vector3.UP) subject.skin.global_rotation.y = lerp_angle(subject.skin.rotation.y, target_angle, subject.rotation_speed * delta) - if %Input.walking: - return %Walk - - if not subject.is_on_floor(): - return %Fall - + if %Input.walk: return %Walk + if not subject.is_on_floor(): return %Fall return diff --git a/scripts/states/state_machine.gd b/scripts/states/state_machine.gd index 9b12467..076982a 100644 --- a/scripts/states/state_machine.gd +++ b/scripts/states/state_machine.gd @@ -9,42 +9,27 @@ func set_subject(new_subject: Node) -> void: state.subject = subject func _change_state(new_state: State) -> void: - if current_state: - #print("Exiting: %s" % current_state.name) - current_state.exit() + if current_state: current_state.exit() current_state = new_state - #print("Entering: %s" % current_state.name) current_state.enter() func process_physics(delta: float) -> void: - if not current_state: - return - - if not current_state.subject: - return + if not current_state or not current_state.subject: return var new_state = current_state.process_physics(delta) if new_state: _change_state(new_state) func process_input(event: InputEvent) -> void: - if not current_state: - return - - if not current_state.subject: - return + if not current_state or not current_state.subject: return var new_state = current_state.process_input(event) if new_state: _change_state(new_state) func process_frame(delta: float) -> void: - if not current_state: - return - - if not current_state.subject: - return + if not current_state or not current_state.subject: return var new_state = current_state.process_frame(delta) if new_state: diff --git a/scripts/states/walk.gd b/scripts/states/walk.gd index 39cf93b..3277d26 100644 --- a/scripts/states/walk.gd +++ b/scripts/states/walk.gd @@ -1,12 +1,10 @@ extends State func process_physics(delta: float) -> State: - if not multiplayer.is_server() and (multiplayer.get_unique_id() != subject.player_id or not subject.client_prediction): - return + if not Main.is_server_or_predicting(subject.player_id, subject.client_prediction): return var input_direction = %Input.direction - if input_direction.length() < 0.05: - return %Idle + if input_direction.length() < 0.05: return %Idle var move_direction = Vector3(input_direction.x, 0, input_direction.y) var target_velocity = Vector3(move_direction.x * subject.walk_speed, subject.velocity.y, move_direction.z * subject.walk_speed) @@ -19,10 +17,6 @@ func process_physics(delta: float) -> State: var target_angle := Vector3.FORWARD.signed_angle_to(subject.last_direction, Vector3.UP) subject.skin.global_rotation.y = lerp_angle(subject.skin.rotation.y, target_angle, subject.rotation_speed * delta) - if not %Input.walking: - return %Run - - if not subject.is_on_floor(): - return %Fall - + if not %Input.walk: return %Run + if not subject.is_on_floor(): return %Fall return