using Godot; using RustyOptions; namespace Movementtests.systems; public partial class MantleSystem: Node3D { [Export(PropertyHint.Range, "0,2,0.1,suffix:m,or_greater")] public float MantleEndLocationDistanceFromWall { get; set; } = 1f; [Export(PropertyHint.Range, "0,10,0.1,suffix:m,or_greater")] public float MantleHeightCastStart { get; set; } = 2f; [Export(PropertyHint.Range, "0,10,0.01,suffix:m,or_greater")] public float MaxStepHeight = 0.5f; private Node3D _head; private ShapeCast3D _wallInFrontCast3D; private ShapeCast3D _mantleCast3D; private RayCast3D _mantleCheckCast3D; private Option _mantleLocation; public void Init(Node3D head) { _head = head; _wallInFrontCast3D = GetNode("WallInFrontCast3D"); _mantleCast3D = GetNode("MantleCast3D"); } public override void _PhysicsProcess(double delta) { base._PhysicsProcess(delta); _wallInFrontCast3D.SetRotation(new Vector3( _wallInFrontCast3D.Rotation.X, _head.Rotation.Y, _wallInFrontCast3D.Rotation.Z)); if (!_wallInFrontCast3D.IsColliding()) { _mantleLocation = Option.None; return; } var collisionPoint = _wallInFrontCast3D.GetCollisionPoint(0); var collisionNormal = _wallInFrontCast3D.GetCollisionNormal(0); _mantleLocation = FindMantleLocationAtPoint(collisionPoint, collisionNormal); } public Option FindMantleInFrontOfPlayer() { return _mantleLocation; } public Option FindMantleLocationAtPoint(Vector3 point, Vector3 wallNormal) { var horizontalEndLocation = point - wallNormal * MantleEndLocationDistanceFromWall; var shapeCastStartLocation = horizontalEndLocation + Vector3.Up * MantleHeightCastStart; _mantleCast3D.SetGlobalPosition(shapeCastStartLocation); var targetLocation = Vector3.Down * MantleHeightCastStart; _mantleCast3D.SetTargetPosition(targetLocation); if (_mantleCast3D.IsColliding() && _mantleCast3D.GetCollisionNormal(0).Y > 0.9f) return Option.Some(_mantleCast3D.GetCollisionPoint(0)); return Option.None; } }