Annotation of quake2/rogue/g_phys.c, revision 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.