Annotation of quake2/qcommon/pmove.c, revision 1.1

1.1     ! root        1: 
        !             2: #include "qcommon.h"
        !             3: 
        !             4: #define        STEPSIZE        18
        !             5: 
        !             6: // all of the locals will be zeroed before each
        !             7: // pmove, just to make damn sure we don't have
        !             8: // any differences when running on client or server
        !             9: 
        !            10: typedef struct
        !            11: {
        !            12:        vec3_t          origin;                 // full float precision
        !            13:        vec3_t          velocity;               // full float precision
        !            14: 
        !            15:        vec3_t          forward, right, up;
        !            16:        float           frametime;
        !            17: 
        !            18: 
        !            19:        csurface_t      *groundsurface;
        !            20:        cplane_t        groundplane;
        !            21:        int                     groundcontents;
        !            22: 
        !            23:        vec3_t          previous_origin;
        !            24:        qboolean        ladder;
        !            25: } pml_t;
        !            26: 
        !            27: pmove_t                *pm;
        !            28: pml_t          pml;
        !            29: 
        !            30: // movement parameters
        !            31: float  pm_stopspeed = 100;
        !            32: float  pm_maxspeed = 300;
        !            33: float  pm_duckspeed = 100;
        !            34: float  pm_accelerate = 10;
        !            35: float  pm_airaccelerate = 1;
        !            36: float  pm_wateraccelerate = 10;
        !            37: float  pm_friction = 6;
        !            38: float  pm_waterfriction = 1;
        !            39: float  pm_waterspeed = 400;
        !            40: /*
        !            41:   walking up a step should kill some velocity
        !            42: */
        !            43: /*
        !            44: ==================
        !            45: PM_ClipVelocity
        !            46: Slide off of the impacting object
        !            47: returns the blocked flags (1 = floor, 2 = step / wall)
        !            48: ==================
        !            49: */
        !            50: #define        STOP_EPSILON    0.1
        !            51: void PM_ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
        !            52: {
        !            53:        float   backoff;
        !            54:        float   change;
        !            55:        int             i;
        !            56:        
        !            57:        backoff = DotProduct (in, normal) * overbounce;
        !            58:        for (i=0 ; i<3 ; i++)
        !            59:        {
        !            60:                change = normal[i]*backoff;
        !            61:                out[i] = in[i] - change;
        !            62:                if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
        !            63:                        out[i] = 0;
        !            64:        }
        !            65: }
        !            66: /*
        !            67: ==================
        !            68: PM_StepSlideMove
        !            69: Each intersection will try to step over the obstruction instead of
        !            70: sliding along it.
        !            71: Returns a new origin, velocity, and contact entity
        !            72: Does not modify any world state?
        !            73: ==================
        !            74: */
        !            75: #define        MIN_STEP_NORMAL 0.7             // can't step up onto very steep slopes
        !            76: #define        MAX_CLIP_PLANES 5
        !            77: void PM_StepSlideMove_ (void)
        !            78: {
        !            79:        int                     bumpcount, numbumps;
        !            80:        vec3_t          dir;
        !            81:        float           d, rub;
        !            82:        int                     numplanes;
        !            83:        vec3_t          planes[MAX_CLIP_PLANES];
        !            84:        vec3_t          primal_velocity;
        !            85:        int                     i;
        !            86:        trace_t trace;
        !            87:        vec3_t          end;
        !            88:        float           time_left;
        !            89:        
        !            90:        numbumps = 4;
        !            91:        
        !            92:        VectorCopy (pml.velocity, primal_velocity);
        !            93:        numplanes = 0;
        !            94:        
        !            95:        time_left = pml.frametime;
        !            96:        for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
        !            97:        {
        !            98:                for (i=0 ; i<3 ; i++)
        !            99:                        end[i] = pml.origin[i] + time_left * pml.velocity[i];
        !           100:                trace = pm->trace (pml.origin, pm->mins, pm->maxs, end);
        !           101:                if (trace.allsolid)
        !           102:                {       // entity is trapped in another solid
        !           103:                        pml.velocity[2] = 0;    // don't build up falling damage
        !           104:                        return;
        !           105:                }
        !           106:                if (trace.fraction > 0)
        !           107:                {       // actually covered some distance
        !           108:                        VectorCopy (trace.endpos, pml.origin);
        !           109:                        numplanes = 0;
        !           110:                }
        !           111:                if (trace.fraction == 1)
        !           112:                         break;         // moved the entire distance
        !           113:                // save entity for contact
        !           114:                if (pm->numtouch < MAXTOUCH && trace.ent)
        !           115:                {
        !           116:                        pm->touchents[pm->numtouch] = trace.ent;
        !           117:                        pm->numtouch++;
        !           118:                }
        !           119:                
        !           120:                time_left -= time_left * trace.fraction;
        !           121:                // slide along this plane
        !           122:                if (numplanes >= MAX_CLIP_PLANES)
        !           123:                {       // this shouldn't really happen
        !           124:                        VectorCopy (vec3_origin, pml.velocity);
        !           125:                        break;
        !           126:                }
        !           127:                VectorCopy (trace.plane.normal, planes[numplanes]);
        !           128:                numplanes++;
        !           129:                //
        !           130:                // modify velocity so it parallels all of the clip planes
        !           131:                //
        !           132:                if (numplanes == 1)
        !           133:                {       // go along this plane
        !           134:                        VectorCopy (pml.velocity, dir);
        !           135:                        VectorNormalize (dir);
        !           136:                        rub = 1.0 + 0.5 * DotProduct (dir, planes[0]);
        !           137: 
        !           138:                        // slide along the plane
        !           139:                        PM_ClipVelocity (pml.velocity, planes[0], pml.velocity, 1.01);
        !           140:                        // rub some extra speed off on xy axis
        !           141:                        // not on Z, or you can scrub down walls
        !           142:                        pml.velocity[0] *= rub;
        !           143:                        pml.velocity[1] *= rub;
        !           144:                        pml.velocity[2] *= rub;
        !           145:                }
        !           146:                else if (numplanes == 2)
        !           147:                {       // go along the crease
        !           148:                        VectorCopy (pml.velocity, dir);
        !           149:                        VectorNormalize (dir);
        !           150:                        rub = 1.0 + 0.5 * DotProduct (dir, planes[0]);
        !           151: 
        !           152:                        // slide along the plane
        !           153:                        CrossProduct (planes[0], planes[1], dir);
        !           154:                        d = DotProduct (dir, pml.velocity);
        !           155:                        VectorScale (dir, d, pml.velocity);
        !           156:                        // rub some extra speed off
        !           157:                        VectorScale (pml.velocity, rub, pml.velocity);
        !           158:                }
        !           159:                else
        !           160:                {
        !           161: //                     Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
        !           162:                        VectorCopy (vec3_origin, pml.velocity);
        !           163:                        break;
        !           164:                }
        !           165:                //
        !           166:                // if velocity is against the original velocity, stop dead
        !           167:                // to avoid tiny occilations in sloping corners
        !           168:                //
        !           169:                if (DotProduct (pml.velocity, primal_velocity) <= 0)
        !           170:                {
        !           171:                        VectorCopy (vec3_origin, pml.velocity);
        !           172:                        break;
        !           173:                }
        !           174:        }
        !           175:        if (pm->s.pm_time)
        !           176:        {
        !           177:                VectorCopy (primal_velocity, pml.velocity);
        !           178:        }
        !           179: }
        !           180: 
        !           181: /*
        !           182: ==================
        !           183: PM_StepSlideMove
        !           184: 
        !           185: ==================
        !           186: */
        !           187: void PM_StepSlideMove (void)
        !           188: {
        !           189:        vec3_t          start_o, start_v;
        !           190:        vec3_t          down_o, down_v;
        !           191:        trace_t         trace;
        !           192:        float           down_dist, up_dist;
        !           193:        vec3_t          delta;
        !           194:        vec3_t          up, down;
        !           195: 
        !           196:        VectorCopy (pml.origin, start_o);
        !           197:        VectorCopy (pml.velocity, start_v);
        !           198: 
        !           199:        PM_StepSlideMove_ ();
        !           200: 
        !           201:        VectorCopy (pml.origin, down_o);
        !           202:        VectorCopy (pml.velocity, down_v);
        !           203: 
        !           204:        VectorCopy (start_o, up);
        !           205:        up[2] += STEPSIZE;
        !           206: 
        !           207:        trace = pm->trace (up, pm->mins, pm->maxs, up);
        !           208:        if (trace.allsolid)
        !           209:                return;         // can't step up
        !           210: 
        !           211:        // try sliding above
        !           212:        VectorCopy (up, pml.origin);
        !           213:        VectorCopy (start_v, pml.velocity);
        !           214: 
        !           215:        PM_StepSlideMove_ ();
        !           216: 
        !           217:        // push down the final amount
        !           218:        VectorCopy (pml.origin, down);
        !           219:        down[2] -= STEPSIZE;
        !           220:        trace = pm->trace (pml.origin, pm->mins, pm->maxs, down);
        !           221:        if (!trace.allsolid)
        !           222:        {
        !           223:                VectorCopy (trace.endpos, pml.origin);
        !           224:        }
        !           225: 
        !           226:        VectorSubtract (pml.origin, up, delta);
        !           227:        up_dist = DotProduct (delta, start_v);
        !           228: 
        !           229:        VectorSubtract (down_o, start_o, delta);
        !           230:        down_dist = DotProduct (delta, start_v);
        !           231: 
        !           232:        if (down_dist > up_dist || trace.plane.normal[2] < MIN_STEP_NORMAL)
        !           233:        {
        !           234:                VectorCopy (down_o, pml.origin);
        !           235:                VectorCopy (down_v, pml.velocity);
        !           236:                return;
        !           237:        }
        !           238: 
        !           239: }
        !           240: 
        !           241: /*
        !           242: ==================
        !           243: PM_Friction
        !           244: Handles both ground friction and water friction
        !           245: ==================
        !           246: */
        !           247: void PM_Friction (void)
        !           248: {
        !           249:        float   *vel;
        !           250:        float   speed, newspeed, control;
        !           251:        float   friction;
        !           252:        float   drop;
        !           253:        
        !           254:        vel = pml.velocity;
        !           255:        
        !           256:        speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1] + vel[2]*vel[2]);
        !           257:        if (speed < 1)
        !           258:        {
        !           259:                vel[0] = 0;
        !           260:                vel[1] = 0;
        !           261:                return;
        !           262:        }
        !           263:        drop = 0;
        !           264: // apply ground friction
        !           265:        if ((pm->groundentity && pml.groundsurface && !(pml.groundsurface->flags & SURF_SLICK) ) || (pml.ladder) )
        !           266:        {
        !           267:                friction = pm_friction;
        !           268:                control = speed < pm_stopspeed ? pm_stopspeed : speed;
        !           269:                drop += control*friction*pml.frametime;
        !           270:        }
        !           271: // apply water friction
        !           272:        if (pm->waterlevel && !pml.ladder)
        !           273:                drop += speed*pm_waterfriction*pm->waterlevel*pml.frametime;
        !           274: // scale the velocity
        !           275:        newspeed = speed - drop;
        !           276:        if (newspeed < 0)
        !           277:        {
        !           278:                newspeed = 0;
        !           279:        }
        !           280:        newspeed /= speed;
        !           281:        vel[0] = vel[0] * newspeed;
        !           282:        vel[1] = vel[1] * newspeed;
        !           283:        vel[2] = vel[2] * newspeed;
        !           284: }
        !           285: /*
        !           286: ==============
        !           287: PM_Accelerate
        !           288: Handles user intended acceleration
        !           289: ==============
        !           290: */
        !           291: void PM_Accelerate (vec3_t wishdir, float wishspeed, float accel)
        !           292: {
        !           293:        int                     i;
        !           294:        float           addspeed, accelspeed, currentspeed;
        !           295: 
        !           296:        currentspeed = DotProduct (pml.velocity, wishdir);
        !           297:        addspeed = wishspeed - currentspeed;
        !           298:        if (addspeed <= 0)
        !           299:                return;
        !           300:        accelspeed = accel*pml.frametime*wishspeed;
        !           301:        if (accelspeed > addspeed)
        !           302:                accelspeed = addspeed;
        !           303:        
        !           304:        for (i=0 ; i<3 ; i++)
        !           305:                pml.velocity[i] += accelspeed*wishdir[i];       
        !           306: }
        !           307: /*
        !           308: =============
        !           309: PM_AddCurrents
        !           310: =============
        !           311: */
        !           312: void PM_AddCurrents (vec3_t    wishvel)
        !           313: {
        !           314:        vec3_t  v;
        !           315:        float   s;
        !           316:        //
        !           317:        // account for ladders
        !           318:        //
        !           319:        if (pml.ladder && fabs(pml.velocity[2]) <= 200)
        !           320:        {
        !           321:                if ((pm->viewangles[PITCH] <= -15) && (pm->cmd.forwardmove > 0))
        !           322:                        wishvel[2] = 200;
        !           323:                else if ((pm->viewangles[PITCH] >= 15) && (pm->cmd.forwardmove > 0))
        !           324:                        wishvel[2] = -200;
        !           325:                else if (pm->cmd.upmove > 0)
        !           326:                        wishvel[2] = 200;
        !           327:                else if (pm->cmd.upmove < 0)
        !           328:                        wishvel[2] = -200;
        !           329:                else
        !           330:                        wishvel[2] = 0;
        !           331:                // limit horizontal speed when on a ladder
        !           332:                if (wishvel[0] < -25)
        !           333:                        wishvel[0] = -25;
        !           334:                else if (wishvel[0] > 25)
        !           335:                        wishvel[0] = 25;
        !           336:                if (wishvel[1] < -25)
        !           337:                        wishvel[1] = -25;
        !           338:                else if (wishvel[1] > 25)
        !           339:                        wishvel[1] = 25;
        !           340:        }
        !           341:        //
        !           342:        // add water currents
        !           343:        //
        !           344:        if (pm->watertype & MASK_CURRENT)
        !           345:        {
        !           346:                VectorClear (v);
        !           347:                if (pm->watertype & CONTENTS_CURRENT_0)
        !           348:                        v[0] += 1;
        !           349:                if (pm->watertype & CONTENTS_CURRENT_90)
        !           350:                        v[1] += 1;
        !           351:                if (pm->watertype & CONTENTS_CURRENT_180)
        !           352:                        v[0] -= 1;
        !           353:                if (pm->watertype & CONTENTS_CURRENT_270)
        !           354:                        v[1] -= 1;
        !           355:                if (pm->watertype & CONTENTS_CURRENT_UP)
        !           356:                        v[2] += 1;
        !           357:                if (pm->watertype & CONTENTS_CURRENT_DOWN)
        !           358:                        v[2] -= 1;
        !           359:                s = pm_waterspeed;
        !           360:                if ((pm->waterlevel == 1) && (pm->groundentity))
        !           361:                        s /= 2;
        !           362:                VectorMA (wishvel, s, v, wishvel);
        !           363:        }
        !           364:        //
        !           365:        // add conveyor belt velocities
        !           366:        //
        !           367:        if (pm->groundentity)
        !           368:        {
        !           369:                VectorClear (v);
        !           370:                if (pml.groundcontents & CONTENTS_CURRENT_0)
        !           371:                        v[0] += 1;
        !           372:                if (pml.groundcontents & CONTENTS_CURRENT_90)
        !           373:                        v[1] += 1;
        !           374:                if (pml.groundcontents & CONTENTS_CURRENT_180)
        !           375:                        v[0] -= 1;
        !           376:                if (pml.groundcontents & CONTENTS_CURRENT_270)
        !           377:                        v[1] -= 1;
        !           378:                if (pml.groundcontents & CONTENTS_CURRENT_UP)
        !           379:                        v[2] += 1;
        !           380:                if (pml.groundcontents & CONTENTS_CURRENT_DOWN)
        !           381:                        v[2] -= 1;
        !           382: 
        !           383:                VectorMA (wishvel, 100 /* pm->groundentity->speed */, v, wishvel);
        !           384:        }
        !           385: }
        !           386: /*
        !           387: ===================
        !           388: PM_WaterMove
        !           389: ===================
        !           390: */
        !           391: void PM_WaterMove (void)
        !           392: {
        !           393:        int             i;
        !           394:        vec3_t  wishvel;
        !           395:        float   wishspeed;
        !           396:        vec3_t  wishdir;
        !           397: //
        !           398: // user intentions
        !           399: //
        !           400:        for (i=0 ; i<3 ; i++)
        !           401:                wishvel[i] = pml.forward[i]*pm->cmd.forwardmove + pml.right[i]*pm->cmd.sidemove;
        !           402:        if (!pm->cmd.forwardmove && !pm->cmd.sidemove && !pm->cmd.upmove)
        !           403:                wishvel[2] -= 60;               // drift towards bottom
        !           404:        else
        !           405:                wishvel[2] += pm->cmd.upmove;
        !           406:        PM_AddCurrents (wishvel);
        !           407:        VectorCopy (wishvel, wishdir);
        !           408:        wishspeed = VectorNormalize(wishdir);
        !           409:        if (wishspeed > pm_maxspeed)
        !           410:        {
        !           411:                VectorScale (wishvel, pm_maxspeed/wishspeed, wishvel);
        !           412:                wishspeed = pm_maxspeed;
        !           413:        }
        !           414:        wishspeed *= 0.5;
        !           415:        PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate);
        !           416:        PM_StepSlideMove ();
        !           417: }
        !           418: /*
        !           419: ===================
        !           420: PM_AirMove
        !           421: ===================
        !           422: */
        !           423: void PM_AirMove (void)
        !           424: {
        !           425:        int                     i;
        !           426:        vec3_t          wishvel;
        !           427:        float           fmove, smove;
        !           428:        vec3_t          wishdir;
        !           429:        float           wishspeed;
        !           430:        float           maxspeed;
        !           431:        fmove = pm->cmd.forwardmove;
        !           432:        smove = pm->cmd.sidemove;
        !           433:        
        !           434:        pml.forward[2] = 0;
        !           435:        pml.right[2] = 0;
        !           436:        VectorNormalize (pml.forward);
        !           437:        VectorNormalize (pml.right);
        !           438:        for (i=0 ; i<2 ; i++)
        !           439:                wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
        !           440:        wishvel[2] = 0;
        !           441:        PM_AddCurrents (wishvel);
        !           442:        VectorCopy (wishvel, wishdir);
        !           443:        wishspeed = VectorNormalize(wishdir);
        !           444: //
        !           445: // clamp to server defined max speed
        !           446: //
        !           447:        maxspeed = (pm->s.pm_flags & PMF_DUCKED) ? pm_duckspeed : pm_maxspeed;
        !           448:        if (wishspeed > maxspeed)
        !           449:        {
        !           450:                VectorScale (wishvel, maxspeed/wishspeed, wishvel);
        !           451:                wishspeed = maxspeed;
        !           452:        }
        !           453:        
        !           454:        if ( pml.ladder )
        !           455:        {
        !           456:                PM_Accelerate (wishdir, wishspeed, pm_accelerate);
        !           457:                if (!wishvel[2])
        !           458:                {
        !           459:                        if (pml.velocity[2] > 0)
        !           460:                        {
        !           461:                                pml.velocity[2] -= pm->s.gravity * pml.frametime;
        !           462:                                if (pml.velocity[2] < 0)
        !           463:                                        pml.velocity[2]  = 0;
        !           464:                        }
        !           465:                        else
        !           466:                        {
        !           467:                                pml.velocity[2] += pm->s.gravity * pml.frametime;
        !           468:                                if (pml.velocity[2] > 0)
        !           469:                                        pml.velocity[2]  = 0;
        !           470:                        }
        !           471:                }
        !           472:                PM_StepSlideMove ();
        !           473:        }
        !           474:        else if ( pm->groundentity )
        !           475:        {       // walking on ground
        !           476:                PM_Accelerate (wishdir, wishspeed, pm_accelerate);
        !           477:                pml.velocity[2] = 0;
        !           478:                if (!pml.velocity[0] && !pml.velocity[1])
        !           479:                        return;
        !           480:                PM_StepSlideMove ();
        !           481:        }
        !           482:        else
        !           483:        {       // not on ground, so little effect on velocity
        !           484:                PM_Accelerate (wishdir, wishspeed, pm_airaccelerate);
        !           485:                // add gravity
        !           486:                pml.velocity[2] -= pm->s.gravity * pml.frametime;
        !           487:                PM_StepSlideMove ();
        !           488:        }
        !           489: }
        !           490: /*
        !           491: =============
        !           492: PM_CatagorizePosition
        !           493: =============
        !           494: */
        !           495: void PM_CatagorizePosition (void)
        !           496: {
        !           497:        vec3_t          point;
        !           498:        int                     cont;
        !           499:        trace_t         trace;
        !           500:        int                     sample1;
        !           501:        int                     sample2;
        !           502: // if the player hull point one unit down is solid, the player
        !           503: // is on ground
        !           504: // see if standing on something solid  
        !           505:        point[0] = pml.origin[0];
        !           506:        point[1] = pml.origin[1];
        !           507:        point[2] = pml.origin[2] - 0.25;
        !           508:        if (pml.velocity[2] > 100)
        !           509:        {
        !           510:                pm->s.pm_flags &= ~PMF_ON_GROUND;
        !           511:                pm->groundentity = NULL;
        !           512:        }
        !           513:        else
        !           514:        {
        !           515:                trace = pm->trace (pml.origin, pm->mins, pm->maxs, point);
        !           516:                pml.groundplane = trace.plane;
        !           517:                pml.groundsurface = trace.surface;
        !           518:                pml.groundcontents = trace.contents;
        !           519: 
        !           520:                if (!trace.ent || (trace.plane.normal[2] < 0.7 && !trace.startsolid) )
        !           521:                {
        !           522:                        pm->groundentity = NULL;
        !           523:                        pm->s.pm_flags &= ~PMF_ON_GROUND;
        !           524:                }
        !           525:                else
        !           526:                {
        !           527:                        pm->groundentity = trace.ent;
        !           528: 
        !           529:                        // hitting solid ground will end a waterjump
        !           530:                        if (pm->s.pm_flags & PMF_TIME_WATERJUMP)
        !           531:                        {
        !           532:                                pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
        !           533:                                pm->s.pm_time = 0;
        !           534:                        }
        !           535: 
        !           536:                        if (! (pm->s.pm_flags & PMF_ON_GROUND) )
        !           537:                        {       // just hit the ground
        !           538:                                pm->s.pm_flags |= PMF_ON_GROUND;
        !           539:                                // don't do landing time if we were just going down a slope
        !           540:                                if (pml.velocity[2] < -200)
        !           541:                                {
        !           542:                                        pm->s.pm_flags |= PMF_TIME_LAND;
        !           543:                                        // don't allow another jump for a little while
        !           544:                                        if (pml.velocity[2] < -400)
        !           545:                                                pm->s.pm_time = 25;     
        !           546:                                        else
        !           547:                                                pm->s.pm_time = 18;
        !           548:                                }
        !           549:                        }
        !           550:                }
        !           551:                if (trace.fraction < 1.0 && trace.ent && pml.velocity[2] < 0)
        !           552:                        pml.velocity[2] = 0;
        !           553: 
        !           554:                if (pm->numtouch < MAXTOUCH && trace.ent)
        !           555:                {
        !           556:                        pm->touchents[pm->numtouch] = trace.ent;
        !           557:                        pm->numtouch++;
        !           558:                }
        !           559:        }
        !           560: //
        !           561: // get waterlevel, accounting for ducking
        !           562: //
        !           563:        pm->waterlevel = 0;
        !           564:        pm->watertype = 0;
        !           565:        sample2 = pm->viewheight - pm->mins[2];
        !           566:        sample1 = sample2 / 2;
        !           567:        point[2] = pml.origin[2] + pm->mins[2] + 1;     
        !           568:        cont = pm->pointcontents (point);
        !           569:        if (cont & MASK_WATER)
        !           570:        {
        !           571:                pm->watertype = cont;
        !           572:                pm->waterlevel = 1;
        !           573:                point[2] = pml.origin[2] + pm->mins[2] + sample1;
        !           574:                cont = pm->pointcontents (point);
        !           575:                if (cont & MASK_WATER)
        !           576:                {
        !           577:                        pm->waterlevel = 2;
        !           578:                        point[2] = pml.origin[2] + pm->mins[2] + sample2;
        !           579:                        cont = pm->pointcontents (point);
        !           580:                        if (cont & MASK_WATER)
        !           581:                                pm->waterlevel = 3;
        !           582:                }
        !           583:        }
        !           584: }
        !           585: /*
        !           586: =============
        !           587: PM_CheckJump
        !           588: =============
        !           589: */
        !           590: void PM_CheckJump (void)
        !           591: {
        !           592:        if (pm->s.pm_flags & PMF_TIME_LAND)
        !           593:        {       // hasn't been long enough since landing to jump again
        !           594:                return;
        !           595:        }
        !           596:        if (pm->cmd.upmove < 10)
        !           597:        {       // not holding jump
        !           598:                pm->s.pm_flags &= ~PMF_JUMP_HELD;
        !           599:                return;
        !           600:        }
        !           601: 
        !           602:        // must wait for jump to be released
        !           603:        if (pm->s.pm_flags & PMF_JUMP_HELD)
        !           604:                return;
        !           605: 
        !           606:        if (pm->s.pm_type == PM_DEAD)
        !           607:                return;
        !           608:        if (pm->waterlevel >= 2)
        !           609:        {       // swimming, not jumping
        !           610:                pm->groundentity = NULL;
        !           611:                if (pml.velocity[2] <= -300)
        !           612:                        return;
        !           613: 
        !           614:                if (pm->watertype == CONTENTS_WATER)
        !           615:                        pml.velocity[2] = 100;
        !           616:                else if (pm->watertype == CONTENTS_SLIME)
        !           617:                        pml.velocity[2] = 80;
        !           618:                else
        !           619:                        pml.velocity[2] = 50;
        !           620:                return;
        !           621:        }
        !           622:        if (pm->groundentity == NULL)
        !           623:                return;         // in air, so no effect
        !           624:        pm->s.pm_flags |= PMF_JUMP_HELD;
        !           625: 
        !           626:        pm->groundentity = NULL;
        !           627:        pml.velocity[2] = 270;
        !           628: }
        !           629: /*
        !           630: =============
        !           631: PM_CheckSpecialMovement
        !           632: =============
        !           633: */
        !           634: void PM_CheckSpecialMovement (void)
        !           635: {
        !           636:        vec3_t  spot;
        !           637:        int             cont;
        !           638:        vec3_t  flatforward;
        !           639:        trace_t trace;
        !           640: 
        !           641:        if (pm->s.pm_time)
        !           642:                return;
        !           643: 
        !           644:        pml.ladder = false;
        !           645:        // check for ladder
        !           646:        flatforward[0] = pml.forward[0];
        !           647:        flatforward[1] = pml.forward[1];
        !           648:        flatforward[2] = 0;
        !           649:        VectorNormalize (flatforward);
        !           650:        VectorMA (pml.origin, 1, flatforward, spot);
        !           651:        trace = pm->trace (pml.origin, pm->mins, pm->maxs, spot);
        !           652:        if ((trace.fraction < 1) && (trace.contents & CONTENTS_LADDER))
        !           653:                pml.ladder = true;
        !           654:        // check for water jump
        !           655:        if (pm->waterlevel != 2)
        !           656:                return;
        !           657:        VectorMA (pml.origin, 30, flatforward, spot);
        !           658:        spot[2] += 4;
        !           659:        cont = pm->pointcontents (spot);
        !           660:        if (!(cont & CONTENTS_SOLID))
        !           661:                return;
        !           662:        spot[2] += 16;
        !           663:        cont = pm->pointcontents (spot);
        !           664:        if (cont)
        !           665:                return;
        !           666:        // jump out of water
        !           667:        VectorScale (pml.forward, 200, pml.velocity);
        !           668:        pml.velocity[2] = 350;
        !           669: 
        !           670:        pm->s.pm_flags |= PMF_TIME_WATERJUMP;
        !           671:        pm->s.pm_time = 255;
        !           672: }
        !           673: /*
        !           674: ===============
        !           675: PM_NoclipMove
        !           676: ===============
        !           677: */
        !           678: void PM_NoclipMove (void)
        !           679: {
        !           680:        float   speed, drop, friction, control, newspeed;
        !           681:        float   currentspeed, addspeed, accelspeed;
        !           682:        int                     i;
        !           683:        vec3_t          wishvel;
        !           684:        float           fmove, smove;
        !           685:        vec3_t          wishdir;
        !           686:        float           wishspeed;
        !           687: 
        !           688:        pm->viewheight = 22;
        !           689:        // friction
        !           690:        speed = VectorLength (pml.velocity);
        !           691:        if (speed < 1)
        !           692:        {
        !           693:                VectorCopy (vec3_origin, pml.velocity);
        !           694:        }
        !           695:        else
        !           696:        {
        !           697:                drop = 0;
        !           698:                friction = pm_friction*1.5;     // extra friction
        !           699:                control = speed < pm_stopspeed ? pm_stopspeed : speed;
        !           700:                drop += control*friction*pml.frametime;
        !           701:                // scale the velocity
        !           702:                newspeed = speed - drop;
        !           703:                if (newspeed < 0)
        !           704:                        newspeed = 0;
        !           705:                newspeed /= speed;
        !           706:                VectorScale (pml.velocity, newspeed, pml.velocity);
        !           707:        }
        !           708:        // accelerate
        !           709:        fmove = pm->cmd.forwardmove;
        !           710:        smove = pm->cmd.sidemove;
        !           711:        
        !           712:        VectorNormalize (pml.forward);
        !           713:        VectorNormalize (pml.right);
        !           714:        for (i=0 ; i<3 ; i++)
        !           715:                wishvel[i] = pml.forward[i]*fmove + pml.right[i]*smove;
        !           716:        wishvel[2] += pm->cmd.upmove;
        !           717:        VectorCopy (wishvel, wishdir);
        !           718:        wishspeed = VectorNormalize(wishdir);
        !           719:        //
        !           720:        // clamp to server defined max speed
        !           721:        //
        !           722:        if (wishspeed > pm_maxspeed)
        !           723:        {
        !           724:                VectorScale (wishvel, pm_maxspeed/wishspeed, wishvel);
        !           725:                wishspeed = pm_maxspeed;
        !           726:        }
        !           727:        currentspeed = DotProduct(pml.velocity, wishdir);
        !           728:        addspeed = wishspeed - currentspeed;
        !           729:        if (addspeed <= 0)
        !           730:                return;
        !           731:        accelspeed = pm_accelerate*pml.frametime*wishspeed;
        !           732:        if (accelspeed > addspeed)
        !           733:                accelspeed = addspeed;
        !           734:        
        !           735:        for (i=0 ; i<3 ; i++)
        !           736:                pml.velocity[i] += accelspeed*wishdir[i];       
        !           737:        // move
        !           738:        VectorMA (pml.origin, pml.frametime, pml.velocity, pml.origin);
        !           739: }
        !           740: /*
        !           741: ==============
        !           742: PM_CheckDuck
        !           743: 
        !           744: Sets mins, maxs, and pm->viewheight
        !           745: ==============
        !           746: */
        !           747: void PM_CheckDuck (void)
        !           748: {
        !           749:        trace_t trace;
        !           750: 
        !           751:        pm->mins[0] = -16;
        !           752:        pm->mins[1] = -16;
        !           753: 
        !           754:        pm->maxs[0] = 16;
        !           755:        pm->maxs[1] = 16;
        !           756:        if (pm->s.pm_type == PM_GIB)
        !           757:        {
        !           758:                pm->mins[2] = 0;
        !           759:                pm->maxs[2] = 16;
        !           760:                pm->viewheight = 8;
        !           761:                return;
        !           762:        }
        !           763: 
        !           764:        pm->mins[2] = -24;
        !           765: 
        !           766:        if (pm->s.pm_type == PM_DEAD)
        !           767:        {
        !           768:                pm->s.pm_flags |= PMF_DUCKED;
        !           769:        }
        !           770:        else if (pm->cmd.upmove < 0 && (pm->s.pm_flags & PMF_ON_GROUND) )
        !           771:        {       // duck
        !           772:                pm->s.pm_flags |= PMF_DUCKED;
        !           773:        }
        !           774:        else
        !           775:        {       // stand up if possible
        !           776:                if (pm->s.pm_flags & PMF_DUCKED)
        !           777:                {
        !           778:                        // try to stand up
        !           779:                        pm->maxs[2] = 32;
        !           780:                        trace = pm->trace (pml.origin, pm->mins, pm->maxs, pml.origin);
        !           781:                        if (!trace.allsolid)
        !           782:                                pm->s.pm_flags &= ~PMF_DUCKED;
        !           783:                }
        !           784:        }
        !           785: 
        !           786:        if (pm->s.pm_flags & PMF_DUCKED)
        !           787:        {
        !           788:                pm->maxs[2] = 4;
        !           789:                pm->viewheight = -2;
        !           790:        }
        !           791:        else
        !           792:        {
        !           793:                pm->maxs[2] = 32;
        !           794:                pm->viewheight = 22;
        !           795:        }
        !           796: }
        !           797: 
        !           798: /*
        !           799: ==============
        !           800: PM_DeadMove
        !           801: ==============
        !           802: */
        !           803: void PM_DeadMove (void)
        !           804: {
        !           805:        float   forward;
        !           806: 
        !           807:        if (!pm->groundentity)
        !           808:                return;
        !           809: 
        !           810:        // extra friction
        !           811: 
        !           812:        forward = VectorLength (pml.velocity);
        !           813:        forward -= 20;
        !           814:        if (forward <= 0)
        !           815:        {
        !           816:                VectorClear (pml.velocity);
        !           817:        }
        !           818:        else
        !           819:        {
        !           820:                VectorNormalize (pml.velocity);
        !           821:                VectorScale (pml.velocity, forward, pml.velocity);
        !           822:        }
        !           823: }
        !           824: 
        !           825: 
        !           826: qboolean       PM_GoodPosition (void)
        !           827: {
        !           828:        trace_t trace;
        !           829:        vec3_t  origin, end;
        !           830:        int             i;
        !           831: 
        !           832:        if (pm->s.pm_type == PM_SPECTATOR)
        !           833:                return true;
        !           834: 
        !           835:        for (i=0 ; i<3 ; i++)
        !           836:                origin[i] = end[i] = pm->s.origin[i]*0.125;
        !           837:        trace = pm->trace (origin, pm->mins, pm->maxs, end);
        !           838: 
        !           839:        return !trace.allsolid;
        !           840: }
        !           841: 
        !           842: /*
        !           843: ================
        !           844: PM_SnapPosition
        !           845: 
        !           846: On exit, the origin will have a value that is pre-quantized to the 0.125
        !           847: precision of the network channel and in a valid position.
        !           848: ================
        !           849: */
        !           850: void PM_SnapPosition (void)
        !           851: {
        !           852:        int             sign[3];
        !           853:        int             i, j, bits;
        !           854:        short   base[3];
        !           855:        // try all single bits first
        !           856:        static int jitterbits[8] = {0,4,1,2,3,5,6,7};
        !           857: 
        !           858:        // snap velocity to eigths
        !           859:        for (i=0 ; i<3 ; i++)
        !           860:                pm->s.velocity[i] = (int)(pml.velocity[i]*8);
        !           861: 
        !           862:        for (i=0 ; i<3 ; i++)
        !           863:        {
        !           864:                if (pml.origin[i] >= 0)
        !           865:                        sign[i] = 1;
        !           866:                else 
        !           867:                        sign[i] = -1;
        !           868:                pm->s.origin[i] = (int)(pml.origin[i]*8);
        !           869:                if (pm->s.origin[i]*0.125 == pml.origin[i])
        !           870:                        sign[i] = 0;
        !           871:        }
        !           872:        VectorCopy (pm->s.origin, base);
        !           873: 
        !           874:        // try all combinations
        !           875:        for (j=0 ; j<8 ; j++)
        !           876:        {
        !           877:                bits = jitterbits[j];
        !           878:                VectorCopy (base, pm->s.origin);
        !           879:                for (i=0 ; i<3 ; i++)
        !           880:                        if (bits & (1<<i) )
        !           881:                                pm->s.origin[i] += sign[i];
        !           882: 
        !           883:                if (PM_GoodPosition ())
        !           884:                        return;
        !           885:        }
        !           886: 
        !           887:        // go back to the last position
        !           888:        VectorCopy (pml.previous_origin, pm->s.origin);
        !           889: //     Com_DPrintf ("using previous_origin\n");
        !           890: }
        !           891: 
        !           892: /*
        !           893: ================
        !           894: PM_InitialSnapPosition
        !           895: 
        !           896: ================
        !           897: */
        !           898: void PM_InitialSnapPosition (void)
        !           899: {
        !           900:        int             x, y, z;
        !           901:        short   base[3];
        !           902: 
        !           903:        VectorCopy (pm->s.origin, base);
        !           904: 
        !           905:        for (z=1 ; z>=-1 ; z--)
        !           906:        {
        !           907:                pm->s.origin[2] = base[2] + z;
        !           908:                for (y=1 ; y>=-1 ; y--)
        !           909:                {
        !           910:                        pm->s.origin[1] = base[1] + y;
        !           911:                        for (x=1 ; x>=-1 ; x--)
        !           912:                        {
        !           913:                                pm->s.origin[0] = base[0] + x;
        !           914:                                if (PM_GoodPosition ())
        !           915:                                {
        !           916:                                        pml.origin[0] = pm->s.origin[0]*0.125;
        !           917:                                        pml.origin[1] = pm->s.origin[1]*0.125;
        !           918:                                        pml.origin[2] = pm->s.origin[2]*0.125;
        !           919:                                        VectorCopy (pm->s.origin, pml.previous_origin);
        !           920:                                        return;
        !           921:                                }
        !           922:                        }
        !           923:                }
        !           924:        }
        !           925: 
        !           926:        Com_DPrintf ("Bad InitialSnapPosition\n");
        !           927: }
        !           928: 
        !           929: /*
        !           930: ================
        !           931: PM_ClampAngles
        !           932: 
        !           933: ================
        !           934: */
        !           935: void PM_ClampAngles (void)
        !           936: {
        !           937:        short   temp;
        !           938:        int             i;
        !           939: 
        !           940:        if (pm->s.pm_flags & PMF_TIME_TELEPORT)
        !           941:        {
        !           942:                pm->viewangles[YAW] = SHORT2ANGLE(pm->cmd.angles[YAW] + pm->s.delta_angles[YAW]);
        !           943:                pm->viewangles[PITCH] = 0;
        !           944:                pm->viewangles[ROLL] = 0;
        !           945:        }
        !           946:        else
        !           947:        {
        !           948:                // circularly clamp the angles with deltas
        !           949:                for (i=0 ; i<3 ; i++)
        !           950:                {
        !           951:                        temp = pm->cmd.angles[i] + pm->s.delta_angles[i];
        !           952:                        pm->viewangles[i] = SHORT2ANGLE(temp);
        !           953:                }
        !           954: 
        !           955:                // don't let the player look up or down more than 90 degrees
        !           956:                if (pm->viewangles[PITCH] > 89 && pm->viewangles[PITCH] < 180)
        !           957:                        pm->viewangles[PITCH] = 89;
        !           958:                else if (pm->viewangles[PITCH] < 271 && pm->viewangles[PITCH] >= 180)
        !           959:                        pm->viewangles[PITCH] = 271;
        !           960:        }
        !           961:        AngleVectors (pm->viewangles, pml.forward, pml.right, pml.up);
        !           962: }
        !           963: 
        !           964: /*
        !           965: ================
        !           966: Pmove
        !           967: 
        !           968: Can be called by either the server or the client
        !           969: ================
        !           970: */
        !           971: void Pmove (pmove_t *pmove)
        !           972: {
        !           973:        pm = pmove;
        !           974: 
        !           975:        // clear results
        !           976:        pm->numtouch = 0;
        !           977:        VectorClear (pm->viewangles);
        !           978:        pm->viewheight = 0;
        !           979:        pm->groundentity = 0;
        !           980:        pm->watertype = 0;
        !           981:        pm->waterlevel = 0;
        !           982: 
        !           983:        // clear all pmove local vars
        !           984:        memset (&pml, 0, sizeof(pml));
        !           985: 
        !           986:        // convert origin and velocity to float values
        !           987:        pml.origin[0] = pm->s.origin[0]*0.125;
        !           988:        pml.origin[1] = pm->s.origin[1]*0.125;
        !           989:        pml.origin[2] = pm->s.origin[2]*0.125;
        !           990: 
        !           991:        pml.velocity[0] = pm->s.velocity[0]*0.125;
        !           992:        pml.velocity[1] = pm->s.velocity[1]*0.125;
        !           993:        pml.velocity[2] = pm->s.velocity[2]*0.125;
        !           994: 
        !           995:        // save old org in case we get stuck
        !           996:        VectorCopy (pm->s.origin, pml.previous_origin);
        !           997: 
        !           998:        pml.frametime = pm->cmd.msec * 0.001;
        !           999: 
        !          1000:        PM_ClampAngles ();
        !          1001: 
        !          1002:        if (pm->s.pm_type == PM_SPECTATOR)
        !          1003:        {
        !          1004:                PM_NoclipMove ();
        !          1005:                PM_SnapPosition ();
        !          1006:                return;
        !          1007:        }
        !          1008: 
        !          1009:        if (pm->s.pm_type >= PM_DEAD)
        !          1010:        {
        !          1011:                pm->cmd.forwardmove = 0;
        !          1012:                pm->cmd.sidemove = 0;
        !          1013:                pm->cmd.upmove = 0;
        !          1014:        }
        !          1015: 
        !          1016:        if (pm->s.pm_type == PM_FREEZE)
        !          1017:                return;         // no movement at all
        !          1018: 
        !          1019:        // set mins, maxs, and viewheight
        !          1020:        PM_CheckDuck ();
        !          1021: 
        !          1022:        if (pm->snapinitial)
        !          1023:                PM_InitialSnapPosition ();
        !          1024: 
        !          1025:        // set groundentity, watertype, and waterlevel
        !          1026:        PM_CatagorizePosition ();
        !          1027: 
        !          1028:        if (pm->s.pm_type == PM_DEAD)
        !          1029:                PM_DeadMove ();
        !          1030: 
        !          1031:        PM_CheckSpecialMovement ();
        !          1032: 
        !          1033:        // drop timing counter
        !          1034:        if (pm->s.pm_time)
        !          1035:        {
        !          1036:                int             msec;
        !          1037: 
        !          1038:                msec = pm->cmd.msec >> 3;
        !          1039:                if (!msec)
        !          1040:                        msec = 1;
        !          1041:                if ( msec >= pm->s.pm_time) 
        !          1042:                {
        !          1043:                        pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
        !          1044:                        pm->s.pm_time = 0;
        !          1045:                }
        !          1046:                else
        !          1047:                        pm->s.pm_time -= msec;
        !          1048:        }
        !          1049: 
        !          1050:        if (pm->s.pm_flags & PMF_TIME_TELEPORT)
        !          1051:        {       // teleport pause stays exactly in place
        !          1052:        }
        !          1053:        else if (pm->s.pm_flags & PMF_TIME_WATERJUMP)
        !          1054:        {       // waterjump has no control, but falls
        !          1055:                pml.velocity[2] -= pm->s.gravity * pml.frametime;
        !          1056:                if (pml.velocity[2] < 0)
        !          1057:                {       // cancel as soon as we are falling down again
        !          1058:                        pm->s.pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_TELEPORT);
        !          1059:                        pm->s.pm_time = 0;
        !          1060:                }
        !          1061: 
        !          1062:                PM_StepSlideMove ();
        !          1063:        }
        !          1064:        else
        !          1065:        {
        !          1066:                PM_CheckJump ();
        !          1067: 
        !          1068:                PM_Friction ();
        !          1069: 
        !          1070:                if (pm->waterlevel >= 2)
        !          1071:                        PM_WaterMove ();
        !          1072:                else
        !          1073:                        PM_AirMove ();
        !          1074:        }
        !          1075: 
        !          1076:        // set groundentity, watertype, and waterlevel for final spot
        !          1077:        PM_CatagorizePosition ();
        !          1078: 
        !          1079:        PM_SnapPosition ();
        !          1080: }

unix.superglobalmegacorp.com

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