using Godot; using System.Collections; using System.Collections.Generic; using Godot.Collections; namespace Rokojori { [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/CCMoveAndSlide.svg")] public partial class MoveAndSlide:CharacterControllerAction { [Export] public bool useStepping = false; [Export] public float stepMaxHeight = 0.2f; protected override void _OnTrigger() { var body = controller.body; var motion = controller.body.Velocity * controller.delta; var collision = body.MoveAndCollide( motion, testOnly: true ); if ( collision != null && StepUp( motion ) ) { return; } controller.body.MoveAndSlide(); } protected bool StepUp( Vector3 motion ) { var up = Vector3.Up * stepMaxHeight; var hitAbove = controller.body.TestMove( controller.body.GlobalTransform, up ); if ( hitAbove ) { return false; } bool hitForward = controller.body.TestMove( controller.body.GlobalTransform.Translated( up ), motion ); if ( ! hitForward ) { var space = controller.body.GetWorld3D().DirectSpaceState; var origin = controller.body.GlobalPosition; var stepUpOrigin = controller.body.GlobalPosition + up; var downHit = space.IntersectRay( new PhysicsRayQueryParameters3D { From = stepUpOrigin, To = stepUpOrigin + Vector3.Down * ( stepMaxHeight + 0.1f ), CollisionMask = 1, CollideWithAreas = false, CollideWithBodies = true } ); if ( downHit.Count == 0 ) { return false; } var exactStepAmount = downHit[ "position" ].AsVector3().Y - origin.Y; if ( exactStepAmount > 0 && exactStepAmount <= stepMaxHeight ) { controller.body.GlobalTranslate( new Vector3( 0, exactStepAmount, 0 ) ); return true; } } return false; } } }