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

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

unix.superglobalmegacorp.com

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