sasalka/Code/Player/Dedugan.cs
2025-05-25 19:14:50 +03:00

227 lines
7.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using Sandbox;
using Sandbox.Citizen;
using ShrimpleCharacterController;
public sealed class Dedugan : Component
{
[RequireComponent] public ShrimpleCharacterController.ShrimpleCharacterController Controller { get; set; }
[RequireComponent] public CitizenAnimationHelper AnimationHelper { get; set; }
public SkinnedModelRenderer Renderer { get; set; }
public GameObject Camera { get; set; }
[Property][Range(1f, 200f, 1f)] public float CamOffsetX { get; set; }
[Property] public GameObject CameraPivot { get; set; }
[Property] [Range(50f, 1200f, 10f)] public float WalkSpeed { get; set; } = 100f;
[Property] [Range(100f, 1500f, 20f)] public float RunSpeed { get; set; } = 300f;
[Property] [Range(25f, 1100f, 5f)] public float DuckSpeed { get; set; } = 50f;
[Property] [Range(200f, 1500f, 20f)] public float JumpStrength { get; set; } = 350f;
[Sync] public Angles NetworkedEyeAngles { get; set; } // для передачи углов другим клиентам
private RagdollController RagdollController { get; set; }
public Angles EyeAngles { get; set; }
public Vector3 OverrideGravity { get; set; } = Vector3.Zero;
private Vector3 _directionToAxis = Vector3.Up;
private Vector3 _up = Vector3.Up;
private Vector3 _forward = Vector3.Forward;
private Vector3 _right = Vector3.Right;
[Sync] private float IsDucking { get; set; } = 0f;
private Vector3 wishDirection;
protected override void OnStart()
{
base.OnStart();
RagdollController = Components.Get<RagdollController>();
Renderer = Components.Get<SkinnedModelRenderer>(FindMode.EverythingInSelfAndDescendants);
if (!Network.IsOwner) return;
// var cameraComponent = GameObject.GetComponentInParent<CameraComponent>(true, true) ;//new GameObject(true, "Camera");
var cameraComponent = Scene.Camera ;//new GameObject(true, "Camera");
Camera = cameraComponent.GameObject;
Camera.SetParent(GameObject);
// var cameraComponent = Camera.Components.Create<CameraComponent>();
cameraComponent.ZFar = 32768f;
cameraComponent.FieldOfView = 100f;
}
protected override void DrawGizmos()
{
base.DrawGizmos();
Gizmo.Transform = global::Transform.Zero;
Gizmo.Draw.LineThickness = 2f;
Gizmo.Draw.IgnoreDepth = true;
Gizmo.Draw.Color = Color.Blue;
Gizmo.Draw.Arrow(WorldPosition, WorldPosition + (_up * 1200f));
Gizmo.Draw.Color = Color.Red;
Gizmo.Draw.Arrow(WorldPosition, WorldPosition + (_forward * 1200f));
Gizmo.Draw.Color = Color.Green;
Gizmo.Draw.Arrow(WorldPosition, WorldPosition + (_right * 1200f));
Gizmo.Draw.Color = Color.Black;
Gizmo.Draw.Arrow(WorldPosition, WorldPosition + (-_up * 100f));
Gizmo.Draw.Color = Color.Magenta;
Gizmo.Draw.Arrow(WorldPosition, WorldPosition + wishDirection * 10f);
var textStartPos = new Vector2(10f);
Gizmo.Draw.ScreenText($"IsOnGround: {Controller.IsOnGround}", textStartPos);
Gizmo.Draw.ScreenText($"IsSlipping: {Controller.IsSlipping}", textStartPos.WithY(30f));
Gizmo.Draw.ScreenText($"WishVelocity: {Controller.WishVelocity}", textStartPos.WithY(50f));
Gizmo.Draw.ScreenText($"Test: {Vector3.Dot(_right, _up)}", textStartPos.WithY(70f));
Gizmo.Draw.ScreenBiasedHalfCircle(WorldPosition, 3f);
}
protected override void OnFixedUpdate()
{
base.OnFixedUpdate();
if ( OverrideGravity == Vector3.Zero )
{
_directionToAxis = Vector3.VectorPlaneProject(WorldPosition, Vector3.Right).Normal;
}
else
{
_directionToAxis = OverrideGravity;
}
_up = -_directionToAxis;
_forward = Vector3.Right;
_right = Vector3.Cross(_up, _forward).Normal;
Controller.Up = _up;
Controller.VectorGravity = -_up * 850f;
if (Network.IsOwner)
{
LookAtSurfaceNormal(_up, _forward);
wishDirection = Input.AnalogMove.Normal * Rotation.FromYaw(EyeAngles.yaw) * WorldRotation;
var isDucking = Input.Down("Duck");
var isRunning = Input.Down("Run");
var wishSpeed = isDucking ? DuckSpeed :
isRunning ? RunSpeed : WalkSpeed;
var ragdollMul = RagdollController.Enabled ? 0f : 1f;
Controller.WishVelocity = wishDirection * wishSpeed * ragdollMul;
if (Input.Pressed("Jump") && Controller.IsOnGround)
{
Controller.Punch(-Controller.AppliedGravity.Normal * JumpStrength);
AnimationHelper?.TriggerJump();
}
if (!AnimationHelper.IsValid()) return;
IsDucking = Input.Down("Duck") ? 1f : 0f;
}
Controller.Move();
if (!AnimationHelper.IsValid()) return;
AnimationHelper.DuckLevel = IsDucking;
AnimationHelper.WithWishVelocity(Controller.WishVelocity);
AnimationHelper.WithVelocity(Controller.Velocity);
AnimationHelper.IsGrounded = Controller.IsOnGround;
}
private void LookAtSurfaceNormal(Vector3 up, Vector3 moveDirection)
{
var newRotation = Rotation.LookAt(moveDirection, up);
WorldRotation = Rotation.Lerp(WorldRotation, newRotation, Time.Delta * 10f);
}
protected override void OnUpdate()
{
base.OnUpdate();
if (Network.IsOwner)
{
EyeAngles += Input.AnalogLook;
EyeAngles = EyeAngles.WithPitch(MathX.Clamp(EyeAngles.pitch, -89f, 89f));
NetworkedEyeAngles = EyeAngles;
RotateCamera();
var targetRotation = Rotation.LookAt(Rotation.FromYaw(EyeAngles.yaw).Forward, -_directionToAxis);
var currentForward = Renderer.LocalRotation.Forward;
float angleDiff = currentForward.Angle(targetRotation.Forward);
if (angleDiff > 15f && Controller.Velocity.Length > 10f)
{
Renderer.LocalRotation = Rotation.Slerp(Renderer.LocalRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 3f);
}
if ( Input.Pressed( "Use" ) )
{
var tr = Scene.Trace
.Ray( Camera.WorldPosition, Camera.WorldPosition + Camera.WorldRotation.Forward * 500f ).IgnoreGameObjectHierarchy(GameObject).Run();
if ( tr.Hit)
{
tr.GameObject.GetComponent<IInteractable>()?.OnUse();
}
}
}
else
{
EyeAngles = NetworkedEyeAngles;
Renderer.LocalRotation = Rotation.Slerp(Renderer.LocalRotation, Rotation.FromYaw(EyeAngles.yaw), Time.Delta * 5f);
}
}
void RotateCamera()
{
var cameraOffset = CameraPivot.LocalPosition + CameraPivot.LocalRotation.Backward * (CamOffsetX + EyeAngles.pitch * .5f);
Camera.LocalRotation = EyeAngles.ToRotation();
Camera.LocalPosition = cameraOffset * Camera.LocalRotation;
}
// void RotateCamera()
// {
// // 1. Задание локального вращения камеры
// Rotation camRot = EyeAngles.ToRotation();
// Camera.LocalRotation = camRot;
//
// // 2. Позиция Pivot'а в мире (нужно для трейса)
// var pivotWorldPos = CameraPivot.LocalPosition;
//
// // 3. Смещение плеча (локально → в мир)
// var shoulderOffsetWorld = Vector3.Zero;
//
// // 4. Желаемая мировая позиция камеры
// var desiredWorldPos = pivotWorldPos - camRot.Forward * 10f + shoulderOffsetWorld;
//
// // 5. Трейс от Pivot до желаемой позиции камеры
// var tr = Scene.Trace
// .Ray(pivotWorldPos, desiredWorldPos)
// .Radius(4f)
// .IgnoreGameObjectHierarchy(GameObject)
// .Run();
//
// // 6. Получаем локальную позицию относительно CameraPivot
// var finalWorldCamPos = tr.EndPosition;
// var finalLocalCamPos = CameraPivot.Transform.WorldToLocal.Transform(finalWorldCamPos);
//
// // 7. Применяем к камере
// Camera.LocalPosition = finalLocalCamPos;
// Camera.LocalRotation = camRot;
// }
}