codemp/game/g_exphysics.c File Reference

#include "g_local.h"

Go to the source code of this file.

Defines

#define MAX_GRAVITY_PULL   512

Functions

void G_RunExPhys (gentity_t *ent, float gravity, float mass, float bounce, qboolean autoKill, int *g2Bolts, int numG2Bolts)


Define Documentation

#define MAX_GRAVITY_PULL   512
 

Definition at line 16 of file g_exphysics.c.

Referenced by G_RunExPhys().


Function Documentation

void G_RunExPhys gentity_t ent,
float  gravity,
float  mass,
float  bounce,
qboolean  autoKill,
int *  g2Bolts,
int  numG2Bolts
 

Definition at line 21 of file g_exphysics.c.

References trace_t::allsolid, entityState_s::apos, gentity_s::clipmask, Com_Printf(), entityShared_t::currentOrigin, trace_t::endpos, trace_t::entityNum, ENTITYNUM_NONE, gentity_s::epGravFactor, gentity_s::epVelocity, trace_t::fraction, g_entities, G_FreeEntity(), G_SetOrigin(), gentity_t, gentity_s::ghoul2, entityState_s::groundEntityNum, level, MAX_GRAVITY_PULL, entityShared_t::maxs, entityShared_t::mins, gentity_s::modelScale, gentity_s::nextthink, cplane_s::normal, NULL, entityState_s::number, ORIGIN, PITCH, trace_t::plane, qboolean, qfalse, qtrue, gentity_s::r, ROLL, gentity_s::s, trace_t::startsolid, gentity_s::think, level_locals_t::time, gentity_s::touch, trap_G2API_GetBoltMatrix(), trap_LinkEntity(), trap_Trace(), trajectory_t::trBase, vec3_t, VectorAdd, VectorClear, VectorCopy, VectorMA, VectorNormalize(), VectorScale, VectorSet, VectorSubtract, and YAW.

Referenced by EWebThink(), faller_think(), G_RunFrame(), LimbThink(), SiegeItemThink(), and SpecialItemThink().

