For my mod pawns can spin in the air alot and bounce when they hit the ground, but when they finally land I want them to always land on their feet, like a cat.
I've checked this code exhaustively and can't figure out what's wrong. Half the time when the pawn lands it just instantaneously snaps into upright position, the other half of the time it does some very quick rotating right before it lands, like it's attempting to rotate to upright position at the last second.
Any help is much appreciated. I've tried to comment as much as possible. The code applies a motion equation from basic physics, but on rotators. My (lack of) understanding rotator maths maybe the problem, but nothing on the wiki sticks out. Here is the relevant code:
P.S. I'm aware the code hasn't been optimized. It will be in the final version
I've checked this code exhaustively and can't figure out what's wrong. Half the time when the pawn lands it just instantaneously snaps into upright position, the other half of the time it does some very quick rotating right before it lands, like it's attempting to rotate to upright position at the last second.
Any help is much appreciated. I've tried to comment as much as possible. The code applies a motion equation from basic physics, but on rotators. My (lack of) understanding rotator maths maybe the problem, but nothing on the wiki sticks out. Here is the relevant code:
Code:
event ModifyVelocity(float DeltaTime, vector OldVelocity)
{
//Where custom rotation system is implemented because DesiredRotation
//doesn't work with PHYS_Falling
if(bIsSpinning)
{
//Drag, always wins out, notice how it's always opposite rotational velocity
rotAcceleration += InvertRot(rotVelocity, true) * rotDeAccelFactor;
//Dynamic Gravity, so you'll land on your feet
//Not sure if DeltaTime should be commented out but tried both ways and niether works.
rotAcceleration += GetCurrentRotGravity();// * DeltaTime;
//Update rotational velocity
rotVelocity += rotAcceleration * DeltaTime;
//Put the changes ingame
SetRotation(Rotation + (rotVelocity * DeltaTime));
}
}
//As pawn falls, roll and pitch approach 0, so player
//always lands on their feet. (in theory)
function rotator GetCurrentRotGravity()
{
local rotator rotGravity;
local vector HitLocation;
local vector HitNormal;
local float Displacement;
local float TimeToImpact;
local vector headPos;
local rotator standingRot;
rotGravity = rot(0,0,0);
//This is only for when pawns are falling
if(Velocity.Z >= 0)
{
return rot(0,0,0);
}
//Find how far away we are from the ground
Trace(HitLocation, HitNormal, Location + vect(0,0,-100000),, false);
//Location is just the center of the pawn. This is not the most likely
//part of the pawn to hit the ground first. So we subtract the collision
//height. If landing on head or feet, will work perfectly, if landing on
//side will get to standingRot a little early, insignificant.
headPos = vect(0,0,0);
headPos.Z = -CollisionHeight;
//Negative because the sign indicates the direction (down)
Displacement = -VSize(HitLocation - (Location+headPos));
//Test if the pawn will be going fast enough when it lands to trigger
//bouncing. If so hold off, we don't want them to land on their feet yet.
if(ShouldBounce(Displacement))
{
return rot(0,0,0);
}
//Rearranging of x=vi*t + .5*a*t^2, solving for x
//So it solves the quadratic: .5*PhysicsVolume.Gravity.Z*t^2 + Velocity.Z*t - Displacement
//It automatically throws out imaginary and negative answers and returns the one left.
//The log reports if both answers are negative or imaginary, but that never happens
TimeToImpact = PositiveRealQuadraticSolver(0.5*(PhysicsVolume.Gravity.Z), Velocity.Z, -Displacement);
//Standing just means pitch and roll have to be zero. Yaw could be anything
//so we make sure standingRot and Rotation's yaw are equal so it's ignored
standingRot = rot(0,0,0);
standingRot.Yaw = Rotation.Yaw;
//Based on rearranging x=vi*t + .5*a*t^2 where a = rotAcceleration + rotGravity
//So: Ag = 2*((xf-xi) - Vi*t)/(t^2) - A
rotGravity = (2*(standingRot - Rotation - rotVelocity*TimeToImpact)/(TimeToImpact ** 2)) - rotAcceleration;
return rotGravity;
}
P.S. I'm aware the code hasn't been optimized. It will be in the final version
Last edited: