using System; using System.Linq; using NodeCanvas.Framework; using ParadoxNotion; using ParadoxNotion.Design; using UnityEngine; using UnityEngine.InputSystem; namespace NodeCanvas.Tasks.Actions { [Category("Reset/Actions")] public class Jump : ActionTask { public BBParameter jumpStrength; public BBParameter airMoveDirection; [Range(0f, 1f)] public BBParameter standStillJumpStrength; public BBParameter jumpPower; [Tooltip("Determines how much current movement vectors into jump direction")] public BBParameter currentVelocityInheritence; public BBParameter directionalForce; public BBParameter directionalForceStrength; protected override string info { get { return "Start Jump" ; } } //Use for initialization. This is called only once in the lifetime of the task. //Return null if init was successfull. Return an error string otherwise protected override string OnInit(){ return null; } //This is called once each time the task is enabled. //Call EndAction() to mark the action as finished, either in success or failure. //EndAction can be called from anywhere. protected override void OnExecute(){ // Set jump power jumpPower.value = jumpStrength.value; { /* // The following creates an air movement direction initially constructed from the agent's velocity, but also from subsequent jump inputs // // Create a vector 3 to hold velocity without jump power or gravity // Vector3 velocityWithoutY = new(agent.velocity.x, 0f, agent.velocity.z); // Vector3 jumpLeapVelocity = new (velocityWithoutY.x, velocityWithoutY.y, velocityWithoutY.z); // // float inputVelocityMagnitude = velocityWithoutY.magnitude; // float usableVelocity = 0f; // // // Ungrounded players can input a jump command to take their relative velcity as input for the new direction // if(!agent.isGrounded){ // // Get raw input direction // Vector3 playerInputVector3 = new(agent.GetComponent().rawMoveInput.x, 0f, agent.GetComponent().rawMoveInput.y); // // // Compare current velocity magnitude against jump strength. This is so air movement with no inherit velocity can be overidden by the new jump. // usableVelocity = Mathf.Abs(velocityWithoutY.magnitude - jumpStrength.value); // usableVelocity = Mathf.Max(usableVelocity, 0f); // usableVelocity /= jumpStrength.value; // // Debug.Log(usableVelocity); // // // Lerp between leaping and adding the full jump strenght, or adding a portion of it // Vector3 fullNewValueVelocity = agent.transform.rotation * playerInputVector3.normalized * jumpStrength.value; // Vector3 fullOriginalValueVelocity = velocityWithoutY; // // jumpLeapVelocity = Vector3.Lerp(fullNewValueVelocity, fullOriginalValueVelocity, 1f - usableVelocity); // } else { // // } // // // Add directional force, for things such as wall bounces // Vector3 directionalForceDirection = new Vector3(directionalForce.value.x, 0f, directionalForce.value.y); // jumpLeapVelocity += (agent.transform.rotation * directionalForce.value) * directionalForceStrength.value; // // // jumpLeapVelocity *= currentVelocityInheritence.value; // if (agent.isGrounded){ // jumpLeapVelocity = Vector3.ClampMagnitude(jumpLeapVelocity, velocityWithoutY.magnitude); // } else { // jumpLeapVelocity = Vector3.ClampMagnitude(jumpLeapVelocity, Mathf.Lerp(velocityWithoutY.magnitude, jumpStrength.value, usableVelocity)); // } // // // Debug.Log(jumpLeapVelocity); // // airMoveDirection.value = jumpLeapVelocity; */ } // Save current velocity and get current input direction Vector3 currentVelocityVector3 = new Vector3(agent.velocity.x, 0f, agent.velocity.z); Vector2 currentInput = agent.GetComponent().rawMoveInput; Vector3 currentInputVector3 = new(currentInput.x, 0f, currentInput.y); // Ignore rotation for the current velocity Vector3 currentVelocityWorld = agent.transform.InverseTransformDirection(currentVelocityVector3.normalized); // Get the dot product between current velocity's direction and current input (UNUSED FOR NOW) float velocityInputDot = Vector3.Dot(currentVelocityWorld, currentInputVector3); // Set air move direction if (agent.isGrounded) { airMoveDirection.value = currentVelocityVector3; } else { // Hold new desired air direction and Dot against the existing air moving directioin Vector3 desiredAirMoveDirection = currentInputVector3; float airMoveDirectionDot = Vector3.Dot(desiredAirMoveDirection.normalized, airMoveDirection.value.normalized); // Check threshold of current XZ velocity- if it's too close to zero, use the jumpStrength for jumping velocity. If it's not, use the current velocity float velocityThreshold = 4f; float magnitudeZeroDifference = Mathf.Clamp(currentVelocityVector3.magnitude - velocityThreshold, 0f, Mathf.Infinity) / velocityThreshold; // Divided by maximum to return a 0-1 value. Clamping not required. float outputVelocity = Mathf.Lerp(jumpStrength.value, currentVelocityVector3.magnitude, Math.Clamp(magnitudeZeroDifference, 0f, 1f)); outputVelocity = Mathf.Min(outputVelocity, Mathf.Lerp(standStillJumpStrength.value * jumpStrength.value, jumpStrength.value * .4f, magnitudeZeroDifference)); // Remap the dot to set -1 (opposing direction) to -.5f, and 1 (same direciton) to 1.2f // This is done to allow some sideways jumping direction change, but none backwards, and all forwards float remappedAirDirectionDot = Mathf.Lerp(.3f, 1.2f, airMoveDirectionDot); remappedAirDirectionDot = Mathf.Clamp(remappedAirDirectionDot, 0f, 1f); // Lerp between the current direction and the inputted direction based on the previous dot product Vector3 outputDirection = Vector3.Lerp(currentVelocityVector3.normalized, currentInputVector3.normalized, remappedAirDirectionDot); // If there is a direction force, lean into that based on it's strength outputDirection = Vector3.Lerp(outputDirection, directionalForce.value.normalized, directionalForceStrength.value).normalized; // Extra math to degrade current air move direction by velocity inheritence, before applying new air direction airMoveDirection.value *= currentVelocityInheritence.value; // Set air move direciton airMoveDirection.value += outputDirection * outputVelocity; } // Transform and apply rotatio agent.transform.rotation = Quaternion.LookRotation(airMoveDirection.value); EndAction(true); } //Called once per frame while the action is active. protected override void OnUpdate(){ } //Called when the task is disabled. protected override void OnStop() { } //Called when the task is paused. protected override void OnPause() { } } }