00022 {
00023         trace_t tr;
00024         vec3_t projectedOrigin;
00025         vec3_t vNorm;
00026         vec3_t ground;
00027         float velScaling = 0.1f;
00028         float vTotal = 0.0f;
00029 
00030         assert(mass <= 1.0f && mass >= 0.01f);
00031 
00032         if (gravity)
00033         { //factor it in before we do anything.
00034                 VectorCopy(ent->r.currentOrigin, ground);
00035                 ground[2] -= 0.1f;
00036 
00037                 trap_Trace(&tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ground, ent->s.number, ent->clipmask);
00038 
00039                 if (tr.fraction == 1.0f)
00040                 {
00041                         ent->s.groundEntityNum = ENTITYNUM_NONE;
00042                 }
00043                 else
00044                 {
00045                         ent->s.groundEntityNum = tr.entityNum;
00046                 }
00047 
00048                 if (ent->s.groundEntityNum == ENTITYNUM_NONE)
00049                 {
00050                         ent->epGravFactor += gravity;
00051 
00052                         if (ent->epGravFactor > MAX_GRAVITY_PULL)
00053                         { //cap it off if needed
00054                                 ent->epGravFactor = MAX_GRAVITY_PULL;
00055                         }
00056 
00057                         ent->epVelocity[2] -= ent->epGravFactor;
00058                 }
00059                 else
00060                 { //if we're sitting on something then reset the gravity factor.
00061                         ent->epGravFactor = 0;
00062                 }
00063         }
00064 
00065         if (!ent->epVelocity[0] && !ent->epVelocity[1] && !ent->epVelocity[2])
00066         { //nothing to do if we have no velocity even after gravity.
00067                 if (ent->touch)
00068                 { //call touch if we're in something
00069                         trap_Trace(&tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, ent->r.currentOrigin, ent->s.number, ent->clipmask);
00070                         if (tr.startsolid || tr.allsolid)
00071                         {
00072                                 ent->touch(ent, &g_entities[tr.entityNum], &tr);
00073                         }
00074                 }
00075                 return;
00076         }
00077 
00078         //get the projected origin based on velocity.
00079         VectorMA(ent->r.currentOrigin, velScaling, ent->epVelocity, projectedOrigin);
00080 
00081         VectorScale(ent->epVelocity, 1.0f-mass, ent->epVelocity); //scale it down based on mass
00082 
00083         VectorCopy(ent->epVelocity, vNorm);
00084         vTotal = VectorNormalize(vNorm);
00085 
00086         if (vTotal < 1 && ent->s.groundEntityNum != ENTITYNUM_NONE)
00087         { //we've pretty much stopped moving anyway, just clear it out then.
00088                 VectorClear(ent->epVelocity);
00089                 ent->epGravFactor = 0;
00090                 trap_LinkEntity(ent);
00091                 return;
00092         }
00093 
00094         if (ent->ghoul2 && g2Bolts)
00095         { //Have we been passed a bolt index array to clip against points on the skeleton?
00096                 vec3_t tMins, tMaxs;
00097                 vec3_t trajDif;
00098                 vec3_t gbmAngles;
00099                 vec3_t boneOrg;
00100                 vec3_t projectedBoneOrg;
00101                 vec3_t collisionRootPos;
00102                 mdxaBone_t matrix;
00103                 trace_t bestCollision;
00104                 qboolean hasFirstCollision = qfalse;
00105                 int i = 0;
00106 
00107                 //Maybe we could use a trap call and get the default radius for the bone specified,
00108                 //but this will do at least for now.
00109                 VectorSet(tMins, -3, -3, -3);
00110                 VectorSet(tMaxs, 3, 3, 3);
00111 
00112                 gbmAngles[PITCH] = gbmAngles[ROLL] = 0;
00113                 gbmAngles[YAW] = ent->s.apos.trBase[YAW];
00114 
00115                 //Get the difference relative to the entity origin and projected origin, to add to each bolt position.
00116                 VectorSubtract(ent->r.currentOrigin, projectedOrigin, trajDif);
00117         
00118                 while (i < numG2Bolts)
00119                 {
00120                         //Get the position of the actual bolt for this frame
00121                         trap_G2API_GetBoltMatrix(ent->ghoul2, 0, g2Bolts[i], &matrix, gbmAngles, ent->r.currentOrigin, level.time, NULL, ent->modelScale);
00122                         BG_GiveMeVectorFromMatrix(&matrix, ORIGIN, boneOrg);
00123 
00124                         //Now add the projected positional difference into the result
00125                         VectorAdd(boneOrg, trajDif, projectedBoneOrg);
00126 
00127                         trap_Trace(&tr, boneOrg, tMins, tMaxs, projectedBoneOrg, ent->s.number, ent->clipmask);
00128 
00129                         if (tr.fraction != 1.0 || tr.startsolid || tr.allsolid)
00130                         { //we've hit something
00131                                 //Store the "deepest" collision we have
00132                 if (!hasFirstCollision)
00133                                 { //don't have one yet so just use this one
00134                                         bestCollision = tr;
00135                                         VectorCopy(boneOrg, collisionRootPos);
00136                                         hasFirstCollision = qtrue;
00137                                 }
00138                                 else
00139                                 {
00140                                         if (tr.allsolid && !bestCollision.allsolid)
00141                                         { //If the whole trace is solid then this one is deeper
00142                                                 bestCollision = tr;
00143                                                 VectorCopy(boneOrg, collisionRootPos);
00144                                         }
00145                                         else if (tr.startsolid && !bestCollision.startsolid && !bestCollision.allsolid)
00146                                         { //Next deepest is if it's startsolid
00147                                                 bestCollision = tr;
00148                                                 VectorCopy(boneOrg, collisionRootPos);
00149                                         }
00150                                         else if (!bestCollision.startsolid && !bestCollision.allsolid &&
00151                                                 tr.fraction < bestCollision.fraction)
00152                                         { //and finally, if neither is startsolid/allsolid, but the new one has a smaller fraction, then it's closer to an impact point so we will use it
00153                                                 bestCollision = tr;
00154                                                 VectorCopy(boneOrg, collisionRootPos);
00155                                         }
00156                                 }
00157                         }
00158 
00159                         i++;
00160                 }
00161 
00162                 if (hasFirstCollision)
00163                 { //at least one bolt collided
00164                         //We'll get the offset between the collided bolt and endpos, then trace there
00165                         //from the origin so that our desired position becomes that point.
00166                         VectorSubtract(collisionRootPos, bestCollision.endpos, trajDif);
00167 
00168                         VectorAdd(ent->r.currentOrigin, trajDif, projectedOrigin);
00169                 }
00170         }
00171 
00172         //If we didn't collide with any bolts projectedOrigin will still be the original desired
00173         //projected position so all is well. If we did then projectedOrigin will be modified
00174         //to provide us with a relative position which does not place the bolt in a solid.
00175         trap_Trace(&tr, ent->r.currentOrigin, ent->r.mins, ent->r.maxs, projectedOrigin, ent->s.number, ent->clipmask);
00176 
00177         if (tr.startsolid || tr.allsolid)
00178         { //can't go anywhere from here
00179 #ifdef _DEBUG
00180                 Com_Printf("ExPhys object in solid (%i)\n", ent->s.number);
00181 #endif
00182                 if (autoKill)
00183                 {
00184                         ent->think = G_FreeEntity;
00185                         ent->nextthink = level.time;
00186                 }
00187                 return;
00188         }
00189 
00190         //Go ahead and set it to the trace endpoint regardless of what it hit
00191         G_SetOrigin(ent, tr.endpos);
00192         trap_LinkEntity(ent);
00193 
00194         if (tr.fraction == 1.0f)
00195         { //Nothing was in the way.
00196                 return;
00197         }
00198 
00199         if (bounce)
00200         {
00201                 vTotal *= bounce; //scale it by bounce
00202 
00203                 VectorScale(tr.plane.normal, vTotal, vNorm); //scale the trace plane normal by the bounce factor
00204 
00205                 if (vNorm[2] > 0)
00206                 {
00207                         ent->epGravFactor -= vNorm[2]*(1.0f-mass); //The lighter it is the more gravity will be reduced by bouncing vertically.
00208                         if (ent->epGravFactor < 0)
00209                         {
00210                                 ent->epGravFactor = 0;
00211                         }
00212                 }
00213 
00214                 //call touch first so we can check velocity upon impact if we want
00215                 if (tr.entityNum != ENTITYNUM_NONE && ent->touch)
00216                 { //then call the touch function
00217                         ent->touch(ent, &g_entities[tr.entityNum], &tr);
00218                 }
00219 
00220                 VectorAdd(ent->epVelocity, vNorm, ent->epVelocity); //add it into the existing velocity.
00221         }
00222         else
00223         { //if no bounce, kill when it hits something.
00224                 ent->epVelocity[0] = 0;
00225                 ent->epVelocity[1] = 0;
00226 
00227                 if (!gravity)
00228                 {
00229                         ent->epVelocity[2] = 0;
00230                 }
00231         }
00232 }