#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) |
|
|
Definition at line 16 of file g_exphysics.c. Referenced by G_RunExPhys(). |
|
||||||||||||||||||||||||||||||||
|
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 }
|