New AI slop
This commit is contained in:
parent
8b824d49da
commit
e8cf9e47c0
@ -1,34 +1,20 @@
|
|||||||
class_name ShipHelm
|
class_name ShipHelm
|
||||||
|
|
||||||
extends Interactable
|
extends Interactable
|
||||||
|
|
||||||
var parent_ship: Ship
|
var parent_ship: Ship
|
||||||
|
|
||||||
var uuid: String = ""
|
|
||||||
|
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
uuid = NetworkManager.register_node(self)
|
|
||||||
NetworkManager.property_update_received.connect(_on_property_update)
|
|
||||||
parent_ship = get_parent().get_parent() #sets the parent ship to the ship that the helm is placed on
|
parent_ship = get_parent().get_parent() #sets the parent ship to the ship that the helm is placed on
|
||||||
NetworkManager.sync_property(uuid, "parent_ship", parent_ship)
|
|
||||||
|
|
||||||
|
|
||||||
func interact():
|
func interact():
|
||||||
if player_reference.is_network_authority:
|
if player_reference.is_network_authority:
|
||||||
if !parent_ship.ship_is_piloted:
|
if !parent_ship.ship_is_piloted:
|
||||||
player_reference.set_is_piloting(true)
|
player_reference.set_is_piloting(true)
|
||||||
parent_ship.ship_is_piloted = true
|
parent_ship.set_piloting_player(player_reference)
|
||||||
|
|
||||||
elif parent_ship.ship_is_piloted:
|
elif parent_ship.ship_is_piloted:
|
||||||
player_reference.set_is_piloting(false)
|
player_reference.set_is_piloting(false)
|
||||||
parent_ship.ship_is_piloted = false
|
parent_ship.remove_piloting_player()
|
||||||
parent_ship._sync_piloting_state()
|
parent_ship._sync_piloting_state()
|
||||||
|
|
||||||
|
|
||||||
func _on_property_update(uuid: String, property_name: String, value: Variant):
|
|
||||||
if NetworkManager.node_map.has(uuid):
|
|
||||||
var node = NetworkManager.node_map[uuid]
|
|
||||||
node.set(property_name, value)
|
|
||||||
else:
|
|
||||||
printerr("Received property update but node_id is wrong? Expected " + str(uuid) + " but got " + str(uuid))
|
|
@ -1,223 +1,105 @@
|
|||||||
extends RigidBody3D
|
|
||||||
class_name Ship
|
class_name Ship
|
||||||
|
|
||||||
|
extends RigidBody3D
|
||||||
|
|
||||||
@export var player_detection_area: Area3D
|
@export var player_detection_area: Area3D
|
||||||
@export var helm_location_marker: Marker3D
|
@export var helm_location_marker: Marker3D
|
||||||
|
|
||||||
var delta_time: float = 0.0
|
|
||||||
|
|
||||||
var ship_helm_scene: PackedScene = load("res://assets/core/interactables/ship-helm/ship-helm.tscn")
|
|
||||||
|
|
||||||
var ship_helm: ShipHelm = null
|
|
||||||
var piloting_player: Player = null
|
var piloting_player: Player = null
|
||||||
#var ship_id: int = random_int() # Generate a random ship ID
|
|
||||||
var ship_is_piloted: bool = false
|
var ship_is_piloted: bool = false
|
||||||
var current_level: Node = null
|
|
||||||
var network_uuid: String = ""
|
|
||||||
|
|
||||||
var old_global_rotation_cache: Vector3
|
@export var base_turn_speed: float = 0.35
|
||||||
var old_global_position_cache: Vector3
|
|
||||||
|
|
||||||
var rotation_correction: Vector3
|
|
||||||
var position_correction: Vector3
|
|
||||||
|
|
||||||
@export_range(0.01, 1.0, 0.01) var base_turn_speed: float = 0.35
|
|
||||||
@export var max_turn_speed: float = 0.5
|
@export var max_turn_speed: float = 0.5
|
||||||
@export_range(0.01, 10.0, 0.01) var base_lift_speed: float = 2.0
|
@export var base_lift_speed: float = 2.0
|
||||||
@export var top_speed: float = 5.0
|
@export var top_speed: float = 5.0
|
||||||
@export var move_speed: float = 1.0
|
@export var move_speed: float = 1.0
|
||||||
@export var acceleration: float = 0.1
|
@export var acceleration: float = 0.1
|
||||||
|
|
||||||
# Network Synchronization Variables
|
# Networking
|
||||||
var last_sync_time: float = 0.0
|
var network_uuid: String = ""
|
||||||
var sync_interval: float = 0.1 # Sync every 0.1 seconds
|
var target_position: Vector3 = Vector3.ZERO
|
||||||
|
var target_rotation: Quaternion = Quaternion()
|
||||||
var predicted_position: Vector3
|
var previous_position: Vector3
|
||||||
var predicted_rotation: Quaternion
|
var previous_rotation: Quaternion
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
# Register the ship with the NetworkManager for P2P communication
|
|
||||||
network_uuid = NetworkManager.register_node(self)
|
network_uuid = NetworkManager.register_node(self)
|
||||||
NetworkManager.property_update_received.connect(_on_property_update)
|
target_position = global_position
|
||||||
|
target_rotation = global_transform.basis.get_rotation_quaternion()
|
||||||
|
previous_position = global_position
|
||||||
|
previous_rotation = global_transform.basis.get_rotation_quaternion()
|
||||||
|
|
||||||
# Connect signals for player interaction
|
NetworkManager.property_update_received.connect(_on_property_update_received)
|
||||||
player_detection_area.body_entered.connect(_on_area_3d_body_entered)
|
|
||||||
player_detection_area.body_exited.connect(_on_area_3d_body_exited)
|
|
||||||
|
|
||||||
# Spawn the ship helm visually (optional based on your design)
|
func _process(delta: float):
|
||||||
_add_ship_helm(ship_helm_scene)
|
if piloting_player and piloting_player.is_network_authority:
|
||||||
|
handle_input(delta)
|
||||||
# Initialize predicted values
|
sync_ship_state()
|
||||||
predicted_position = global_position
|
|
||||||
predicted_rotation = Quaternion.from_euler(global_rotation).normalized()
|
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
|
||||||
delta_time = delta
|
|
||||||
|
|
||||||
func _physics_process(_delta):
|
|
||||||
# Predict movement only for non-authority clients
|
|
||||||
if not piloting_player or piloting_player.is_network_authority:
|
|
||||||
_predict_movement(_delta)
|
|
||||||
else:
|
else:
|
||||||
# Apply predicted values until peer correction arrives
|
interpolate_position_and_rotation(delta)
|
||||||
global_position = predicted_position
|
|
||||||
global_rotation = predicted_rotation.get_euler()
|
|
||||||
|
|
||||||
# Apply actual input if it's the authority client
|
func handle_input(delta: float):
|
||||||
if piloting_player != null and piloting_player.is_network_authority:
|
var input_vector = Vector3.ZERO
|
||||||
_apply_local_input(_delta)
|
|
||||||
|
|
||||||
# Self level slowly if host
|
|
||||||
global_rotation.x = lerpf(global_rotation.x, 0, 0.1)
|
|
||||||
global_rotation.z = lerpf(global_rotation.z, 0, 0.1)
|
|
||||||
|
|
||||||
# Apply corrections if available
|
|
||||||
if position_correction != Vector3.ZERO:
|
|
||||||
_handle_position_correction(position_correction)
|
|
||||||
position_correction = Vector3.ZERO
|
|
||||||
|
|
||||||
if rotation_correction != Vector3.ZERO:
|
|
||||||
_handle_rotation_correction(rotation_correction)
|
|
||||||
rotation_correction = Vector3.ZERO
|
|
||||||
|
|
||||||
# Send network updates periodically
|
|
||||||
_send_ship_sync()
|
|
||||||
|
|
||||||
func _predict_movement(_delta):
|
|
||||||
# Simple linear prediction
|
|
||||||
var predicted_velocity = linear_velocity
|
|
||||||
predicted_position += predicted_velocity * _delta
|
|
||||||
|
|
||||||
# Basic rotation prediction (can be improved)
|
|
||||||
if angular_velocity.length() > 0:
|
|
||||||
var predicted_angular_velocity = angular_velocity.normalized()
|
|
||||||
var predicted_rotation_delta = Quaternion(predicted_angular_velocity, _delta)
|
|
||||||
predicted_rotation = predicted_rotation * predicted_rotation_delta
|
|
||||||
|
|
||||||
func _apply_local_input(_delta):
|
|
||||||
if piloting_player == null or not piloting_player.is_network_authority or not piloting_player.is_piloting:
|
|
||||||
return
|
|
||||||
|
|
||||||
var turn_speed = base_turn_speed / max(mass, 1)
|
|
||||||
var lift_speed = base_lift_speed / max(mass, 1)
|
|
||||||
|
|
||||||
|
if Input.is_action_pressed("move_forward"):
|
||||||
|
input_vector.z -= 1
|
||||||
|
if Input.is_action_pressed("move_backward"):
|
||||||
|
input_vector.z += 1
|
||||||
if Input.is_action_pressed("move_left"):
|
if Input.is_action_pressed("move_left"):
|
||||||
angular_velocity.y += turn_speed
|
input_vector.x -= 1
|
||||||
elif Input.is_action_pressed("move_right"):
|
if Input.is_action_pressed("move_right"):
|
||||||
angular_velocity.y -= turn_speed
|
input_vector.x += 1
|
||||||
else:
|
if Input.is_action_pressed("move_up"):
|
||||||
global_rotation.z = lerpf(global_rotation.z, 0, 0.8)
|
input_vector.y += 1
|
||||||
|
if Input.is_action_pressed("move_down"):
|
||||||
|
input_vector.y -= 1
|
||||||
|
|
||||||
if Input.is_action_pressed("jump"):
|
if input_vector.length() > 0:
|
||||||
linear_velocity.y += lift_speed
|
input_vector = input_vector.normalized() * move_speed
|
||||||
elif Input.is_action_pressed("crouch"):
|
apply_force(input_vector)
|
||||||
linear_velocity.y -= lift_speed
|
|
||||||
|
|
||||||
var target_velocity = Vector3.ZERO
|
# Rotation handling
|
||||||
if Input.is_action_pressed("move_forwards"):
|
var yaw = Input.get_action_strength("turn_right") - Input.get_action_strength("turn_left")
|
||||||
target_velocity = -transform.basis.z * top_speed
|
var pitch = Input.get_action_strength("turn_up") - Input.get_action_strength("turn_down")
|
||||||
elif Input.is_action_pressed("move_backwards"):
|
|
||||||
target_velocity = transform.basis.z * top_speed
|
|
||||||
|
|
||||||
var current_acceleration = (target_velocity - linear_velocity) * acceleration
|
if yaw != 0 or pitch != 0:
|
||||||
apply_central_force(current_acceleration * mass)
|
apply_torque(Vector3(pitch, yaw, 0) * base_turn_speed)
|
||||||
|
|
||||||
# Clamp velocity to prevent excessive speed
|
func sync_ship_state():
|
||||||
if linear_velocity.length() > top_speed:
|
if global_position != previous_position:
|
||||||
linear_velocity = linear_velocity.normalized() * top_speed
|
|
||||||
|
|
||||||
# Clamp angular velocity to prevent excessive turning
|
|
||||||
angular_velocity.y = clamp(angular_velocity.y, -max_turn_speed, max_turn_speed)
|
|
||||||
|
|
||||||
func _on_area_3d_body_entered(body: Node3D) -> void:
|
|
||||||
if body is Player and body.get_parent() != self:
|
|
||||||
body.ship_entered(self)
|
|
||||||
piloting_player = body
|
|
||||||
body.call_deferred("reparent", self, true) # Reparents player onto the ship
|
|
||||||
ship_is_piloted = true
|
|
||||||
_sync_piloting_state() # Update piloting state for other clients
|
|
||||||
|
|
||||||
func _on_area_3d_body_exited(body: Node3D) -> void:
|
|
||||||
if body is Player and body.get_parent() != get_node("/root/DevLevel/"):
|
|
||||||
body.ship_exited()
|
|
||||||
ship_is_piloted = false
|
|
||||||
piloting_player = null
|
|
||||||
body.call_deferred("reparent", get_node("/root/DevLevel/"), true) # Reparents player back to the world
|
|
||||||
_sync_piloting_state() # Update piloting state for other clients
|
|
||||||
|
|
||||||
func _add_ship_helm(_ship_helm_scene: PackedScene):
|
|
||||||
var ship_helm_instance = _ship_helm_scene.instantiate()
|
|
||||||
helm_location_marker.add_child(ship_helm_instance)
|
|
||||||
ship_helm = helm_location_marker.get_node("ShipHelm") # Assuming "ShipHelm" is the node name
|
|
||||||
|
|
||||||
func _on_property_update(uuid: String, property_name: String, value: Variant):
|
|
||||||
if NetworkManager.node_map.has(uuid):
|
|
||||||
var node = NetworkManager.node_map[uuid]
|
|
||||||
|
|
||||||
if property_name == "global_position":
|
|
||||||
_handle_ship_sync_position(value)
|
|
||||||
elif property_name == "global_rotation":
|
|
||||||
_handle_ship_sync_rotation(value)
|
|
||||||
elif property_name == "ship_is_piloted":
|
|
||||||
ship_is_piloted = value
|
|
||||||
elif property_name == "piloting_player":
|
|
||||||
if value != "":
|
|
||||||
# Find the Player object based on the network_uuid
|
|
||||||
for child in get_parent().get_children():
|
|
||||||
if child is Player and child.network_uuid == value:
|
|
||||||
piloting_player = child
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
piloting_player = null
|
|
||||||
else:
|
|
||||||
node.set(property_name, value)
|
|
||||||
else:
|
|
||||||
printerr("Received property update but node_id is wrong? Expected " + str(uuid) + " but got " + str(uuid))
|
|
||||||
|
|
||||||
func _sync_piloting_state():
|
|
||||||
NetworkManager.sync_property(network_uuid, "ship_is_piloted", ship_is_piloted)
|
|
||||||
if piloting_player != null:
|
|
||||||
NetworkManager.sync_property(network_uuid, "piloting_player", piloting_player.network_uuid)
|
|
||||||
else:
|
|
||||||
NetworkManager.sync_property(network_uuid, "piloting_player", "")
|
|
||||||
|
|
||||||
func _send_ship_sync():
|
|
||||||
if Time.get_ticks_msec() - last_sync_time > sync_interval * 1000:
|
|
||||||
last_sync_time = Time.get_ticks_msec()
|
|
||||||
NetworkManager.sync_property(network_uuid, "global_position", global_position)
|
NetworkManager.sync_property(network_uuid, "global_position", global_position)
|
||||||
NetworkManager.sync_property(network_uuid, "global_rotation", global_rotation)
|
previous_position = global_position
|
||||||
NetworkManager.sync_property(network_uuid, "linear_velocity", linear_velocity)
|
|
||||||
NetworkManager.sync_property(network_uuid, "angular_velocity", angular_velocity)
|
|
||||||
|
|
||||||
func _handle_ship_sync_position(pos: Vector3):
|
var current_rotation = global_transform.basis.get_rotation_quaternion()
|
||||||
if piloting_player and not piloting_player.is_network_authority:
|
if current_rotation != previous_rotation:
|
||||||
# Correct prediction with server data
|
NetworkManager.sync_property(network_uuid, "global_rotation", current_rotation)
|
||||||
var correction_threshold = 0.5 # Adjust based on your desired tolerance
|
previous_rotation = current_rotation
|
||||||
if (pos - global_position).length() > correction_threshold:
|
|
||||||
position_correction = pos
|
|
||||||
|
|
||||||
func _handle_ship_sync_rotation(rot: Vector3):
|
func interpolate_position_and_rotation(delta: float):
|
||||||
if piloting_player and not piloting_player.is_network_authority:
|
global_position = lerp(global_position, target_position, acceleration * delta)
|
||||||
var correction_threshold = 0.1 # Adjust based on your desired tolerance
|
var current_rotation = global_transform.basis.get_rotation_quaternion()
|
||||||
var received_rotation = Quaternion.from_euler(Vector3(rot.x, rot.y, rot.z))
|
var interpolated_rotation = current_rotation.slerp(target_rotation, acceleration * delta)
|
||||||
var delta_rot = received_rotation * global_rotation.inverse()
|
global_transform.basis = Basis(interpolated_rotation)
|
||||||
if delta_rot.length() > correction_threshold:
|
|
||||||
rotation_correction = rot
|
|
||||||
|
|
||||||
# Apply server rotation directly
|
func _on_property_update_received(node_id: String, property_name: String, value: Variant):
|
||||||
global_rotation = Quaternion.from_euler(rot).get_euler()
|
if node_id == network_uuid:
|
||||||
|
match property_name:
|
||||||
|
"global_position":
|
||||||
|
target_position = value
|
||||||
|
"global_rotation":
|
||||||
|
target_rotation = value
|
||||||
|
|
||||||
func _handle_position_correction(corrected_position: Vector3):
|
func set_piloting_player(player: Player):
|
||||||
if piloting_player and not piloting_player.is_network_authority:
|
piloting_player = player
|
||||||
predicted_position = corrected_position
|
ship_is_piloted = piloting_player != null
|
||||||
linear_velocity = (corrected_position - global_position) / delta_time
|
if piloting_player:
|
||||||
|
print("Player", piloting_player.username, "is now piloting the ship.")
|
||||||
|
else:
|
||||||
|
print("The ship is no longer piloted.")
|
||||||
|
|
||||||
func _handle_rotation_correction(corrected_rotation: Vector3):
|
|
||||||
if piloting_player and not piloting_player.is_network_authority:
|
|
||||||
var received_rotation = Quaternion.from_euler(corrected_rotation)
|
func remove_piloting_player():
|
||||||
var delta_rot = received_rotation * global_rotation.inverse()
|
piloting_player = null
|
||||||
predicted_rotation = received_rotation
|
ship_is_piloted = false
|
||||||
angular_velocity = Quaternion(delta_rot).get_euler() / delta_time
|
print("The ship is no longer piloted.")
|
||||||
|
|
||||||
# Apply server rotation directly
|
|
||||||
global_rotation = Quaternion.from_euler(corrected_rotation).get_euler()
|
|
Loading…
Reference in New Issue
Block a user