Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function int ProjectileIntercept(int stid, int ttid, int spd, int ptid)
- {
- /* stid is the shooter tid, ttid is the target tid, spd is the speed of the projectile in fixed point, ptid is the tid the projectile will have */
- int t, last_t, sml_t, n, diff, lastdiff, smldiff, check;
- int a, b, c, t1, t2;
- int sX = GetActorX(stid);
- int sY = GetActorY(stid);
- int sZ = GetActorZ(stid);
- int tX = GetActorX(ttid);
- int tY = GetActorY(ttid);
- int tZ = GetActorZ(ttid);
- //tZ = tZ + 26.5; This was just here for comparison with Thing_ProjectileIntercept, which fires above the target's Z approximately 26.5 map units.
- int tVelX = GetActorVelX(ttid);
- int tVelY = GetActorVelY(ttid);
- int tVelZ = GetActorVelZ(ttid);
- //Triangle STI, where S is shooter position, T is target position and I is where the target and fired projectile will intercept
- int S_T_len = FixedSqrt(sq(sX - tX) + sq(sY - tY) + sq(sZ - tZ)); //Distance between shooter and target, or S_T
- int tVel_len = FixedSqrt(sq(tVelX) + sq(tVelY) + sq(tVelZ)); //Vector length for the shooter's velocity
- int alg_dot_STI = FixedMul(sX-tX, tVelX) + FixedMul(sY-tY, tVelY) + FixedMul(sZ-tZ, tVelZ); /* The algebraic dot product, which is:
- //log(s: "alg_dot_STI:", f: alg_dot_STI);
- http://en.wikipedia.org/wiki/Dot_product
- http://math.oregonstate.edu/home/programs/undergrad/CalculusQuestStudyGuides/vcalc/dotprod/dotprod.html
- Vector0 * Vector1 =
- [x0,y0,z0] * [x1,y1,z1] =
- (x0 * x1) + (y0 * y1) + (z0 * z1)
- which is equal to the geometric dot product, which is:
- Vector0 * Vector1 =
- |V0| * |V1| * cos(θ) where θ is the angle between the vectors and |x| denotes "length of x"
- so
- sqrt(x0*x0 + y0*y0 + z0*z0) * sqrt(x1*x1 + y1*y1 + z1*z1) * cos(θ) = (x0 * x1 ) + (y0 * y1) + (z0 * z1)
- so
- cos(θ) = [(x0 * x1 ) + (y0 * y1) + (z0 * z1)] / [sqrt(x0*x0 + y0*y0 + z0*z0) * sqrt(x1*x1 + y1*y1 + z1*z1)]
- */
- int cos_STI = FixedDiv(alg_dot_STI, FixedMul(S_T_len, tVel_len));
- /*
- Then using the Law of Cosines, which is:
- c*c = a*a + b*b - 2*a*b*cos(C), where a, b, and c are sides of a triangle and C is the angle opposite side c.
- in this case
- a = S_T = S_T_len | S_T_len = FixedSqrt(sq(sX - tX) + sq(sY - tY) + sq(sZ - tZ));
- b = T_I = target veloctiy * t = tVel_len * t | tVel_len = FixedSqrt(sq(tVelX) + sq(tVelY) + sq(tVelZ));
- c = S_I = projectile veloctiy * t = spd * t | function argument
- C = angle S_T_I = arccos(cos_STI) | cos_STI = FixedDiv(alg_dot_STI, FixedMul(S_T_len, tVel_len));
- where t is time to impact, in tics.
- We can then substitute
- c*c = a*a + b*b - 2*a*b*cos(C)
- (spd * t)*(spd * t) = (S_T_len)*(S_T_len) + (tVel_len * t)*(tVel_len * t) - 2*(S_T_len)*(tVel_len * t)*(cos_STI)
- set it equal to zero by subtracting from the left
- 0 = (S_T_len)*(S_T_len) + (tVel_len * t)*(tVel_len * t) - 2*(S_T_len)*(tVel_len * t)*(cos_STI) - (spd * t)*(spd * t)
- then factor for t
- 0 = (tVel_len * t)*(tVel_len * t) - (spd * t)*(spd * t) + (S_T_len)*(S_T_len) - 2*(S_T_len)*(tVel_len * t)*(cos_STI)
- 0 = (tVel_len * t)*(tVel_len * t) - (spd * t)*(spd * t) + (S_T_len)*(S_T_len) - 2*(S_T_len)*(tVel_len * t)*(cos_STI)
- 0 = (t*t)*(tVel_len)*(tVel_len) - (t*t)*(spd)*(spd) - (t)*2*(S_T_len)*(tVel_len)*(cos_STI) + (S_T_len)*(S_T_len)
- 0 = (t^2)*((tVel_len)*(tVel_len) - (spd)*(spd)) + (t)*(-2*(S_T_len)*(tVel_len)*(cos_STI)) + (S_T_len)*(S_T_len)
- since the expression is now in the form
- y = ax^2 + bx + c = 0
- we can use the quadratic formula
- [-b +/- sqrt(b^2 - 4*a*c)] / (2*a)
- to find when the two paths intersect
- to make it easier, isolate a, b, and c from the expression
- 0 = (t^2)*((tVel_len)*(tVel_len) - (spd)*(spd)) + (t)*(-2*(S_T_len)*(tVel_len)*(cos_STI)) + (S_T_len)*(S_T_len)
- a = (tVel_len)*(tVel_len) - (spd)*(spd)
- b = -2*(S_T_len)*(tVel_len)*(cos_STI)
- c = (S_T_len)*(S_T_len)
- */
- a = sq(tVel_len) - sq(spd);
- b = -2 * FixedMul(FixedMul(S_T_len, tVel_len), cos_STI);
- c = sq(S_T_len);
- t1 = FixedDiv( (-b + FixedSqrt(sq(b) - (4 * FixedMul(a,c)))) , (2 * a) );
- t2 = FixedDiv( (-b - FixedSqrt(sq(b) - (4 * FixedMul(a,c)))) , (2 * a) );
- log(s: "t1 = ", f: t1);
- log(s: "t2 = ", f: t2);
- /* in this case only positive values for t can be used, so */
- if(t1 > t2 && t1 > 0){ t = t1; }
- else if (t2 > 0){ t = t2; }
- else{ t = 99.0; }
- log(s: "t = ", f: t);
- int tVelX_t = FixedMul(t,tVelX);
- int tVelY_t = FixedMul(t,tVelY);
- int tVelZ_t = FixedMul(t,tVelZ);
- int tXf = tX + tVelX_t;
- int tYf = tY + tVelY_t;
- int tZf = tZ + tVelZ_t;
- int Z_spd = FixedDiv(tZf - sZ, t);
- int X_spd = FixedDiv(tXf - sX, t);
- int Y_spd = FixedDiv(tYf - sY, t);
- /* below is only used to have the firing actor be the firer of the projectile
- and allow assigning of a tid to that projectile */
- Thing_ProjectileIntercept (stid, 201, 0, ttid, ptid);
- SetActorAngle(ptid,VectorAngle(tXf - sX, tYf - sY));
- SetActorVelocity(ptid,X_spd,Y_spd,Z_spd,0,0);
- return t;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement