Files
voider/Scripts/Player/Player.cs

237 lines
6.7 KiB
C#

using EinSoftworks.Events;
using EinSoftworks.Input;
using EinSoftworks.Movement;
using Godot;
namespace Voider.Player;
public partial class Player : FirstPersonController
{
[Export]
public Label SpeedVal { get; set; }
[Export]
public Label StateVal { get; set; }
[Export]
public Label PositionVal { get; set; }
[Export]
public Label VelocityVal { get; set; }
private float _lastSpeed = 0f;
private float _lastDisplayedSpeed = 0f;
private Vector3 _lastDisplayedPosition;
private Vector3 _lastDisplayedVelocity;
private string _lastDisplayedState = "";
private const float UI_UPDATE_THRESHOLD = 0.1f;
public override void _Ready()
{
// InputManager is initialized by the library
InputManager = InputManager.Instance;
// Assign CameraNode from scene before calling base._Ready()
if (CameraNode == null)
{
CameraNode = GetNode<Node3D>("CameraMount");
}
// Set FOV and camera settings before base._Ready()
BaseFov = 75f;
MouseSensitivity = 0.35f;
ControllerSensitivity = 3.0f;
MinPitch = -89f;
MaxPitch = 89f;
EnableDebugOutput = true;
base._Ready();
// Try to find UI labels if they're not already assigned
// This allows the scene to work standalone or with external UI
if (SpeedVal == null || StateVal == null || PositionVal == null || VelocityVal == null)
{
// Try to find DebugHUD in the scene tree
var ui = GetNodeOrNull<Control>("/root/LibraryTest/UI/DebugHUD");
if (ui == null)
{
ui = GetNodeOrNull<Control>("/root/Main/UI/DebugHUD");
}
if (ui != null)
{
SpeedVal = ui.GetNodeOrNull<Label>("StatsPanel/VBoxContainerValues/SpeedVal");
StateVal = ui.GetNodeOrNull<Label>("StatsPanel/VBoxContainerValues/StateVal");
PositionVal = ui.GetNodeOrNull<Label>("StatsPanel/VBoxContainerValues/PositionVal");
VelocityVal = ui.GetNodeOrNull<Label>("StatsPanel/VBoxContainerValues/VelocityVal");
}
}
Config = new MovementConfig
{
// Base speeds (HL2-style)
MaxSpeed = 5f,
MaxSprintSpeed = 8f,
MaxWalkSpeed = 3f,
MaxCrouchSpeed = 2f,
Acceleration = 8f,
AirAcceleration = 1.5f,
AirSpeedCap = 8f,
AirControl = 0.3f,
Friction = 6f,
StopSpeed = 1f,
JumpVelocity = 5f,
Gravity = 15f,
// Bunny hopping with momentum preservation
EnableBunnyHopping = true,
EnableAutoHop = false,
BunnyHopSpeedMultiplier = 1.05f,
// Crouching
EnableCrouching = true,
CrouchHeight = 0.5f,
// Titanfall 2-style sliding
EnableSliding = true,
SlideSpeed = 10f,
SlideAcceleration = 15f,
SlideFriction = 3f,
SlideMinSpeed = 5f,
SlideJumpBoost = 1.2f,
SlideDuration = 1.2f,
EnableSurfing = true,
};
MouseSensitivity = 0.35f;
EnableDebugOutput = false;
#if DEBUG
GD.Print($"InputManager assigned: {InputManager != null}");
GD.Print($"CameraNode assigned: {CameraNode != null}");
GD.Print($"Config assigned: {Config != null}");
#endif
SubscribeToStateChanges(OnMovementStateChanged);
MovementEvents.PlayerJumped += OnPlayerJumped;
MovementEvents.SpeedChanged += OnSpeedChanged;
#if DEBUG
GD.Print("TestPlayer initialized with all libraries!");
GD.Print("- Movement: Enabled");
GD.Print("- Input: Enabled");
GD.Print("- Events: Enabled");
GD.Print("- StateManagement: Enabled");
GD.Print("- Camera: Enabled");
#endif
}
public override void _Process(double delta)
{
base._Process(delta);
UpdateUI();
}
private void UpdateUI()
{
if (SpeedVal != null && Mathf.Abs(CurrentSpeed - _lastDisplayedSpeed) > UI_UPDATE_THRESHOLD)
{
SpeedVal.Text = $"{CurrentSpeed:F1} u/s ";
_lastDisplayedSpeed = CurrentSpeed;
}
if (StateVal != null)
{
string state = "Unknown";
if (IsCrouching)
{
state = "Crouching";
}
else if (IsOnFloor())
{
if (WishDirection.LengthSquared() > 0.01f)
state = "Walking";
else
state = "Idle";
}
else
{
state = "Airborne";
}
if (state != _lastDisplayedState)
{
StateVal.Text = $"{state} ";
_lastDisplayedState = state;
}
}
if (PositionVal != null && GlobalPosition.DistanceSquaredTo(_lastDisplayedPosition) > UI_UPDATE_THRESHOLD)
{
PositionVal.Text =
$"({GlobalPosition.X:F1}, {GlobalPosition.Y:F1}, {GlobalPosition.Z:F1}) ";
_lastDisplayedPosition = GlobalPosition;
}
if (VelocityVal != null && Velocity.DistanceSquaredTo(_lastDisplayedVelocity) > UI_UPDATE_THRESHOLD)
{
VelocityVal.Text = $"({Velocity.X:F1}, {Velocity.Y:F1}, {Velocity.Z:F1}) ";
_lastDisplayedVelocity = Velocity;
}
}
private void OnMovementStateChanged(MovementStateChangedEvent evt)
{
#if DEBUG
GD.Print($"[Movement] State changed to: {evt.StateName} (Speed: {evt.Speed:F1})");
#endif
MovementEvents.RaiseStateChanged(evt.StateName);
}
private void OnPlayerJumped()
{
#if DEBUG
GD.Print($"[Event] Player jumped at speed: {CurrentSpeed:F1}");
#endif
}
private void OnSpeedChanged(float speed)
{
if (Mathf.Abs(speed - _lastSpeed) > 50f)
{
#if DEBUG
GD.Print($"[Event] Speed changed significantly: {_lastSpeed:F1} -> {speed:F1}");
#endif
_lastSpeed = speed;
}
}
public override void _Input(InputEvent @event)
{
base._Input(@event);
if (@event.IsActionPressed("ui_cancel"))
{
if (Godot.Input.MouseMode == Godot.Input.MouseModeEnum.Captured)
{
Godot.Input.MouseMode = Godot.Input.MouseModeEnum.Visible;
}
else
{
Godot.Input.MouseMode = Godot.Input.MouseModeEnum.Captured;
}
}
}
public override void _ExitTree()
{
MovementEvents.PlayerJumped -= OnPlayerJumped;
MovementEvents.SpeedChanged -= OnSpeedChanged;
base._ExitTree();
}
}