Annotation of quake2/game/g_phys.c, revision 1.1.1.1

1.1       root        1: // g_phys.c
                      2: 
                      3: #include "g_local.h"
                      4: 
                      5: /*
                      6: 
                      7: 
                      8: 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.
                      9: 
                     10: onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects 
                     11: 
                     12: doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
                     13: bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
                     14: corpses are SOLID_NOT and MOVETYPE_TOSS
                     15: crates are SOLID_BBOX and MOVETYPE_TOSS
                     16: walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
                     17: flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
                     18: 
                     19: solid_edge items only clip against bsp models.
                     20: 
                     21: */
                     22: 
                     23: 
                     24: /*
                     25: ============
                     26: SV_TestEntityPosition
                     27: 
                     28: ============
                     29: */
                     30: edict_t        *SV_TestEntityPosition (edict_t *ent)
                     31: {
                     32:        trace_t trace;
                     33:        int             mask;
                     34: 
                     35:        if (ent->clipmask)
                     36:                mask = ent->clipmask;
                     37:        else
                     38:                mask = MASK_SOLID;
                     39:        trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, ent->s.origin, ent, mask);
                     40:        
                     41:        if (trace.startsolid)
                     42:                return g_edicts;
                     43:                
                     44:        return NULL;
                     45: }
                     46: 
                     47: 
                     48: /*
                     49: ================
                     50: SV_CheckVelocity
                     51: ================
                     52: */
                     53: void SV_CheckVelocity (edict_t *ent)
                     54: {
                     55:        int             i;
                     56: 
                     57: //
                     58: // bound velocity
                     59: //
                     60:        for (i=0 ; i<3 ; i++)
                     61:        {
                     62:                if (ent->velocity[i] > sv_maxvelocity->value)
                     63:                        ent->velocity[i] = sv_maxvelocity->value;
                     64:                else if (ent->velocity[i] < -sv_maxvelocity->value)
                     65:                        ent->velocity[i] = -sv_maxvelocity->value;
                     66:        }
                     67: }
                     68: 
                     69: /*
                     70: =============
                     71: SV_RunThink
                     72: 
                     73: Runs thinking code for this frame if necessary
                     74: =============
                     75: */
                     76: qboolean SV_RunThink (edict_t *ent)
                     77: {
                     78:        float   thinktime;
                     79: 
                     80:        thinktime = ent->nextthink;
                     81:        if (thinktime <= 0)
                     82:                return true;
                     83:        if (thinktime > level.time+0.001)
                     84:                return true;
                     85:        
                     86:        ent->nextthink = 0;
                     87:        if (!ent->think)
                     88:                gi.error ("NULL ent->think");
                     89:        ent->think (ent);
                     90: 
                     91:        return false;
                     92: }
                     93: 
                     94: /*
                     95: ==================
                     96: SV_Impact
                     97: 
                     98: Two entities have touched, so run their touch functions
                     99: ==================
                    100: */
                    101: void SV_Impact (edict_t *e1, trace_t *trace)
                    102: {
                    103:        edict_t         *e2;
                    104: //     cplane_t        backplane;
                    105: 
                    106:        e2 = trace->ent;
                    107: 
                    108:        if (e1->touch && e1->solid != SOLID_NOT)
                    109:                e1->touch (e1, e2, &trace->plane, trace->surface);
                    110:        
                    111:        if (e2->touch && e2->solid != SOLID_NOT)
                    112:                e2->touch (e2, e1, NULL, NULL);
                    113: }
                    114: 
                    115: 
                    116: /*
                    117: ==================
                    118: ClipVelocity
                    119: 
                    120: Slide off of the impacting object
                    121: returns the blocked flags (1 = floor, 2 = step / wall)
                    122: ==================
                    123: */
                    124: #define        STOP_EPSILON    0.1
                    125: 
                    126: int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
                    127: {
                    128:        float   backoff;
                    129:        float   change;
                    130:        int             i, blocked;
                    131:        
                    132:        blocked = 0;
                    133:        if (normal[2] > 0)
                    134:                blocked |= 1;           // floor
                    135:        if (!normal[2])
                    136:                blocked |= 2;           // step
                    137:        
                    138:        backoff = DotProduct (in, normal) * overbounce;
                    139: 
                    140:        for (i=0 ; i<3 ; i++)
                    141:        {
                    142:                change = normal[i]*backoff;
                    143:                out[i] = in[i] - change;
                    144:                if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
                    145:                        out[i] = 0;
                    146:        }
                    147:        
                    148:        return blocked;
                    149: }
                    150: 
                    151: 
                    152: /*
                    153: ============
                    154: SV_FlyMove
                    155: 
                    156: The basic solid body movement clip that slides along multiple planes
                    157: Returns the clipflags if the velocity was modified (hit something solid)
                    158: 1 = floor
                    159: 2 = wall / step
                    160: 4 = dead stop
                    161: ============
                    162: */
                    163: #define        MAX_CLIP_PLANES 5
                    164: int SV_FlyMove (edict_t *ent, float time, int mask)
                    165: {
                    166:        edict_t         *hit;
                    167:        int                     bumpcount, numbumps;
                    168:        vec3_t          dir;
                    169:        float           d;
                    170:        int                     numplanes;
                    171:        vec3_t          planes[MAX_CLIP_PLANES];
                    172:        vec3_t          primal_velocity, original_velocity, new_velocity;
                    173:        int                     i, j;
                    174:        trace_t         trace;
                    175:        vec3_t          end;
                    176:        float           time_left;
                    177:        int                     blocked;
                    178:        
                    179:        numbumps = 4;
                    180:        
                    181:        blocked = 0;
                    182:        VectorCopy (ent->velocity, original_velocity);
                    183:        VectorCopy (ent->velocity, primal_velocity);
                    184:        numplanes = 0;
                    185:        
                    186:        time_left = time;
                    187: 
                    188:        ent->groundentity = NULL;
                    189:        for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
                    190:        {
                    191:                for (i=0 ; i<3 ; i++)
                    192:                        end[i] = ent->s.origin[i] + time_left * ent->velocity[i];
                    193: 
                    194:                trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, end, ent, mask);
                    195: 
                    196:                if (trace.allsolid)
                    197:                {       // entity is trapped in another solid
                    198:                        VectorCopy (vec3_origin, ent->velocity);
                    199:                        return 3;
                    200:                }
                    201: 
                    202:                if (trace.fraction > 0)
                    203:                {       // actually covered some distance
                    204:                        VectorCopy (trace.endpos, ent->s.origin);
                    205:                        VectorCopy (ent->velocity, original_velocity);
                    206:                        numplanes = 0;
                    207:                }
                    208: 
                    209:                if (trace.fraction == 1)
                    210:                         break;         // moved the entire distance
                    211: 
                    212:                hit = trace.ent;
                    213: 
                    214:                if (trace.plane.normal[2] > 0.7)
                    215:                {
                    216:                        blocked |= 1;           // floor
                    217:                        if ( hit->solid == SOLID_BSP)
                    218:                        {
                    219:                                ent->groundentity = hit;
                    220:                                ent->groundentity_linkcount = hit->linkcount;
                    221:                        }
                    222:                }
                    223:                if (!trace.plane.normal[2])
                    224:                {
                    225:                        blocked |= 2;           // step
                    226:                }
                    227: 
                    228: //
                    229: // run the impact function
                    230: //
                    231:                SV_Impact (ent, &trace);
                    232:                if (!ent->inuse)
                    233:                        break;          // removed by the impact function
                    234: 
                    235:                
                    236:                time_left -= time_left * trace.fraction;
                    237:                
                    238:        // cliped to another plane
                    239:                if (numplanes >= MAX_CLIP_PLANES)
                    240:                {       // this shouldn't really happen
                    241:                        VectorCopy (vec3_origin, ent->velocity);
                    242:                        return 3;
                    243:                }
                    244: 
                    245:                VectorCopy (trace.plane.normal, planes[numplanes]);
                    246:                numplanes++;
                    247: 
                    248: //
                    249: // modify original_velocity so it parallels all of the clip planes
                    250: //
                    251:                for (i=0 ; i<numplanes ; i++)
                    252:                {
                    253:                        ClipVelocity (original_velocity, planes[i], new_velocity, 1);
                    254:                        for (j=0 ; j<numplanes ; j++)
                    255:                                if (j != i)
                    256:                                {
                    257:                                        if (DotProduct (new_velocity, planes[j]) < 0)
                    258:                                                break;  // not ok
                    259:                                }
                    260:                        if (j == numplanes)
                    261:                                break;
                    262:                }
                    263:                
                    264:                if (i != numplanes)
                    265:                {       // go along this plane
                    266:                        VectorCopy (new_velocity, ent->velocity);
                    267:                }
                    268:                else
                    269:                {       // go along the crease
                    270:                        if (numplanes != 2)
                    271:                        {
                    272: //                             gi.dprintf ("clip velocity, numplanes == %i\n",numplanes);
                    273:                                VectorCopy (vec3_origin, ent->velocity);
                    274:                                return 7;
                    275:                        }
                    276:                        CrossProduct (planes[0], planes[1], dir);
                    277:                        d = DotProduct (dir, ent->velocity);
                    278:                        VectorScale (dir, d, ent->velocity);
                    279:                }
                    280: 
                    281: //
                    282: // if original velocity is against the original velocity, stop dead
                    283: // to avoid tiny occilations in sloping corners
                    284: //
                    285:                if (DotProduct (ent->velocity, primal_velocity) <= 0)
                    286:                {
                    287:                        VectorCopy (vec3_origin, ent->velocity);
                    288:                        return blocked;
                    289:                }
                    290:        }
                    291: 
                    292:        return blocked;
                    293: }
                    294: 
                    295: 
                    296: /*
                    297: ============
                    298: SV_AddGravity
                    299: 
                    300: ============
                    301: */
                    302: void SV_AddGravity (edict_t *ent)
                    303: {
                    304:        ent->velocity[2] -= ent->gravity * sv_gravity->value * FRAMETIME;
                    305: }
                    306: 
                    307: /*
                    308: ===============================================================================
                    309: 
                    310: PUSHMOVE
                    311: 
                    312: ===============================================================================
                    313: */
                    314: 
                    315: /*
                    316: ============
                    317: SV_PushEntity
                    318: 
                    319: Does not change the entities velocity at all
                    320: ============
                    321: */
                    322: trace_t SV_PushEntity (edict_t *ent, vec3_t push)
                    323: {
                    324:        trace_t trace;
                    325:        vec3_t  start;
                    326:        vec3_t  end;
                    327:        int             mask;
                    328: 
                    329:        VectorCopy (ent->s.origin, start);
                    330:        VectorAdd (start, push, end);
                    331: 
                    332: retry:
                    333:        if (ent->clipmask)
                    334:                mask = ent->clipmask;
                    335:        else
                    336:                mask = MASK_SOLID;
                    337: 
                    338:        trace = gi.trace (start, ent->mins, ent->maxs, end, ent, mask);
                    339:        
                    340:        VectorCopy (trace.endpos, ent->s.origin);
                    341:        gi.linkentity (ent);
                    342: 
                    343:        if (trace.fraction != 1.0)
                    344:        {
                    345:                SV_Impact (ent, &trace);
                    346: 
                    347:                // if the pushed entity went away and the pusher is still there
                    348:                if (!trace.ent->inuse && ent->inuse)
                    349:                {
                    350:                        // move the pusher back and try again
                    351:                        VectorCopy (start, ent->s.origin);
                    352:                        gi.linkentity (ent);
                    353:                        goto retry;
                    354:                }
                    355:        }
                    356: 
                    357:        if (ent->inuse)
                    358:                G_TouchTriggers (ent);
                    359: 
                    360:        return trace;
                    361: }                                      
                    362: 
                    363: 
                    364: typedef struct
                    365: {
                    366:        edict_t *ent;
                    367:        vec3_t  origin;
                    368:        vec3_t  angles;
                    369:        float   deltayaw;
                    370: } pushed_t;
                    371: pushed_t       pushed[MAX_EDICTS], *pushed_p;
                    372: 
                    373: edict_t        *obstacle;
                    374: 
                    375: /*
                    376: ============
                    377: SV_Push
                    378: 
                    379: Objects need to be moved back on a failed push,
                    380: otherwise riders would continue to slide.
                    381: ============
                    382: */
                    383: qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove)
                    384: {
                    385:        int                     i, e;
                    386:        edict_t         *check, *block;
                    387:        vec3_t          mins, maxs;
                    388:        pushed_t        *p;
                    389:        vec3_t          org, org2, move2, forward, right, up;
                    390: 
                    391:        // clamp the move to 1/8 units, so the position will
                    392:        // be accurate for client side prediction
                    393:        for (i=0 ; i<3 ; i++)
                    394:        {
                    395:                float   temp;
                    396:                temp = move[i]*8.0;
                    397:                if (temp > 0.0)
                    398:                        temp += 0.5;
                    399:                else
                    400:                        temp -= 0.5;
                    401:                move[i] = 0.125 * (int)temp;
                    402:        }
                    403: 
                    404:        // find the bounding box
                    405:        for (i=0 ; i<3 ; i++)
                    406:        {
                    407:                mins[i] = pusher->absmin[i] + move[i];
                    408:                maxs[i] = pusher->absmax[i] + move[i];
                    409:        }
                    410: 
                    411: // we need this for pushing things later
                    412:        VectorSubtract (vec3_origin, amove, org);
                    413:        AngleVectors (org, forward, right, up);
                    414: 
                    415: // save the pusher's original position
                    416:        pushed_p->ent = pusher;
                    417:        VectorCopy (pusher->s.origin, pushed_p->origin);
                    418:        VectorCopy (pusher->s.angles, pushed_p->angles);
                    419:        if (pusher->client)
                    420:                pushed_p->deltayaw = pusher->client->ps.pmove.delta_angles[YAW];
                    421:        pushed_p++;
                    422: 
                    423: // move the pusher to it's final position
                    424:        VectorAdd (pusher->s.origin, move, pusher->s.origin);
                    425:        VectorAdd (pusher->s.angles, amove, pusher->s.angles);
                    426:        gi.linkentity (pusher);
                    427: 
                    428: // see if any solid entities are inside the final position
                    429:        check = g_edicts+1;
                    430:        for (e = 1; e < globals.num_edicts; e++, check++)
                    431:        {
                    432:                if (!check->inuse)
                    433:                        continue;
                    434:                if (check->movetype == MOVETYPE_PUSH
                    435:                || check->movetype == MOVETYPE_STOP
                    436:                || check->movetype == MOVETYPE_NONE
                    437:                || check->movetype == MOVETYPE_NOCLIP)
                    438:                        continue;
                    439: 
                    440:                if (!check->area.prev)
                    441:                        continue;               // not linked in anywhere
                    442: 
                    443:        // if the entity is standing on the pusher, it will definitely be moved
                    444:                if (check->groundentity != pusher)
                    445:                {
                    446:                        // see if the ent needs to be tested
                    447:                        if ( check->absmin[0] >= maxs[0]
                    448:                        || check->absmin[1] >= maxs[1]
                    449:                        || check->absmin[2] >= maxs[2]
                    450:                        || check->absmax[0] <= mins[0]
                    451:                        || check->absmax[1] <= mins[1]
                    452:                        || check->absmax[2] <= mins[2] )
                    453:                                continue;
                    454: 
                    455:                        // see if the ent's bbox is inside the pusher's final position
                    456:                        if (!SV_TestEntityPosition (check))
                    457:                                continue;
                    458:                }
                    459: 
                    460:                if ((pusher->movetype == MOVETYPE_PUSH) || (check->groundentity == pusher))
                    461:                {
                    462:                        // move this entity
                    463:                        pushed_p->ent = check;
                    464:                        VectorCopy (check->s.origin, pushed_p->origin);
                    465:                        VectorCopy (check->s.angles, pushed_p->angles);
                    466:                        pushed_p++;
                    467: 
                    468:                        // try moving the contacted entity 
                    469:                        VectorAdd (check->s.origin, move, check->s.origin);
                    470:                        if (check->client)
                    471:                        {       // FIXME: doesn't rotate monsters?
                    472:                                check->client->ps.pmove.delta_angles[YAW] += amove[YAW];
                    473:                        }
                    474: 
                    475:                        // figure movement due to the pusher's amove
                    476:                        VectorSubtract (check->s.origin, pusher->s.origin, org);
                    477:                        org2[0] = DotProduct (org, forward);
                    478:                        org2[1] = -DotProduct (org, right);
                    479:                        org2[2] = DotProduct (org, up);
                    480:                        VectorSubtract (org2, org, move2);
                    481:                        VectorAdd (check->s.origin, move2, check->s.origin);
                    482: 
                    483:                        // may have pushed them off an edge
                    484:                        if (check->groundentity != pusher)
                    485:                                check->groundentity = NULL;
                    486: 
                    487:                        block = SV_TestEntityPosition (check);
                    488:                        if (!block)
                    489:                        {       // pushed ok
                    490:                                gi.linkentity (check);
                    491:                                // impact?
                    492:                                continue;
                    493:                        }
                    494: 
                    495:                        // if it is ok to leave in the old position, do it
                    496:                        // this is only relevent for riding entities, not pushed
                    497:                        // FIXME: this doesn't acount for rotation
                    498:                        VectorSubtract (check->s.origin, move, check->s.origin);
                    499:                        block = SV_TestEntityPosition (check);
                    500:                        if (!block)
                    501:                        {
                    502:                                pushed_p--;
                    503:                                continue;
                    504:                        }
                    505:                }
                    506:                
                    507:                // save off the obstacle so we can call the block function
                    508:                obstacle = check;
                    509: 
                    510:                // move back any entities we already moved
                    511:                // go backwards, so if the same entity was pushed
                    512:                // twice, it goes back to the original position
                    513:                for (p=pushed_p-1 ; p>=pushed ; p--)
                    514:                {
                    515:                        VectorCopy (p->origin, p->ent->s.origin);
                    516:                        VectorCopy (p->angles, p->ent->s.angles);
                    517:                        if (p->ent->client)
                    518:                        {
                    519:                                p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw;
                    520:                        }
                    521:                        gi.linkentity (p->ent);
                    522:                }
                    523:                return false;
                    524:        }
                    525: 
                    526: //FIXME: is there a better way to handle this?
                    527:        // see if anything we moved has touched a trigger
                    528:        for (p=pushed_p-1 ; p>=pushed ; p--)
                    529:                G_TouchTriggers (p->ent);
                    530: 
                    531:        return true;
                    532: }
                    533: 
                    534: /*
                    535: ================
                    536: SV_Physics_Pusher
                    537: 
                    538: Bmodel objects don't interact with each other, but
                    539: push all box objects
                    540: ================
                    541: */
                    542: void SV_Physics_Pusher (edict_t *ent)
                    543: {
                    544:        vec3_t          move, amove;
                    545:        edict_t         *part, *mv;
                    546: 
                    547:        // if not a team captain, so movement will be handled elsewhere
                    548:        if ( ent->flags & FL_TEAMSLAVE)
                    549:                return;
                    550: 
                    551:        // make sure all team slaves can move before commiting
                    552:        // any moves or calling any think functions
                    553:        // if the move is blocked, all moved objects will be backed out
                    554: //retry:
                    555:        pushed_p = pushed;
                    556:        for (part = ent ; part ; part=part->teamchain)
                    557:        {
                    558:                if (part->velocity[0] || part->velocity[1] || part->velocity[2] ||
                    559:                        part->avelocity[0] || part->avelocity[1] || part->avelocity[2]
                    560:                        )
                    561:                {       // object is moving
                    562:                        VectorScale (part->velocity, FRAMETIME, move);
                    563:                        VectorScale (part->avelocity, FRAMETIME, amove);
                    564: 
                    565:                        if (!SV_Push (part, move, amove))
                    566:                                break;  // move was blocked
                    567:                }
                    568:        }
                    569:        if (pushed_p > &pushed[MAX_EDICTS])
                    570:                gi.error (ERR_FATAL, "pushed_p > &pushed[MAX_EDICTS], memory corrupted");
                    571: 
                    572:        if (part)
                    573:        {
                    574:                // the move failed, bump all nextthink times and back out moves
                    575:                for (mv = ent ; mv ; mv=mv->teamchain)
                    576:                {
                    577:                        if (mv->nextthink > 0)
                    578:                                mv->nextthink += FRAMETIME;
                    579:                }
                    580: 
                    581:                // if the pusher has a "blocked" function, call it
                    582:                // otherwise, just stay in place until the obstacle is gone
                    583:                if (part->blocked)
                    584:                        part->blocked (part, obstacle);
                    585: #if 0
                    586:                // if the pushed entity went away and the pusher is still there
                    587:                if (!obstacle->inuse && part->inuse)
                    588:                        goto retry;
                    589: #endif
                    590:        }
                    591:        else
                    592:        {
                    593:                // the move succeeded, so call all think functions
                    594:                for (part = ent ; part ; part=part->teamchain)
                    595:                {
                    596:                        SV_RunThink (part);
                    597:                }
                    598:        }
                    599: }
                    600: 
                    601: //==================================================================
                    602: 
                    603: /*
                    604: =============
                    605: SV_Physics_None
                    606: 
                    607: Non moving objects can only think
                    608: =============
                    609: */
                    610: void SV_Physics_None (edict_t *ent)
                    611: {
                    612: // regular thinking
                    613:        SV_RunThink (ent);
                    614: }
                    615: 
                    616: /*
                    617: =============
                    618: SV_Physics_Noclip
                    619: 
                    620: A moving object that doesn't obey physics
                    621: =============
                    622: */
                    623: void SV_Physics_Noclip (edict_t *ent)
                    624: {
                    625: // regular thinking
                    626:        if (!SV_RunThink (ent))
                    627:                return;
                    628:        
                    629:        VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);
                    630:        VectorMA (ent->s.origin, FRAMETIME, ent->velocity, ent->s.origin);
                    631: 
                    632:        gi.linkentity (ent);
                    633: }
                    634: 
                    635: /*
                    636: ==============================================================================
                    637: 
                    638: TOSS / BOUNCE
                    639: 
                    640: ==============================================================================
                    641: */
                    642: 
                    643: /*
                    644: =============
                    645: SV_Physics_Toss
                    646: 
                    647: Toss, bounce, and fly movement.  When onground, do nothing.
                    648: =============
                    649: */
                    650: void SV_Physics_Toss (edict_t *ent)
                    651: {
                    652:        trace_t         trace;
                    653:        vec3_t          move;
                    654:        float           backoff;
                    655:        edict_t         *slave;
                    656:        qboolean        wasinwater;
                    657:        qboolean        isinwater;
                    658:        vec3_t          old_origin;
                    659: 
                    660: // regular thinking
                    661:        SV_RunThink (ent);
                    662: 
                    663:        // if not a team captain, so movement will be handled elsewhere
                    664:        if ( ent->flags & FL_TEAMSLAVE)
                    665:                return;
                    666: 
                    667:        if (ent->velocity[2] > 0)
                    668:                ent->groundentity = NULL;
                    669: 
                    670: // check for the groundentity going away
                    671:        if (ent->groundentity)
                    672:                if (!ent->groundentity->inuse)
                    673:                        ent->groundentity = NULL;
                    674: 
                    675: // if onground, return without moving
                    676:        if ( ent->groundentity )
                    677:                return;
                    678: 
                    679:        VectorCopy (ent->s.origin, old_origin);
                    680: 
                    681:        SV_CheckVelocity (ent);
                    682: 
                    683: // add gravity
                    684:        if (ent->movetype != MOVETYPE_FLY
                    685:        && ent->movetype != MOVETYPE_FLYMISSILE)
                    686:                SV_AddGravity (ent);
                    687: 
                    688: // move angles
                    689:        VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);
                    690: 
                    691: // move origin
                    692:        VectorScale (ent->velocity, FRAMETIME, move);
                    693:        trace = SV_PushEntity (ent, move);
                    694:        if (!ent->inuse)
                    695:                return;
                    696: 
                    697:        if (trace.fraction < 1)
                    698:        {
                    699:                if (ent->movetype == MOVETYPE_BOUNCE)
                    700:                        backoff = 1.5;
                    701:                else
                    702:                        backoff = 1;
                    703: 
                    704:                ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff);
                    705: 
                    706:        // stop if on ground
                    707:                if (trace.plane.normal[2] > 0.7)
                    708:                {               
                    709:                        if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE )
                    710:                        {
                    711:                                ent->groundentity = trace.ent;
                    712:                                ent->groundentity_linkcount = trace.ent->linkcount;
                    713:                                VectorCopy (vec3_origin, ent->velocity);
                    714:                                VectorCopy (vec3_origin, ent->avelocity);
                    715:                        }
                    716:                }
                    717: 
                    718: //             if (ent->touch)
                    719: //                     ent->touch (ent, trace.ent, &trace.plane, trace.surface);
                    720:        }
                    721:        
                    722: // check for water transition
                    723:        wasinwater = (ent->watertype & MASK_WATER);
                    724:        ent->watertype = gi.pointcontents (ent->s.origin);
                    725:        isinwater = ent->watertype & MASK_WATER;
                    726: 
                    727:        if (isinwater)
                    728:                ent->waterlevel = 1;
                    729:        else
                    730:                ent->waterlevel = 0;
                    731: 
                    732:        if (!wasinwater && isinwater)
                    733:                gi.positioned_sound (old_origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
                    734:        else if (wasinwater && !isinwater)
                    735:                gi.positioned_sound (ent->s.origin, g_edicts, CHAN_AUTO, gi.soundindex("misc/h2ohit1.wav"), 1, 1, 0);
                    736: 
                    737: // move teamslaves
                    738:        for (slave = ent->teamchain; slave; slave = slave->teamchain)
                    739:        {
                    740:                VectorCopy (ent->s.origin, slave->s.origin);
                    741:                gi.linkentity (slave);
                    742:        }
                    743: }
                    744: 
                    745: /*
                    746: ===============================================================================
                    747: 
                    748: STEPPING MOVEMENT
                    749: 
                    750: ===============================================================================
                    751: */
                    752: 
                    753: /*
                    754: =============
                    755: SV_Physics_Step
                    756: 
                    757: Monsters freefall when they don't have a ground entity, otherwise
                    758: all movement is done with discrete steps.
                    759: 
                    760: This is also used for objects that have become still on the ground, but
                    761: will fall if the floor is pulled out from under them.
                    762: FIXME: is this true?
                    763: =============
                    764: */
                    765: 
                    766: //FIXME: hacked in for E3 demo
                    767: #define        sv_stopspeed            100
                    768: #define sv_friction                    6
                    769: #define sv_waterfriction       1
                    770: 
                    771: void SV_AddRotationalFriction (edict_t *ent)
                    772: {
                    773:        int             n;
                    774:        float   adjustment;
                    775: 
                    776:        VectorMA (ent->s.angles, FRAMETIME, ent->avelocity, ent->s.angles);
                    777:        adjustment = FRAMETIME * sv_stopspeed * sv_friction;
                    778:        for (n = 0; n < 3; n++)
                    779:        {
                    780:                if (ent->avelocity[n] > 0)
                    781:                {
                    782:                        ent->avelocity[n] -= adjustment;
                    783:                        if (ent->avelocity[n] < 0)
                    784:                                ent->avelocity[n] = 0;
                    785:                }
                    786:                else
                    787:                {
                    788:                        ent->avelocity[n] += adjustment;
                    789:                        if (ent->avelocity[n] > 0)
                    790:                                ent->avelocity[n] = 0;
                    791:                }
                    792:        }
                    793: }
                    794: 
                    795: void SV_Physics_Step (edict_t *ent)
                    796: {
                    797:        qboolean        wasonground;
                    798:        qboolean        hitsound = false;
                    799:        float           *vel;
                    800:        float           speed, newspeed, control;
                    801:        float           friction;
                    802:        edict_t         *groundentity;
                    803:        int                     mask;
                    804: 
                    805:        // airborn monsters should always check for ground
                    806:        if (!ent->groundentity)
                    807:                M_CheckGround (ent);
                    808: 
                    809:        groundentity = ent->groundentity;
                    810: 
                    811:        SV_CheckVelocity (ent);
                    812: 
                    813:        if (groundentity)
                    814:                wasonground = true;
                    815:        else
                    816:                wasonground = false;
                    817:                
                    818:        if (ent->avelocity[0] || ent->avelocity[1] || ent->avelocity[2])
                    819:                SV_AddRotationalFriction (ent);
                    820: 
                    821:        // add gravity except:
                    822:        //   flying monsters
                    823:        //   swimming monsters who are in the water
                    824:        if (! wasonground)
                    825:                if (!(ent->flags & FL_FLY))
                    826:                        if (!((ent->flags & FL_SWIM) && (ent->waterlevel > 2)))
                    827:                        {
                    828:                                if (ent->velocity[2] < sv_gravity->value*-0.1)
                    829:                                        hitsound = true;
                    830:                                if (ent->waterlevel == 0)
                    831:                                        SV_AddGravity (ent);
                    832:                        }
                    833: 
                    834:        // friction for flying monsters that have been given vertical velocity
                    835:        if ((ent->flags & FL_FLY) && (ent->velocity[2] != 0))
                    836:        {
                    837:                speed = fabs(ent->velocity[2]);
                    838:                control = speed < sv_stopspeed ? sv_stopspeed : speed;
                    839:                friction = sv_friction/3;
                    840:                newspeed = speed - (FRAMETIME * control * friction);
                    841:                if (newspeed < 0)
                    842:                        newspeed = 0;
                    843:                newspeed /= speed;
                    844:                ent->velocity[2] *= newspeed;
                    845:        }
                    846: 
                    847:        // friction for flying monsters that have been given vertical velocity
                    848:        if ((ent->flags & FL_SWIM) && (ent->velocity[2] != 0))
                    849:        {
                    850:                speed = fabs(ent->velocity[2]);
                    851:                control = speed < sv_stopspeed ? sv_stopspeed : speed;
                    852:                newspeed = speed - (FRAMETIME * control * sv_waterfriction * ent->waterlevel);
                    853:                if (newspeed < 0)
                    854:                        newspeed = 0;
                    855:                newspeed /= speed;
                    856:                ent->velocity[2] *= newspeed;
                    857:        }
                    858: 
                    859:        if (ent->velocity[2] || ent->velocity[1] || ent->velocity[0])
                    860:        {
                    861:                // apply friction
                    862:                // let dead monsters who aren't completely onground slide
                    863:                if ((wasonground) || (ent->flags & (FL_SWIM|FL_FLY)))
                    864:                        if (!(ent->health <= 0.0 && !M_CheckBottom(ent)))
                    865:                        {
                    866:                                vel = ent->velocity;
                    867:                                speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
                    868:                                if (speed)
                    869:                                {
                    870:                                        friction = sv_friction;
                    871: 
                    872:                                        control = speed < sv_stopspeed ? sv_stopspeed : speed;
                    873:                                        newspeed = speed - FRAMETIME*control*friction;
                    874: 
                    875:                                        if (newspeed < 0)
                    876:                                                newspeed = 0;
                    877:                                        newspeed /= speed;
                    878: 
                    879:                                        vel[0] *= newspeed;
                    880:                                        vel[1] *= newspeed;
                    881:                                }
                    882:                        }
                    883: 
                    884:                if (ent->svflags & SVF_MONSTER)
                    885:                        mask = MASK_MONSTERSOLID;
                    886:                else
                    887:                        mask = MASK_SOLID;
                    888:                SV_FlyMove (ent, FRAMETIME, mask);
                    889: 
                    890:                gi.linkentity (ent);
                    891:                G_TouchTriggers (ent);
                    892: 
                    893:                if (ent->groundentity)
                    894:                        if (!wasonground)
                    895:                                if (hitsound)
                    896:                                        gi.sound (ent, 0, gi.soundindex("world/land.wav"), 1, 1, 0);
                    897:        }
                    898: 
                    899: // regular thinking
                    900:        SV_RunThink (ent);
                    901: }
                    902: 
                    903: //============================================================================
                    904: /*
                    905: ================
                    906: G_RunEntity
                    907: 
                    908: ================
                    909: */
                    910: void G_RunEntity (edict_t *ent)
                    911: {
                    912:        if (ent->prethink)
                    913:                ent->prethink (ent);
                    914: 
                    915:        switch ( (int)ent->movetype)
                    916:        {
                    917:        case MOVETYPE_PUSH:
                    918:        case MOVETYPE_STOP:
                    919:                SV_Physics_Pusher (ent);
                    920:                break;
                    921:        case MOVETYPE_NONE:
                    922:                SV_Physics_None (ent);
                    923:                break;
                    924:        case MOVETYPE_NOCLIP:
                    925:                SV_Physics_Noclip (ent);
                    926:                break;
                    927:        case MOVETYPE_STEP:
                    928:                SV_Physics_Step (ent);
                    929:                break;
                    930:        case MOVETYPE_TOSS:
                    931:        case MOVETYPE_BOUNCE:
                    932:        case MOVETYPE_FLY:
                    933:        case MOVETYPE_FLYMISSILE:
                    934:                SV_Physics_Toss (ent);
                    935:                break;
                    936:        default:
                    937:                gi.error ("SV_Physics: bad movetype %i", (int)ent->movetype);                   
                    938:        }
                    939: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.