136 lines
5.2 KiB
C#
136 lines
5.2 KiB
C#
using Godot;
|
|
using Movementtests.interfaces;
|
|
|
|
namespace Movementtests.systems;
|
|
|
|
[GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_wind.png")]
|
|
public partial class DashSystem: Node3D
|
|
{
|
|
public record DashLocation(bool HasHit, Vector3 TargetLocation, Vector3 CollisionPoint, Vector3 CollisionNormal, GodotObject HitObject = null);
|
|
|
|
|
|
[Export(PropertyHint.Range, "0,0.2,0.01,or_greater")]
|
|
public float DashSpeed { get; set; } = 0.1f;
|
|
[Export(PropertyHint.Range, "0,1000,1,or_greater")]
|
|
public float PostDashSpeed { get; set; } = 0f;
|
|
|
|
public bool HasHit { get; set; }
|
|
public bool CanDashThroughTarget { get; set; }
|
|
public Vector3 TargetLocation { get; set; }
|
|
public Vector3 CollisionPoint { get; set; }
|
|
public Vector3 CollisionNormal { get; set; }
|
|
public GodotObject? CollidedObject { get; set; }
|
|
public Vector3 PlannedLocation { get; set; }
|
|
|
|
public bool ShouldMantle { get; set; }
|
|
public Vector3 PlannedMantleLocation { get; set; }
|
|
public MantleSystem MantleSystem { get; set; } = null!;
|
|
|
|
internal HeadSystem Head = null!;
|
|
public ShapeCast3D DashCast3D = null!;
|
|
internal Camera3D Camera = null!;
|
|
internal Vector3 DashDirection = Vector3.Zero;
|
|
|
|
internal ShapeCast3D DashCastDrop = null!;
|
|
internal MeshInstance3D DashDropIndicator = null!;
|
|
internal MeshInstance3D DashDropLocationIndicator = null!;
|
|
internal MeshInstance3D DashTarget = null!;
|
|
internal CpuParticles3D DashIndicator = null!;
|
|
internal AnimationPlayer DashIndicatorAnim = null!;
|
|
|
|
[Export] public PackedScene DashIndicatorScene { get; set; } = null!;
|
|
|
|
[Signal]
|
|
public delegate void DashStartedEventHandler();
|
|
[Signal]
|
|
public delegate void DashEndedEventHandler();
|
|
[Signal]
|
|
public delegate void DashProgressEventHandler(float progress);
|
|
|
|
private Vector3 _globalDashPosition = Vector3.Zero;
|
|
|
|
public float DashCastRadius { get; set; }
|
|
|
|
public void Init(HeadSystem head, Camera3D camera)
|
|
{
|
|
DashCast3D = GetNode<ShapeCast3D>("DashCast3D");
|
|
var dashShape = DashCast3D.GetShape() as SphereShape3D;
|
|
DashCastRadius = dashShape!.Radius;
|
|
|
|
DashCastDrop = GetNode<ShapeCast3D>("DashCastDrop");
|
|
DashDropIndicator = GetNode<MeshInstance3D>("DashDropIndicator");
|
|
DashDropIndicator.Visible = false;
|
|
DashDropLocationIndicator = GetNode<MeshInstance3D>("DashDropLocationIndicator");
|
|
DashDropLocationIndicator.Visible = false;
|
|
|
|
Head = head;
|
|
Camera = camera;
|
|
|
|
MantleSystem = GetNode<MantleSystem>("MantleSystem");
|
|
MantleSystem.Init();
|
|
|
|
DashTarget = GetNode<MeshInstance3D>("DashTarget");
|
|
DashTarget.SetVisible(false);
|
|
DashIndicator = GetNode<CpuParticles3D>("DashIndicator");
|
|
DashIndicatorAnim = GetNode<AnimationPlayer>("DashIndicator/AnimationPlayer");
|
|
}
|
|
|
|
internal DashLocation ComputeDashLocation()
|
|
{
|
|
var targetLocation = DashCast3D.ToGlobal(DashCast3D.TargetPosition);
|
|
var hasHit = DashCast3D.IsColliding();
|
|
if (!hasHit)
|
|
{
|
|
return new DashLocation(false, targetLocation, Vector3.Zero, Vector3.Zero);
|
|
}
|
|
|
|
var collisionPoint = DashCast3D.GetCollisionPoint(0);
|
|
var collisionNormal = DashCast3D.GetCollisionNormal(0);
|
|
var collidedObject = DashCast3D.GetCollider(0);
|
|
|
|
var fraction = DashCast3D.GetClosestCollisionSafeFraction();
|
|
var globalSweepPath = targetLocation - DashCast3D.GlobalPosition;
|
|
var locationAlongPath = DashCast3D.GlobalPosition + globalSweepPath * fraction;
|
|
return new DashLocation(true, locationAlongPath, collisionPoint, collisionNormal, collidedObject);
|
|
}
|
|
|
|
public void PrepareDash()
|
|
{
|
|
DashCast3D.SetRotation(Head.GetGlobalLookRotation());
|
|
|
|
(HasHit, PlannedLocation, CollisionPoint, CollisionNormal, CollidedObject) = ComputeDashLocation();
|
|
CanDashThroughTarget = false;
|
|
if (CollidedObject is ITargetable)
|
|
{
|
|
DashTarget.SetVisible(false);
|
|
CanDashThroughTarget = true;
|
|
return;
|
|
}
|
|
|
|
MantleSystem.SetGlobalPosition(PlannedLocation);
|
|
MantleSystem.SetRotation(new Vector3(
|
|
MantleSystem.Rotation.X,
|
|
Head.Rotation.Y,
|
|
MantleSystem.Rotation.Z));
|
|
MantleSystem.ProcessMantle(false);
|
|
ShouldMantle = MantleSystem.IsMantlePossible;
|
|
|
|
// Setup dash target
|
|
var targetColor = HasHit ? new Color(1f, 0.2f, 0.2f) : new Color(1f, 1f, 1f);
|
|
targetColor = ShouldMantle ? new Color(0.2f, 0.2f, 1f) : targetColor;
|
|
var targetMaterial = (StandardMaterial3D) DashTarget.GetSurfaceOverrideMaterial(0);
|
|
targetMaterial.SetAlbedo(targetColor);
|
|
DashTarget.SetVisible(true);
|
|
var targetLocation = ShouldMantle ? MantleSystem.FirstMantleProfilePoint : PlannedLocation;
|
|
DashTarget.SetGlobalPosition(targetLocation);
|
|
}
|
|
|
|
public void StopPreparingDash()
|
|
{
|
|
CanDashThroughTarget = false;
|
|
DashTarget.SetVisible(false);
|
|
DashDropIndicator.SetVisible(false);
|
|
DashDropLocationIndicator.SetVisible(false);
|
|
}
|
|
}
|