diff options
Diffstat (limited to 'src/baseq2/g_phys.c')
-rw-r--r-- | src/baseq2/g_phys.c | 491 |
1 files changed, 224 insertions, 267 deletions
diff --git a/src/baseq2/g_phys.c b/src/baseq2/g_phys.c index edc2837..61f8a2a 100644 --- a/src/baseq2/g_phys.c +++ b/src/baseq2/g_phys.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move. -onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects +onground is set for toss objects when they come to a complete rest. it is set for steping or walking objects doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS @@ -46,7 +46,7 @@ SV_TestEntityPosition ============ */ -edict_t *SV_TestEntityPosition (edict_t *ent) +edict_t *SV_TestEntityPosition(edict_t *ent) { trace_t trace; int mask; @@ -55,11 +55,11 @@ edict_t *SV_TestEntityPosition (edict_t *ent) mask = ent->clipmask; else mask = MASK_SOLID; - trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask); - + trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask); + if (trace.startsolid) return g_edicts; - + return NULL; } @@ -69,15 +69,14 @@ edict_t *SV_TestEntityPosition (edict_t *ent) SV_CheckVelocity ================ */ -void SV_CheckVelocity (edict_t *ent) +void SV_CheckVelocity(edict_t *ent) { int i; // // bound velocity // - for (i=0 ; i<3 ; i++) - { + for (i = 0 ; i < 3 ; i++) { if (ent->velocity[i] > sv_maxvelocity->value) ent->velocity[i] = sv_maxvelocity->value; else if (ent->velocity[i] < -sv_maxvelocity->value) @@ -92,20 +91,20 @@ SV_RunThink Runs thinking code for this frame if necessary ============= */ -qboolean SV_RunThink (edict_t *ent) +qboolean SV_RunThink(edict_t *ent) { float thinktime; thinktime = ent->nextthink; if (thinktime <= 0) return qtrue; - if (thinktime > level.time+0.001) + if (thinktime > level.time + 0.001) return qtrue; - + ent->nextthink = 0; if (!ent->think) - gi.error ("NULL ent->think"); - ent->think (ent); + gi.error("NULL ent->think"); + ent->think(ent); return qfalse; } @@ -117,7 +116,7 @@ SV_Impact Two entities have touched, so run their touch functions ================== */ -void SV_Impact (edict_t *e1, trace_t *trace) +void SV_Impact(edict_t *e1, trace_t *trace) { edict_t *e2; // cplane_t backplane; @@ -125,10 +124,10 @@ void SV_Impact (edict_t *e1, trace_t *trace) e2 = trace->ent; if (e1->touch && e1->solid != SOLID_NOT) - e1->touch (e1, e2, &trace->plane, trace->surface); - + e1->touch(e1, e2, &trace->plane, trace->surface); + if (e2->touch && e2->solid != SOLID_NOT) - e2->touch (e2, e1, NULL, NULL); + e2->touch(e2, e1, NULL, NULL); } @@ -142,23 +141,22 @@ returns the blocked flags (1 = floor, 2 = step / wall) */ #define STOP_EPSILON 0.1 -int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce) +int ClipVelocity(vec3_t in, vec3_t normal, vec3_t out, float overbounce) { float backoff; float change; int i, blocked; - + blocked = 0; if (normal[2] > 0) blocked |= 1; // floor if (!normal[2]) blocked |= 2; // step - - backoff = DotProduct (in, normal) * overbounce; - for (i=0 ; i<3 ; i++) - { - change = normal[i]*backoff; + backoff = DotProduct(in, normal) * overbounce; + + for (i = 0 ; i < 3 ; i++) { + change = normal[i] * backoff; out[i] = in[i] - change; if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) out[i] = 0; @@ -180,7 +178,7 @@ Returns the clipflags if the velocity was modified (hit something solid) ============ */ #define MAX_CLIP_PLANES 5 -int SV_FlyMove (edict_t *ent, float time, int mask) +int SV_FlyMove(edict_t *ent, float time, int mask) { edict_t *hit; int bumpcount, numbumps; @@ -194,117 +192,108 @@ int SV_FlyMove (edict_t *ent, float time, int mask) vec3_t end; float time_left; int blocked; - + numbumps = 4; - + blocked = 0; - VectorCopy (ent->velocity, original_velocity); - VectorCopy (ent->velocity, primal_velocity); + VectorCopy(ent->velocity, original_velocity); + VectorCopy(ent->velocity, primal_velocity); numplanes = 0; - + time_left = time; ent->groundentity = NULL; - for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++) - { - for (i=0 ; i<3 ; i++) + for (bumpcount = 0 ; bumpcount < numbumps ; bumpcount++) { + for (i = 0 ; i < 3 ; i++) end[i] = ent->s.origin[i] + time_left * ent->velocity[i]; - trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask); + trace = gi.trace(ent->s.origin, ent->mins, ent->maxs, end, ent, mask); - if (trace.allsolid) - { // entity is trapped in another solid - VectorCopy (vec3_origin, ent->velocity); + if (trace.allsolid) { + // entity is trapped in another solid + VectorCopy(vec3_origin, ent->velocity); return 3; } - if (trace.fraction > 0) - { // actually covered some distance - VectorCopy (trace.endpos, ent->s.origin); - VectorCopy (ent->velocity, original_velocity); + if (trace.fraction > 0) { + // actually covered some distance + VectorCopy(trace.endpos, ent->s.origin); + VectorCopy(ent->velocity, original_velocity); numplanes = 0; } if (trace.fraction == 1) - break; // moved the entire distance + break; // moved the entire distance hit = trace.ent; - if (trace.plane.normal[2] > 0.7) - { + if (trace.plane.normal[2] > 0.7) { blocked |= 1; // floor - if ( hit->solid == SOLID_BSP) - { + if (hit->solid == SOLID_BSP) { ent->groundentity = hit; ent->groundentity_linkcount = hit->linkcount; } } - if (!trace.plane.normal[2]) - { + if (!trace.plane.normal[2]) { blocked |= 2; // step } // // run the impact function // - SV_Impact (ent, &trace); + SV_Impact(ent, &trace); if (!ent->inuse) break; // removed by the impact function - + time_left -= time_left * trace.fraction; - - // cliped to another plane - if (numplanes >= MAX_CLIP_PLANES) - { // this shouldn't really happen - VectorCopy (vec3_origin, ent->velocity); + + // cliped to another plane + if (numplanes >= MAX_CLIP_PLANES) { + // this shouldn't really happen + VectorCopy(vec3_origin, ent->velocity); return 3; } - VectorCopy (trace.plane.normal, planes[numplanes]); + VectorCopy(trace.plane.normal, planes[numplanes]); numplanes++; // // modify original_velocity so it parallels all of the clip planes // - for (i=0 ; i<numplanes ; i++) - { - ClipVelocity (original_velocity, planes[i], new_velocity, 1); - - for (j=0 ; j<numplanes ; j++) - if ((j != i) && !VectorCompare (planes[i], planes[j])) - { - if (DotProduct (new_velocity, planes[j]) < 0) + for (i = 0 ; i < numplanes ; i++) { + ClipVelocity(original_velocity, planes[i], new_velocity, 1); + + for (j = 0 ; j < numplanes ; j++) + if ((j != i) && !VectorCompare(planes[i], planes[j])) { + if (DotProduct(new_velocity, planes[j]) < 0) break; // not ok } if (j == numplanes) break; } - - if (i != numplanes) - { // go along this plane - VectorCopy (new_velocity, ent->velocity); - } - else - { // go along the crease - if (numplanes != 2) - { + + if (i != numplanes) { + // go along this plane + VectorCopy(new_velocity, ent->velocity); + } else { + // go along the crease + if (numplanes != 2) { // gi.dprintf ("clip velocity, numplanes == %i\n",numplanes); - VectorCopy (vec3_origin, ent->velocity); + VectorCopy(vec3_origin, ent->velocity); return 7; } - CrossProduct (planes[0], planes[1], dir); - d = DotProduct (dir, ent->velocity); - VectorScale (dir, d, ent->velocity); + CrossProduct(planes[0], planes[1], dir); + d = DotProduct(dir, ent->velocity); + VectorScale(dir, d, ent->velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // - if (DotProduct (ent->velocity, primal_velocity) <= 0) - { - VectorCopy (vec3_origin, ent->velocity); + if (DotProduct(ent->velocity, primal_velocity) <= 0) { + VectorCopy(vec3_origin, ent->velocity); return blocked; } } @@ -319,7 +308,7 @@ SV_AddGravity ============ */ -void SV_AddGravity (edict_t *ent) +void SV_AddGravity(edict_t *ent) { ent->velocity[2] -= ent->gravity * sv_gravity->value * FRAMETIME; } @@ -339,15 +328,15 @@ SV_PushEntity Does not change the entities velocity at all ============ */ -trace_t SV_PushEntity (edict_t *ent, vec3_t push) +trace_t SV_PushEntity(edict_t *ent, vec3_t push) { trace_t trace; vec3_t start; vec3_t end; int mask; - VectorCopy (ent->s.origin, start); - VectorAdd (start, push, end); + VectorCopy(ent->s.origin, start); + VectorAdd(start, push, end); retry: if (ent->clipmask) @@ -355,34 +344,31 @@ retry: else mask = MASK_SOLID; - trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask); - - VectorCopy (trace.endpos, ent->s.origin); - gi.linkentity (ent); + trace = gi.trace(start, ent->mins, ent->maxs, end, ent, mask); + + VectorCopy(trace.endpos, ent->s.origin); + gi.linkentity(ent); - if (trace.fraction != 1.0) - { - SV_Impact (ent, &trace); + if (trace.fraction != 1.0) { + SV_Impact(ent, &trace); // if the pushed entity went away and the pusher is still there - if (!trace.ent->inuse && ent->inuse) - { + if (!trace.ent->inuse && ent->inuse) { // move the pusher back and try again - VectorCopy (start, ent->s.origin); - gi.linkentity (ent); + VectorCopy(start, ent->s.origin); + gi.linkentity(ent); goto retry; } } if (ent->inuse) - G_TouchTriggers (ent); + G_TouchTriggers(ent); return trace; -} +} -typedef struct -{ +typedef struct { edict_t *ent; vec3_t origin; vec3_t angles; @@ -402,7 +388,7 @@ Objects need to be moved back on a failed push, otherwise riders would continue to slide. ============ */ -qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) +qboolean SV_Push(edict_t *pusher, vec3_t move, vec3_t amove) { int i, e; edict_t *check, *block; @@ -412,10 +398,9 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) // clamp the move to 1/8 units, so the position will // be accurate for client side prediction - for (i=0 ; i<3 ; i++) - { + for (i = 0 ; i < 3 ; i++) { float temp; - temp = move[i]*8.0; + temp = move[i] * 8.0; if (temp > 0.0) temp += 0.5; else @@ -424,20 +409,19 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) } // find the bounding box - for (i=0 ; i<3 ; i++) - { + for (i = 0 ; i < 3 ; i++) { mins[i] = pusher->absmin[i] + move[i]; maxs[i] = pusher->absmax[i] + move[i]; } // we need this for pushing things later - VectorSubtract (vec3_origin, amove, org); - AngleVectors (org, forward, right, up); + VectorSubtract(vec3_origin, amove, org); + AngleVectors(org, forward, right, up); // save the pusher's original position pushed_p->ent = pusher; - VectorCopy (pusher->s.origin, pushed_p->origin); - VectorCopy (pusher->s.angles, pushed_p->angles); + VectorCopy(pusher->s.origin, pushed_p->origin); + VectorCopy(pusher->s.angles, pushed_p->angles); #if USE_SMOOTH_DELTA_ANGLES if (pusher->client) pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW]; @@ -445,80 +429,77 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) pushed_p++; // move the pusher to it's final position - VectorAdd (pusher->s.origin, move, pusher->s.origin); - VectorAdd (pusher->s.angles, amove, pusher->s.angles); - gi.linkentity (pusher); + VectorAdd(pusher->s.origin, move, pusher->s.origin); + VectorAdd(pusher->s.angles, amove, pusher->s.angles); + gi.linkentity(pusher); // see if any solid entities are inside the final position - check = g_edicts+1; - for (e = 1; e < globals.num_edicts; e++, check++) - { + check = g_edicts + 1; + for (e = 1; e < globals.num_edicts; e++, check++) { if (!check->inuse) continue; if (check->movetype == MOVETYPE_PUSH - || check->movetype == MOVETYPE_STOP - || check->movetype == MOVETYPE_NONE - || check->movetype == MOVETYPE_NOCLIP) + || check->movetype == MOVETYPE_STOP + || check->movetype == MOVETYPE_NONE + || check->movetype == MOVETYPE_NOCLIP) continue; if (!check->area.prev) continue; // not linked in anywhere - // if the entity is standing on the pusher, it will definitely be moved - if (check->groundentity != pusher) - { + // if the entity is standing on the pusher, it will definitely be moved + if (check->groundentity != pusher) { // see if the ent needs to be tested - if ( check->absmin[0] >= maxs[0] - || check->absmin[1] >= maxs[1] - || check->absmin[2] >= maxs[2] - || check->absmax[0] <= mins[0] - || check->absmax[1] <= mins[1] - || check->absmax[2] <= mins[2] ) + if (check->absmin[0] >= maxs[0] + || check->absmin[1] >= maxs[1] + || check->absmin[2] >= maxs[2] + || check->absmax[0] <= mins[0] + || check->absmax[1] <= mins[1] + || check->absmax[2] <= mins[2]) continue; // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) + if (!SV_TestEntityPosition(check)) continue; } - if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher)) - { + if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher)) { // move this entity pushed_p->ent = check; - VectorCopy (check->s.origin, pushed_p->origin); - VectorCopy (check->s.angles, pushed_p->angles); + VectorCopy(check->s.origin, pushed_p->origin); + VectorCopy(check->s.angles, pushed_p->angles); #if USE_SMOOTH_DELTA_ANGLES if (check->client) pushed_p->deltayaw = check->client->ps.pmove.delta_angles[YAW]; #endif pushed_p++; - // try moving the contacted entity - VectorAdd (check->s.origin, move, check->s.origin); + // try moving the contacted entity + VectorAdd(check->s.origin, move, check->s.origin); #if USE_SMOOTH_DELTA_ANGLES - if (check->client) - { // FIXME: doesn't rotate monsters? + if (check->client) { + // FIXME: doesn't rotate monsters? // FIXME: skuller: needs client side interpolation - check->client->ps.pmove.delta_angles[YAW] += ANGLE2SHORT( amove[YAW] ); + check->client->ps.pmove.delta_angles[YAW] += ANGLE2SHORT(amove[YAW]); } #endif // figure movement due to the pusher's amove - VectorSubtract (check->s.origin, pusher->s.origin, org); - org2[0] = DotProduct (org, forward); - org2[1] = -DotProduct (org, right); - org2[2] = DotProduct (org, up); - VectorSubtract (org2, org, move2); - VectorAdd (check->s.origin, move2, check->s.origin); + VectorSubtract(check->s.origin, pusher->s.origin, org); + org2[0] = DotProduct(org, forward); + org2[1] = -DotProduct(org, right); + org2[2] = DotProduct(org, up); + VectorSubtract(org2, org, move2); + VectorAdd(check->s.origin, move2, check->s.origin); // may have pushed them off an edge if (check->groundentity != pusher) check->groundentity = NULL; - block = SV_TestEntityPosition (check); - if (!block) - { // pushed ok - gi.linkentity (check); + block = SV_TestEntityPosition(check); + if (!block) { + // pushed ok + gi.linkentity(check); // impact? continue; } @@ -526,40 +507,37 @@ qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) // if it is ok to leave in the old position, do it // this is only relevent for riding entities, not pushed // FIXME: this doesn't acount for rotation - VectorSubtract (check->s.origin, move, check->s.origin); - block = SV_TestEntityPosition (check); - if (!block) - { + VectorSubtract(check->s.origin, move, check->s.origin); + block = SV_TestEntityPosition(check); + if (!block) { pushed_p--; continue; } } - + // save off the obstacle so we can call the block function obstacle = check; // move back any entities we already moved // go backwards, so if the same entity was pushed // twice, it goes back to the original position - for (p=pushed_p-1 ; p>=pushed ; p--) - { - VectorCopy (p->origin, p->ent->s.origin); - VectorCopy (p->angles, p->ent->s.angles); + for (p = pushed_p - 1 ; p >= pushed ; p--) { + VectorCopy(p->origin, p->ent->s.origin); + VectorCopy(p->angles, p->ent->s.angles); #if USE_SMOOTH_DELTA_ANGLES - if (p->ent->client) - { + if (p->ent->client) { p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw; } #endif - gi.linkentity (p->ent); + gi.linkentity(p->ent); } return qfalse; } //FIXME: is there a better way to handle this? // see if anything we moved has touched a trigger - for (p=pushed_p-1 ; p>=pushed ; p--) - G_TouchTriggers (p->ent); + for (p = pushed_p - 1 ; p >= pushed ; p--) + G_TouchTriggers(p->ent); return qtrue; } @@ -572,13 +550,13 @@ Bmodel objects don't interact with each other, but push all box objects ================ */ -void SV_Physics_Pusher (edict_t *ent) +void SV_Physics_Pusher(edict_t *ent) { vec3_t move, amove; edict_t *part, *mv; // if not a team captain, so movement will be handled elsewhere - if ( ent->flags & FL_TEAMSLAVE) + if (ent->flags & FL_TEAMSLAVE) return; // make sure all team slaves can move before commiting @@ -586,27 +564,24 @@ void SV_Physics_Pusher (edict_t *ent) // if the move is blocked, all moved objects will be backed out //retry: pushed_p = pushed; - for (part = ent ; part ; part=part->teamchain) - { + for (part = ent ; part ; part = part->teamchain) { if (part->velocity[0] || part->velocity[1] || part->velocity[2] || part->avelocity[0] || part->avelocity[1] || part->avelocity[2] - ) - { // object is moving - VectorScale (part->velocity, FRAMETIME, move); - VectorScale (part->avelocity, FRAMETIME, amove); + ) { + // object is moving + VectorScale(part->velocity, FRAMETIME, move); + VectorScale(part->avelocity, FRAMETIME, amove); - if (!SV_Push (part, move, amove)) + if (!SV_Push(part, move, amove)) break; // move was blocked } } if (pushed_p > &pushed[MAX_EDICTS]) - gi.error ("pushed_p > &pushed[MAX_EDICTS], memory corrupted"); + gi.error("pushed_p > &pushed[MAX_EDICTS], memory corrupted"); - if (part) - { + if (part) { // the move failed, bump all nextthink times and back out moves - for (mv = ent ; mv ; mv=mv->teamchain) - { + for (mv = ent ; mv ; mv = mv->teamchain) { if (mv->nextthink > 0) mv->nextthink += FRAMETIME; } @@ -614,19 +589,16 @@ void SV_Physics_Pusher (edict_t *ent) // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (part->blocked) - part->blocked (part, obstacle); + part->blocked(part, obstacle); #if 0 // if the pushed entity went away and the pusher is still there if (!obstacle->inuse && part->inuse) goto retry; #endif - } - else - { + } else { // the move succeeded, so call all think functions - for (part = ent ; part ; part=part->teamchain) - { - SV_RunThink (part); + for (part = ent ; part ; part = part->teamchain) { + SV_RunThink(part); } } } @@ -640,10 +612,10 @@ SV_Physics_None Non moving objects can only think ============= */ -void SV_Physics_None (edict_t *ent) +void SV_Physics_None(edict_t *ent) { // regular thinking - SV_RunThink (ent); + SV_RunThink(ent); } /* @@ -653,18 +625,18 @@ SV_Physics_Noclip A moving object that doesn't obey physics ============= */ -void SV_Physics_Noclip (edict_t *ent) +void SV_Physics_Noclip(edict_t *ent) { // regular thinking - if (!SV_RunThink (ent)) + if (!SV_RunThink(ent)) return; if (!ent->inuse) return; - - VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); - VectorMA (ent->s.origin, FRAMETIME, ent->velocity, ent->s.origin); - gi.linkentity (ent); + VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); + VectorMA(ent->s.origin, FRAMETIME, ent->velocity, ent->s.origin); + + gi.linkentity(ent); } /* @@ -682,7 +654,7 @@ SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ -void SV_Physics_Toss (edict_t *ent) +void SV_Physics_Toss(edict_t *ent) { trace_t trace; vec3_t move; @@ -693,12 +665,12 @@ void SV_Physics_Toss (edict_t *ent) vec3_t old_origin; // regular thinking - SV_RunThink (ent); + SV_RunThink(ent); if (!ent->inuse) return; // if not a team captain, so movement will be handled elsewhere - if ( ent->flags & FL_TEAMSLAVE) + if (ent->flags & FL_TEAMSLAVE) return; if (ent->velocity[2] > 0) @@ -710,55 +682,52 @@ void SV_Physics_Toss (edict_t *ent) ent->groundentity = NULL; // if onground, return without moving - if ( ent->groundentity ) + if (ent->groundentity) return; - VectorCopy (ent->s.origin, old_origin); + VectorCopy(ent->s.origin, old_origin); - SV_CheckVelocity (ent); + SV_CheckVelocity(ent); // add gravity if (ent->movetype != MOVETYPE_FLY - && ent->movetype != MOVETYPE_FLYMISSILE) - SV_AddGravity (ent); + && ent->movetype != MOVETYPE_FLYMISSILE) + SV_AddGravity(ent); // move angles - VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); + VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); // move origin - VectorScale (ent->velocity, FRAMETIME, move); - trace = SV_PushEntity (ent, move); + VectorScale(ent->velocity, FRAMETIME, move); + trace = SV_PushEntity(ent, move); if (!ent->inuse) return; - if (trace.fraction < 1) - { + if (trace.fraction < 1) { if (ent->movetype == MOVETYPE_BOUNCE) backoff = 1.5; else backoff = 1; - ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff); + ClipVelocity(ent->velocity, trace.plane.normal, ent->velocity, backoff); - // stop if on ground - if (trace.plane.normal[2] > 0.7) - { - if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE ) - { + // stop if on ground + if (trace.plane.normal[2] > 0.7) { + if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; - VectorCopy (vec3_origin, ent->velocity); - VectorCopy (vec3_origin, ent->avelocity); + VectorCopy(vec3_origin, ent->velocity); + VectorCopy(vec3_origin, ent->avelocity); } } // if (ent->touch) // ent->touch (ent, trace.ent, &trace.plane, trace.surface); } - + // check for water transition wasinwater = (ent->watertype & MASK_WATER); - ent->watertype = gi.pointcontents (ent->s.origin); + ent->watertype = gi.pointcontents(ent->s.origin); isinwater = ent->watertype & MASK_WATER; if (isinwater) @@ -767,15 +736,14 @@ void SV_Physics_Toss (edict_t *ent) ent->waterlevel = 0; if (!wasinwater && isinwater) - gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); + gi.positioned_sound(old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); else if (wasinwater && !isinwater) - gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); + gi.positioned_sound(ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0); // move teamslaves - for (slave = ent->teamchain; slave; slave = slave->teamchain) - { - VectorCopy (ent->s.origin, slave->s.origin); - gi.linkentity (slave); + for (slave = ent->teamchain; slave; slave = slave->teamchain) { + VectorCopy(ent->s.origin, slave->s.origin); + gi.linkentity(slave); } } @@ -805,23 +773,19 @@ FIXME: is this qtrue? #define sv_friction 6 #define sv_waterfriction 1 -void SV_AddRotationalFriction (edict_t *ent) +void SV_AddRotationalFriction(edict_t *ent) { int n; float adjustment; - VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); + VectorMA(ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles); adjustment = FRAMETIME * sv_stopspeed * sv_friction; - for (n = 0; n < 3; n++) - { - if (ent->avelocity[n] > 0) - { + for (n = 0; n < 3; n++) { + if (ent->avelocity[n] > 0) { ent->avelocity[n] -= adjustment; if (ent->avelocity[n] < 0) ent->avelocity[n] = 0; - } - else - { + } else { ent->avelocity[n] += adjustment; if (ent->avelocity[n] > 0) ent->avelocity[n] = 0; @@ -829,7 +793,7 @@ void SV_AddRotationalFriction (edict_t *ent) } } -void SV_Physics_Step (edict_t *ent) +void SV_Physics_Step(edict_t *ent) { qboolean wasonground; qboolean hitsound = qfalse; @@ -841,39 +805,37 @@ void SV_Physics_Step (edict_t *ent) // airborn monsters should always check for ground if (!ent->groundentity) - M_CheckGround (ent); + M_CheckGround(ent); groundentity = ent->groundentity; - SV_CheckVelocity (ent); + SV_CheckVelocity(ent); if (groundentity) wasonground = qtrue; else wasonground = qfalse; - + if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2]) - SV_AddRotationalFriction (ent); + SV_AddRotationalFriction(ent); // add gravity except: // flying monsters // swimming monsters who are in the water if (! wasonground) if (!(ent->flags & FL_FLY)) - if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) - { - if (ent->velocity[2] < sv_gravity->value*-0.1) + if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2))) { + if (ent->velocity[2] < sv_gravity->value * -0.1) hitsound = qtrue; if (ent->waterlevel == 0) - SV_AddGravity (ent); + SV_AddGravity(ent); } // friction for flying monsters that have been given vertical velocity - if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) - { + if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; - friction = sv_friction/3; + friction = sv_friction / 3; newspeed = speed - (FRAMETIME * control * friction); if (newspeed < 0) newspeed = 0; @@ -882,8 +844,7 @@ void SV_Physics_Step (edict_t *ent) } // friction for flying monsters that have been given vertical velocity - if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) - { + if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0)) { speed = fabs(ent->velocity[2]); control = speed < sv_stopspeed ? sv_stopspeed : speed; newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel); @@ -893,21 +854,18 @@ void SV_Physics_Step (edict_t *ent) ent->velocity[2] *= newspeed; } - if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) - { + if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0]) { // apply friction // let dead monsters who aren't completely onground slide - if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY))) - if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) - { + if ((wasonground) || (ent->flags & (FL_SWIM | FL_FLY))) + if (!(ent->health <= 0.0 && !M_CheckBottom(ent))) { vel = ent->velocity; - speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]); - if (speed) - { + speed = sqrt(vel[0] * vel[0] + vel[1] * vel[1]); + if (speed) { friction = sv_friction; control = speed < sv_stopspeed ? sv_stopspeed : speed; - newspeed = speed - FRAMETIME*control*friction; + newspeed = speed - FRAMETIME * control * friction; if (newspeed < 0) newspeed = 0; @@ -922,21 +880,21 @@ void SV_Physics_Step (edict_t *ent) mask = MASK_MONSTERSOLID; else mask = MASK_SOLID; - SV_FlyMove (ent, FRAMETIME, mask); + SV_FlyMove(ent, FRAMETIME, mask); - gi.linkentity (ent); - G_TouchTriggers (ent); + gi.linkentity(ent); + G_TouchTriggers(ent); if (!ent->inuse) return; if (ent->groundentity) if (!wasonground) if (hitsound) - gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); + gi.sound(ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0); } // regular thinking - SV_RunThink (ent); + SV_RunThink(ent); } //============================================================================ @@ -946,33 +904,32 @@ G_RunEntity ================ */ -void G_RunEntity (edict_t *ent) +void G_RunEntity(edict_t *ent) { if (ent->prethink) - ent->prethink (ent); + ent->prethink(ent); - switch ( (int)ent->movetype) - { + switch ((int)ent->movetype) { case MOVETYPE_PUSH: case MOVETYPE_STOP: - SV_Physics_Pusher (ent); + SV_Physics_Pusher(ent); break; case MOVETYPE_NONE: - SV_Physics_None (ent); + SV_Physics_None(ent); break; case MOVETYPE_NOCLIP: - SV_Physics_Noclip (ent); + SV_Physics_Noclip(ent); break; case MOVETYPE_STEP: - SV_Physics_Step (ent); + SV_Physics_Step(ent); break; case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: - SV_Physics_Toss (ent); + SV_Physics_Toss(ent); break; default: - gi.error ("SV_Physics: bad movetype %i", (int)ent->movetype); + gi.error("SV_Physics: bad movetype %i", (int)ent->movetype); } } |