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

unix.superglobalmegacorp.com

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