Annotation of quake2/qcommon/pmove.c, revision 1.1.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.