I am doing a modification of Unreal Tournament 1999. Normally the game's jump pads' velocity applied to pawns that reach it's radius is defined by a velocity vector, which is a true pain to change and test and repeat this ad nauseum. (Mods please edit if I seem unclear.)
What I am trying to do is to simply set a position in space as destination (just an actor that already is part in the bot's AI pathing network, basically the destination marker) so that we don't need to manually specify that annoying KickVelocity variable.
This means I would need to find not only the horizontal direction (which I did) and put the result in the KickVelocity, I would also need to find the Z (height) part of the KickVelocity's height part would be.
It's not simply the relative height from the jump pad to the destination actor (I discovered that by trial and error) but it's actually the upwards velocity that makes the actor fly to the destination (if it's too low, he falls. If he goes too high, he goes far. Both means splat!) but I can't seem to determine it. Being $H$ the jump pad location, $I$ the destination location and $D^{H-I}$ the distance between jump pad and destination, I tried the formula $$V.Z = D^{H-I} * pi$$ but it don't seem to work, only resulting in a very high velocity downwards (instant splat).
What formula will determine the initial velocity's height part needed to reach $D$?
Edit: just in case, UnrealScript posted:
//=============================================================================
// EasyKicker2.
//=============================================================================
class EasyKicker2 expands LiftCenter;
var vector KickVelocity;
var(EasyKicker) name KickedClasses;
var(EasyKicker) bool bKillVelocity;
var(EasyKicker) bool bRandomize;
var(EasyKicker) name DestTag;
var(EasyKicker) float FineTuningFactor;
function PreBeginPlay()
{
local EasyKickerDest A;
local float Closest;
local float SQD;
local float NQD;
Closest = 0;
foreach AllActors(class'EasyKickerDest', A, DestTag)
{
NQD = VSize(A.Location - Location);
SQD = NQD ^ 2;
if ((SQD < Closest) || (Closest == 0))
{
Closest = SQD;
KickVelocity = A.Location - Location;
KickVelocity.Z = NQD * ((1 / (-950 / Level.ZoneGravity.Z)) * FineTuningFactor);
}
}
}
simulated function Touch( actor Other )
{
local Actor A;
if ( !Other.IsA(KickedClasses) )
return;
PendingTouch = Other.PendingTouch;
Other.PendingTouch = self;
if( Event != '' )
foreach AllActors( class 'Actor', A, Event )
A.Trigger( Other, Other.Instigator );
}
simulated function PostTouch( actor Other )
{
local bool bWasFalling;
local vector Push;
local float PMag;
bWasFalling = ( Other.Physics == PHYS_Falling );
if ( bKillVelocity )
Push = -1 * Other.Velocity;
else
Push.Z = -1 * Other.Velocity.Z;
if ( bRandomize )
{
PMag = VSize(KickVelocity);
Push += PMag * Normal(KickVelocity + 0.5 * PMag * VRand());
}
else
Push += KickVelocity;
if ( Bot(Other) != None )
{
if ( bWasFalling )
Bot(Other).bJumpOffPawn = true;
Bot(Other).SetFall();
}
Other.SetPhysics(PHYS_Falling);
Other.Velocity += Push;
}
I'll try to answer the question, although there are still some details missing in the description. Let's say we have an initial velocity vector $$V_0 = \begin{pmatrix} V_x(0) \\ V_y(0) \\ V_z(0) \\ \end{pmatrix}.$$ If $R(t)$ is the position vector as a function of time, we get $$R(t) = \begin{pmatrix} V_x(0)t + R_x(0) \\ V_y(0)t + R_y(0) \\ R_z(0) + V_z(0)t - \frac{g}{2}t^2\end{pmatrix}$$ Now lets say the target where we want to land is given by the vector $T$ and we're landing there at some time $t_0$. This leads to the equations
$$R(t_0) = \begin{pmatrix} V_x(0)t_0 + R_x(0) \\ V_y(0)t_0 + R_y(0) \\ R_z(0) + V_z(0)t_0 - \frac{g}{2}t_0^2\end{pmatrix} = \begin{pmatrix} T_x \\ T_y \\ T_z \end{pmatrix}$$
Now you can express $t_0$ with one of the $x$ or $y$ equations and plug it into the third one giving$$ V_z(0) = \frac{T_z - R_z(0)}{t_0} + \frac{gt_0}{2}$$ where
$$t_0 = \frac{T_x - R_x(0)}{V_x(0)}$$