Annotation of quake1/sv_phys.c, revision 1.1.1.1

1.1       root        1: // sv_phys.c
                      2: 
                      3: #include "quakedef.h"
                      4: 
                      5: /*
                      6: 
                      7: 
                      8: pushmove objects do not obey gravity, and do not interact with each other or trigger fields, but block normal movement and push normal objects when they move.
                      9: 
                     10: onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects 
                     11: 
                     12: doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
                     13: bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
                     14: corpses are SOLID_NOT and MOVETYPE_TOSS
                     15: crates are SOLID_BBOX and MOVETYPE_TOSS
                     16: walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
                     17: flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
                     18: 
                     19: solid_edge items only clip against bsp models.
                     20: 
                     21: */
                     22: 
                     23: cvar_t sv_friction = {"sv_friction","4",false,true};
                     24: cvar_t sv_stopspeed = {"sv_stopspeed","100"};
                     25: cvar_t sv_gravity = {"sv_gravity","800",false,true};
                     26: cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"};
                     27: cvar_t sv_nostep = {"sv_nostep","0"};
                     28: 
                     29: #define        MOVE_EPSILON    0.01
                     30: 
                     31: void SV_Physics_Toss (edict_t *ent);
                     32: 
                     33: /*
                     34: ================
                     35: SV_CheckAllEnts
                     36: ================
                     37: */
                     38: void SV_CheckAllEnts (void)
                     39: {
                     40:        int                     e;
                     41:        edict_t         *check;
                     42: 
                     43: // see if any solid entities are inside the final position
                     44:        check = NEXT_EDICT(sv.edicts);
                     45:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
                     46:        {
                     47:                if (check->free)
                     48:                        continue;
                     49:                if (check->v.movetype == MOVETYPE_PUSH
                     50:                || check->v.movetype == MOVETYPE_NONE
                     51:                || check->v.movetype == MOVETYPE_NOCLIP)
                     52:                        continue;
                     53: 
                     54:                if (SV_TestEntityPosition (check))
                     55:                        Con_Printf ("entity in invalid position\n");
                     56:        }
                     57: }
                     58: 
                     59: /*
                     60: ================
                     61: SV_CheckVelocity
                     62: ================
                     63: */
                     64: void SV_CheckVelocity (edict_t *ent)
                     65: {
                     66:        int             i;
                     67: 
                     68: //
                     69: // bound velocity
                     70: //
                     71:        for (i=0 ; i<3 ; i++)
                     72:        {
                     73:                if (IS_NAN(ent->v.velocity[i]))
                     74:                {
                     75:                        Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname);
                     76:                        ent->v.velocity[i] = 0;
                     77:                }
                     78:                if (IS_NAN(ent->v.origin[i]))
                     79:                {
                     80:                        Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname);
                     81:                        ent->v.origin[i] = 0;
                     82:                }
                     83:                if (ent->v.velocity[i] > sv_maxvelocity.value)
                     84:                        ent->v.velocity[i] = sv_maxvelocity.value;
                     85:                else if (ent->v.velocity[i] < -sv_maxvelocity.value)
                     86:                        ent->v.velocity[i] = -sv_maxvelocity.value;
                     87:        }
                     88: }
                     89: 
                     90: /*
                     91: =============
                     92: SV_RunThink
                     93: 
                     94: Runs thinking code if time.  There is some play in the exact time the think
                     95: function will be called, because it is called before any movement is done
                     96: in a frame.  Not used for pushmove objects, because they must be exact.
                     97: Returns false if the entity removed itself.
                     98: =============
                     99: */
                    100: qboolean SV_RunThink (edict_t *ent)
                    101: {
                    102:        float   thinktime;
                    103: 
                    104:        thinktime = ent->v.nextthink;
                    105:        if (thinktime <= 0 || thinktime > sv.time + host_frametime)
                    106:                return true;
                    107:                
                    108:        if (thinktime < sv.time)
                    109:                thinktime = sv.time;    // don't let things stay in the past.
                    110:                                                                // it is possible to start that way
                    111:                                                                // by a trigger with a local time.
                    112:        ent->v.nextthink = 0;
                    113:        pr_global_struct->time = thinktime;
                    114:        pr_global_struct->self = EDICT_TO_PROG(ent);
                    115:        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                    116:        PR_ExecuteProgram (ent->v.think);
                    117:        return !ent->free;
                    118: }
                    119: 
                    120: /*
                    121: ==================
                    122: SV_Impact
                    123: 
                    124: Two entities have touched, so run their touch functions
                    125: ==================
                    126: */
                    127: void SV_Impact (edict_t *e1, edict_t *e2)
                    128: {
                    129:        int             old_self, old_other;
                    130:        
                    131:        old_self = pr_global_struct->self;
                    132:        old_other = pr_global_struct->other;
                    133:        
                    134:        pr_global_struct->time = sv.time;
                    135:        if (e1->v.touch && e1->v.solid != SOLID_NOT)
                    136:        {
                    137:                pr_global_struct->self = EDICT_TO_PROG(e1);
                    138:                pr_global_struct->other = EDICT_TO_PROG(e2);
                    139:                PR_ExecuteProgram (e1->v.touch);
                    140:        }
                    141:        
                    142:        if (e2->v.touch && e2->v.solid != SOLID_NOT)
                    143:        {
                    144:                pr_global_struct->self = EDICT_TO_PROG(e2);
                    145:                pr_global_struct->other = EDICT_TO_PROG(e1);
                    146:                PR_ExecuteProgram (e2->v.touch);
                    147:        }
                    148: 
                    149:        pr_global_struct->self = old_self;
                    150:        pr_global_struct->other = old_other;
                    151: }
                    152: 
                    153: 
                    154: /*
                    155: ==================
                    156: ClipVelocity
                    157: 
                    158: Slide off of the impacting object
                    159: returns the blocked flags (1 = floor, 2 = step / wall)
                    160: ==================
                    161: */
                    162: #define        STOP_EPSILON    0.1
                    163: 
                    164: int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
                    165: {
                    166:        float   backoff;
                    167:        float   change;
                    168:        int             i, blocked;
                    169:        
                    170:        blocked = 0;
                    171:        if (normal[2] > 0)
                    172:                blocked |= 1;           // floor
                    173:        if (!normal[2])
                    174:                blocked |= 2;           // step
                    175:        
                    176:        backoff = DotProduct (in, normal) * overbounce;
                    177: 
                    178:        for (i=0 ; i<3 ; i++)
                    179:        {
                    180:                change = normal[i]*backoff;
                    181:                out[i] = in[i] - change;
                    182:                if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
                    183:                        out[i] = 0;
                    184:        }
                    185:        
                    186:        return blocked;
                    187: }
                    188: 
                    189: 
                    190: /*
                    191: ============
                    192: SV_FlyMove
                    193: 
                    194: The basic solid body movement clip that slides along multiple planes
                    195: Returns the clipflags if the velocity was modified (hit something solid)
                    196: 1 = floor
                    197: 2 = wall / step
                    198: 4 = dead stop
                    199: If steptrace is not NULL, the trace of any vertical wall hit will be stored
                    200: ============
                    201: */
                    202: #define        MAX_CLIP_PLANES 5
                    203: int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                    204: {
                    205:        int                     bumpcount, numbumps;
                    206:        vec3_t          dir;
                    207:        float           d;
                    208:        int                     numplanes;
                    209:        vec3_t          planes[MAX_CLIP_PLANES];
                    210:        vec3_t          primal_velocity, original_velocity, new_velocity;
                    211:        int                     i, j;
                    212:        trace_t         trace;
                    213:        vec3_t          end;
                    214:        float           time_left;
                    215:        int                     blocked;
                    216:        
                    217:        numbumps = 4;
                    218:        
                    219:        blocked = 0;
                    220:        VectorCopy (ent->v.velocity, original_velocity);
                    221:        VectorCopy (ent->v.velocity, primal_velocity);
                    222:        numplanes = 0;
                    223:        
                    224:        time_left = time;
                    225: 
                    226:        for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
                    227:        {
                    228:                for (i=0 ; i<3 ; i++)
                    229:                        end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
                    230: 
                    231:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
                    232: 
                    233:                if (trace.allsolid)
                    234:                {       // entity is trapped in another solid
                    235:                        VectorCopy (vec3_origin, ent->v.velocity);
                    236:                        return 3;
                    237:                }
                    238: 
                    239:                if (trace.fraction > 0)
                    240:                {       // actually covered some distance
                    241:                        VectorCopy (trace.endpos, ent->v.origin);
                    242:                        VectorCopy (ent->v.velocity, original_velocity);
                    243:                        numplanes = 0;
                    244:                }
                    245: 
                    246:                if (trace.fraction == 1)
                    247:                         break;         // moved the entire distance
                    248: 
                    249:                if (!trace.ent)
                    250:                        Sys_Error ("SV_FlyMove: !trace.ent");
                    251: 
                    252:                if (trace.plane.normal[2] > 0.7)
                    253:                {
                    254:                        blocked |= 1;           // floor
                    255:                        if (trace.ent->v.solid == SOLID_BSP)
                    256:                        {
                    257:                                ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
                    258:                                ent->v.groundentity = EDICT_TO_PROG(trace.ent);
                    259:                        }
                    260:                }
                    261:                if (!trace.plane.normal[2])
                    262:                {
                    263:                        blocked |= 2;           // step
                    264:                        if (steptrace)
                    265:                                *steptrace = trace;     // save for player extrafriction
                    266:                }
                    267: 
                    268: //
                    269: // run the impact function
                    270: //
                    271:                SV_Impact (ent, trace.ent);
                    272:                if (ent->free)
                    273:                        break;          // removed by the impact function
                    274: 
                    275:                
                    276:                time_left -= time_left * trace.fraction;
                    277:                
                    278:        // cliped to another plane
                    279:                if (numplanes >= MAX_CLIP_PLANES)
                    280:                {       // this shouldn't really happen
                    281:                        VectorCopy (vec3_origin, ent->v.velocity);
                    282:                        return 3;
                    283:                }
                    284: 
                    285:                VectorCopy (trace.plane.normal, planes[numplanes]);
                    286:                numplanes++;
                    287: 
                    288: //
                    289: // modify original_velocity so it parallels all of the clip planes
                    290: //
                    291:                for (i=0 ; i<numplanes ; i++)
                    292:                {
                    293:                        ClipVelocity (original_velocity, planes[i], new_velocity, 1);
                    294:                        for (j=0 ; j<numplanes ; j++)
                    295:                                if (j != i)
                    296:                                {
                    297:                                        if (DotProduct (new_velocity, planes[j]) < 0)
                    298:                                                break;  // not ok
                    299:                                }
                    300:                        if (j == numplanes)
                    301:                                break;
                    302:                }
                    303:                
                    304:                if (i != numplanes)
                    305:                {       // go along this plane
                    306:                        VectorCopy (new_velocity, ent->v.velocity);
                    307:                }
                    308:                else
                    309:                {       // go along the crease
                    310:                        if (numplanes != 2)
                    311:                        {
                    312: //                             Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
                    313:                                VectorCopy (vec3_origin, ent->v.velocity);
                    314:                                return 7;
                    315:                        }
                    316:                        CrossProduct (planes[0], planes[1], dir);
                    317:                        d = DotProduct (dir, ent->v.velocity);
                    318:                        VectorScale (dir, d, ent->v.velocity);
                    319:                }
                    320: 
                    321: //
                    322: // if original velocity is against the original velocity, stop dead
                    323: // to avoid tiny occilations in sloping corners
                    324: //
                    325:                if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
                    326:                {
                    327:                        VectorCopy (vec3_origin, ent->v.velocity);
                    328:                        return blocked;
                    329:                }
                    330:        }
                    331: 
                    332:        return blocked;
                    333: }
                    334: 
                    335: 
                    336: /*
                    337: ============
                    338: SV_AddGravity
                    339: 
                    340: ============
                    341: */
                    342: void SV_AddGravity (edict_t *ent, float scale)
                    343: {
                    344:        ent->v.velocity[2] -= scale * sv_gravity.value * host_frametime;
                    345: }
                    346: 
                    347: /*
                    348: ===============================================================================
                    349: 
                    350: PUSHMOVE
                    351: 
                    352: ===============================================================================
                    353: */
                    354: 
                    355: /*
                    356: ============
                    357: SV_PushEntity
                    358: 
                    359: Does not change the entities velocity at all
                    360: ============
                    361: */
                    362: trace_t SV_PushEntity (edict_t *ent, vec3_t push)
                    363: {
                    364:        trace_t trace;
                    365:        vec3_t  end;
                    366:                
                    367:        VectorAdd (ent->v.origin, push, end);
                    368: 
                    369:        if (ent->v.movetype == MOVETYPE_FLYMISSILE)
                    370:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
                    371:        else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
                    372:        // only clip against bmodels
                    373:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
                    374:        else
                    375:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);       
                    376:        
                    377:        VectorCopy (trace.endpos, ent->v.origin);
                    378:        SV_LinkEdict (ent, true);
                    379: 
                    380:        if (trace.ent)
                    381:                SV_Impact (ent, trace.ent);             
                    382: 
                    383:        return trace;
                    384: }                                      
                    385: 
                    386: 
                    387: /*
                    388: ============
                    389: SV_PushMove
                    390: 
                    391: ============
                    392: */
                    393: void SV_PushMove (edict_t *pusher, float movetime)
                    394: {
                    395:        int                     i, e;
                    396:        edict_t         *check, *block;
                    397:        vec3_t          mins, maxs, move;
                    398:        vec3_t          entorig, pushorig;
                    399:        int                     num_moved;
                    400:        edict_t         *moved_edict[MAX_EDICTS];
                    401:        vec3_t          moved_from[MAX_EDICTS];
                    402: 
                    403:        if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
                    404:        {
                    405:                pusher->v.ltime += movetime;
                    406:                return;
                    407:        }
                    408: 
                    409:        for (i=0 ; i<3 ; i++)
                    410:        {
                    411:                move[i] = pusher->v.velocity[i] * movetime;
                    412:                mins[i] = pusher->v.absmin[i] + move[i];
                    413:                maxs[i] = pusher->v.absmax[i] + move[i];
                    414:        }
                    415: 
                    416:        VectorCopy (pusher->v.origin, pushorig);
                    417:        
                    418: // move the pusher to it's final position
                    419: 
                    420:        VectorAdd (pusher->v.origin, move, pusher->v.origin);
                    421:        pusher->v.ltime += movetime;
                    422:        SV_LinkEdict (pusher, false);
                    423: 
                    424: 
                    425: // see if any solid entities are inside the final position
                    426:        num_moved = 0;
                    427:        check = NEXT_EDICT(sv.edicts);
                    428:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
                    429:        {
                    430:                if (check->free)
                    431:                        continue;
                    432:                if (check->v.movetype == MOVETYPE_PUSH
                    433:                || check->v.movetype == MOVETYPE_NONE
                    434:                || check->v.movetype == MOVETYPE_NOCLIP)
                    435:                        continue;
                    436: 
                    437:        // if the entity is standing on the pusher, it will definately be moved
                    438:                if ( ! ( ((int)check->v.flags & FL_ONGROUND)
                    439:                && PROG_TO_EDICT(check->v.groundentity) == pusher) )
                    440:                {
                    441:                        if ( check->v.absmin[0] >= maxs[0]
                    442:                        || check->v.absmin[1] >= maxs[1]
                    443:                        || check->v.absmin[2] >= maxs[2]
                    444:                        || check->v.absmax[0] <= mins[0]
                    445:                        || check->v.absmax[1] <= mins[1]
                    446:                        || check->v.absmax[2] <= mins[2] )
                    447:                                continue;
                    448: 
                    449:                // see if the ent's bbox is inside the pusher's final position
                    450:                        if (!SV_TestEntityPosition (check))
                    451:                                continue;
                    452:                }
                    453: 
                    454:        // remove the onground flag for non-players
                    455:                if (check->v.movetype != MOVETYPE_WALK)
                    456:                        check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
                    457:                
                    458:                VectorCopy (check->v.origin, entorig);
                    459:                VectorCopy (check->v.origin, moved_from[num_moved]);
                    460:                moved_edict[num_moved] = check;
                    461:                num_moved++;
                    462: 
                    463:                // try moving the contacted entity 
                    464:                pusher->v.solid = SOLID_NOT;
                    465:                SV_PushEntity (check, move);
                    466:                pusher->v.solid = SOLID_BSP;
                    467: 
                    468:        // if it is still inside the pusher, block
                    469:                block = SV_TestEntityPosition (check);
                    470:                if (block)
                    471:                {       // fail the move
                    472:                        if (check->v.mins[0] == check->v.maxs[0])
                    473:                                continue;
                    474:                        if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
                    475:                        {       // corpse
                    476:                                check->v.mins[0] = check->v.mins[1] = 0;
                    477:                                VectorCopy (check->v.mins, check->v.maxs);
                    478:                                continue;
                    479:                        }
                    480:                        
                    481:                        VectorCopy (entorig, check->v.origin);
                    482:                        SV_LinkEdict (check, true);
                    483: 
                    484:                        VectorCopy (pushorig, pusher->v.origin);
                    485:                        SV_LinkEdict (pusher, false);
                    486:                        pusher->v.ltime -= movetime;
                    487: 
                    488:                        // if the pusher has a "blocked" function, call it
                    489:                        // otherwise, just stay in place until the obstacle is gone
                    490:                        if (pusher->v.blocked)
                    491:                        {
                    492:                                pr_global_struct->self = EDICT_TO_PROG(pusher);
                    493:                                pr_global_struct->other = EDICT_TO_PROG(check);
                    494:                                PR_ExecuteProgram (pusher->v.blocked);
                    495:                        }
                    496:                        
                    497:                // move back any entities we already moved
                    498:                        for (i=0 ; i<num_moved ; i++)
                    499:                        {
                    500:                                VectorCopy (moved_from[i], moved_edict[i]->v.origin);
                    501:                                SV_LinkEdict (moved_edict[i], false);
                    502:                        }
                    503:                        return;
                    504:                }       
                    505:        }
                    506: 
                    507:        
                    508: }
                    509: 
                    510: 
                    511: /*
                    512: ================
                    513: SV_Physics_Pusher
                    514: 
                    515: ================
                    516: */
                    517: void SV_Physics_Pusher (edict_t *ent)
                    518: {
                    519:        float   thinktime;
                    520:        float   oldltime;
                    521:        float   movetime;
                    522: 
                    523:        oldltime = ent->v.ltime;
                    524:        
                    525:        thinktime = ent->v.nextthink;
                    526:        if (thinktime < ent->v.ltime + host_frametime)
                    527:        {
                    528:                movetime = thinktime - ent->v.ltime;
                    529:                if (movetime < 0)
                    530:                        movetime = 0;
                    531:        }
                    532:        else
                    533:                movetime = host_frametime;
                    534: 
                    535:        if (movetime)
                    536:        {
                    537:                SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
                    538:        }
                    539:                
                    540:        if (thinktime > oldltime && thinktime <= ent->v.ltime)
                    541:        {
                    542:                ent->v.nextthink = 0;
                    543:                pr_global_struct->time = sv.time;
                    544:                pr_global_struct->self = EDICT_TO_PROG(ent);
                    545:                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                    546:                PR_ExecuteProgram (ent->v.think);
                    547:                if (ent->free)
                    548:                        return;
                    549:        }
                    550: 
                    551: }
                    552: 
                    553: 
                    554: /*
                    555: ===============================================================================
                    556: 
                    557: CLIENT MOVEMENT
                    558: 
                    559: ===============================================================================
                    560: */
                    561: 
                    562: /*
                    563: =============
                    564: SV_CheckStuck
                    565: 
                    566: This is a big hack to try and fix the rare case of getting stuck in the world
                    567: clipping hull.
                    568: =============
                    569: */
                    570: void SV_CheckStuck (edict_t *ent)
                    571: {
                    572:        int             i, j;
                    573:        int             z;
                    574:        vec3_t  org;
                    575: 
                    576:        if (!SV_TestEntityPosition(ent))
                    577:        {
                    578:                VectorCopy (ent->v.origin, ent->v.oldorigin);
                    579:                return;
                    580:        }
                    581: 
                    582:        VectorCopy (ent->v.origin, org);
                    583:        VectorCopy (ent->v.oldorigin, ent->v.origin);
                    584:        if (!SV_TestEntityPosition(ent))
                    585:        {
                    586:                Con_Printf ("Unstuck.\n");
                    587:                SV_LinkEdict (ent, true);
                    588:                return;
                    589:        }
                    590:        
                    591:        for (z=0 ; z< 18 ; z++)
                    592:                for (i=-1 ; i <= 1 ; i++)
                    593:                        for (j=-1 ; j <= 1 ; j++)
                    594:                        {
                    595:                                ent->v.origin[0] = org[0] + i;
                    596:                                ent->v.origin[1] = org[1] + j;
                    597:                                ent->v.origin[2] = org[2] + z;
                    598:                                if (!SV_TestEntityPosition(ent))
                    599:                                {
                    600:                                        Con_DPrintf ("Unstuck.\n");
                    601:                                        SV_LinkEdict (ent, true);
                    602:                                        return;
                    603:                                }
                    604:                        }
                    605:                        
                    606:        VectorCopy (org, ent->v.origin);
                    607:        Con_DPrintf ("player is stuck.\n");
                    608: }
                    609: 
                    610: 
                    611: /*
                    612: =============
                    613: SV_CheckWater
                    614: =============
                    615: */
                    616: qboolean SV_CheckWater (edict_t *ent)
                    617: {
                    618:        vec3_t  point;
                    619:        int             cont;
                    620:        
                    621:        point[0] = ent->v.origin[0];
                    622:        point[1] = ent->v.origin[1];
                    623:        
                    624:        ent->v.waterlevel = 0;
                    625:        ent->v.watertype = CONTENTS_EMPTY;
                    626:        point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;       
                    627:        cont = SV_PointContents (point);
                    628:        if (cont <= CONTENTS_WATER)
                    629:        {
                    630:                ent->v.watertype = cont;
                    631:                ent->v.waterlevel = 1;
                    632:                point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5;
                    633:                cont = SV_PointContents (point);
                    634:                if (cont <= CONTENTS_WATER)
                    635:                {
                    636:                        ent->v.waterlevel = 2;
                    637:                        point[2] = ent->v.origin[2] + ent->v.view_ofs[2];
                    638:                        cont = SV_PointContents (point);
                    639:                        if (cont <= CONTENTS_WATER)
                    640:                                ent->v.waterlevel = 3;
                    641:                }
                    642:        }
                    643:        
                    644:        return ent->v.waterlevel > 1;
                    645: }
                    646: 
                    647: /*
                    648: ============
                    649: SV_WallFriction
                    650: 
                    651: ============
                    652: */
                    653: void SV_WallFriction (edict_t *ent, trace_t *trace)
                    654: {
                    655:        vec3_t          forward, right, up;
                    656:        float           d, i;
                    657:        vec3_t          into, side;
                    658:        
                    659:        AngleVectors (ent->v.v_angle, forward, right, up);
                    660:        d = DotProduct (trace->plane.normal, forward);
                    661:        
                    662:        d += 0.5;
                    663:        if (d >= 0)
                    664:                return;
                    665:                
                    666: // cut the tangential velocity
                    667:        i = DotProduct (trace->plane.normal, ent->v.velocity);
                    668:        VectorScale (trace->plane.normal, i, into);
                    669:        VectorSubtract (ent->v.velocity, into, side);
                    670:        
                    671:        ent->v.velocity[0] = side[0] * (1 + d);
                    672:        ent->v.velocity[1] = side[1] * (1 + d);
                    673: }
                    674: 
                    675: /*
                    676: =====================
                    677: SV_TryUnstick
                    678: 
                    679: Player has come to a dead stop, possibly due to the problem with limited
                    680: float precision at some angle joins in the BSP hull.
                    681: 
                    682: Try fixing by pushing one pixel in each direction.
                    683: 
                    684: This is a hack, but in the interest of good gameplay...
                    685: ======================
                    686: */
                    687: int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
                    688: {
                    689:        int             i;
                    690:        vec3_t  oldorg;
                    691:        vec3_t  dir;
                    692:        int             clip;
                    693:        trace_t steptrace;
                    694:        
                    695:        VectorCopy (ent->v.origin, oldorg);
                    696:        VectorCopy (vec3_origin, dir);
                    697: 
                    698:        for (i=0 ; i<8 ; i++)
                    699:        {
                    700: // try pushing a little in an axial direction
                    701:                switch (i)
                    702:                {
                    703:                        case 0: dir[0] = 2; dir[1] = 0; break;
                    704:                        case 1: dir[0] = 0; dir[1] = 2; break;
                    705:                        case 2: dir[0] = -2; dir[1] = 0; break;
                    706:                        case 3: dir[0] = 0; dir[1] = -2; break;
                    707:                        case 4: dir[0] = 2; dir[1] = 2; break;
                    708:                        case 5: dir[0] = -2; dir[1] = 2; break;
                    709:                        case 6: dir[0] = 2; dir[1] = -2; break;
                    710:                        case 7: dir[0] = -2; dir[1] = -2; break;
                    711:                }
                    712:                
                    713:                SV_PushEntity (ent, dir);
                    714: 
                    715: // retry the original move
                    716:                ent->v.velocity[0] = oldvel[0];
                    717:                ent->v. velocity[1] = oldvel[1];
                    718:                ent->v. velocity[2] = 0;
                    719:                clip = SV_FlyMove (ent, 0.1, &steptrace);
                    720: 
                    721:                if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
                    722:                || fabs(oldorg[0] - ent->v.origin[0]) > 4 )
                    723:                {
                    724: //Con_Printf ("unstuck!\n");
                    725:                        return clip;
                    726:                }
                    727:                        
                    728: // go back to the original pos and try again
                    729:                VectorCopy (oldorg, ent->v.origin);
                    730:        }
                    731:        
                    732:        VectorCopy (vec3_origin, ent->v.velocity);
                    733:        return 7;               // still not moving
                    734: }
                    735: 
                    736: /*
                    737: =====================
                    738: SV_WalkMove
                    739: 
                    740: Only used by players
                    741: ======================
                    742: */
                    743: #define        STEPSIZE        18
                    744: void SV_WalkMove (edict_t *ent)
                    745: {
                    746:        vec3_t          upmove, downmove;
                    747:        vec3_t          oldorg, oldvel;
                    748:        vec3_t          nosteporg, nostepvel;
                    749:        int                     clip;
                    750:        int                     oldonground;
                    751:        trace_t         steptrace, downtrace;
                    752:        
                    753: //
                    754: // do a regular slide move unless it looks like you ran into a step
                    755: //
                    756:        oldonground = (int)ent->v.flags & FL_ONGROUND;
                    757:        ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
                    758:        
                    759:        VectorCopy (ent->v.origin, oldorg);
                    760:        VectorCopy (ent->v.velocity, oldvel);
                    761:        
                    762:        clip = SV_FlyMove (ent, host_frametime, &steptrace);
                    763: 
                    764:        if ( !(clip & 2) )
                    765:                return;         // move didn't block on a step
                    766: 
                    767:        if (!oldonground && ent->v.waterlevel == 0)
                    768:                return;         // don't stair up while jumping
                    769:        
                    770:        if (ent->v.movetype != MOVETYPE_WALK)
                    771:                return;         // gibbed by a trigger
                    772:        
                    773:        if (sv_nostep.value)
                    774:                return;
                    775:        
                    776:        if ( (int)sv_player->v.flags & FL_WATERJUMP )
                    777:                return;
                    778: 
                    779:        VectorCopy (ent->v.origin, nosteporg);
                    780:        VectorCopy (ent->v.velocity, nostepvel);
                    781: 
                    782: //
                    783: // try moving up and forward to go up a step
                    784: //
                    785:        VectorCopy (oldorg, ent->v.origin);     // back to start pos
                    786: 
                    787:        VectorCopy (vec3_origin, upmove);
                    788:        VectorCopy (vec3_origin, downmove);
                    789:        upmove[2] = STEPSIZE;
                    790:        downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
                    791: 
                    792: // move up
                    793:        SV_PushEntity (ent, upmove);    // FIXME: don't link?
                    794: 
                    795: // move forward
                    796:        ent->v.velocity[0] = oldvel[0];
                    797:        ent->v. velocity[1] = oldvel[1];
                    798:        ent->v. velocity[2] = 0;
                    799:        clip = SV_FlyMove (ent, host_frametime, &steptrace);
                    800: 
                    801: // check for stuckness, possibly due to the limited precision of floats
                    802: // in the clipping hulls
                    803:        if (clip)
                    804:        {
                    805:                if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125
                    806:                && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 )
                    807:                {       // stepping up didn't make any progress
                    808:                        clip = SV_TryUnstick (ent, oldvel);
                    809:                }
                    810:        }
                    811:        
                    812: // extra friction based on view angle
                    813:        if ( clip & 2 )
                    814:                SV_WallFriction (ent, &steptrace);
                    815: 
                    816: // move down
                    817:        downtrace = SV_PushEntity (ent, downmove);      // FIXME: don't link?
                    818: 
                    819:        if (downtrace.plane.normal[2] > 0.7)
                    820:        {
                    821:                if (ent->v.solid == SOLID_BSP)
                    822:                {
                    823:                        ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
                    824:                        ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
                    825:                }
                    826:        }
                    827:        else
                    828:        {
                    829: // if the push down didn't end up on good ground, use the move without
                    830: // the step up.  This happens near wall / slope combinations, and can
                    831: // cause the player to hop up higher on a slope too steep to climb     
                    832:                VectorCopy (nosteporg, ent->v.origin);
                    833:                VectorCopy (nostepvel, ent->v.velocity);
                    834:        }
                    835: }
                    836: 
                    837: 
                    838: /*
                    839: ================
                    840: SV_Physics_Client
                    841: 
                    842: Player character actions
                    843: ================
                    844: */
                    845: void SV_Physics_Client (edict_t        *ent, int num)
                    846: {
                    847:        if ( ! svs.clients[num-1].active )
                    848:                return;         // unconnected slot
                    849: 
                    850: //
                    851: // call standard client pre-think
                    852: //     
                    853:        pr_global_struct->time = sv.time;
                    854:        pr_global_struct->self = EDICT_TO_PROG(ent);
                    855:        PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
                    856:        
                    857: //
                    858: // do a move
                    859: //
                    860:        SV_CheckVelocity (ent);
                    861: 
                    862: //
                    863: // decide which move function to call
                    864: //
                    865:        switch ((int)ent->v.movetype)
                    866:        {
                    867:        case MOVETYPE_NONE:
                    868:                if (!SV_RunThink (ent))
                    869:                        return;
                    870:                break;
                    871: 
                    872:        case MOVETYPE_WALK:
                    873:                if (!SV_RunThink (ent))
                    874:                        return;
                    875:                if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
                    876:                        SV_AddGravity (ent, 1.0);
                    877:                SV_CheckStuck (ent);
                    878:                SV_WalkMove (ent);
                    879:                break;
                    880:                
                    881:        case MOVETYPE_TOSS:
                    882:        case MOVETYPE_BOUNCE:
                    883:                SV_Physics_Toss (ent);
                    884:                break;
                    885: 
                    886:        case MOVETYPE_FLY:
                    887:                if (!SV_RunThink (ent))
                    888:                        return;
                    889:                SV_FlyMove (ent, host_frametime, NULL);
                    890:                break;
                    891:                
                    892:        case MOVETYPE_NOCLIP:
                    893:                if (!SV_RunThink (ent))
                    894:                        return;
                    895:                VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
                    896:                break;
                    897:                
                    898:        default:
                    899:                Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
                    900:        }
                    901: 
                    902: //
                    903: // call standard player post-think
                    904: //             
                    905:        SV_LinkEdict (ent, true);
                    906: 
                    907:        pr_global_struct->time = sv.time;
                    908:        pr_global_struct->self = EDICT_TO_PROG(ent);
                    909:        PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
                    910: }
                    911: 
                    912: //============================================================================
                    913: 
                    914: /*
                    915: =============
                    916: SV_Physics_None
                    917: 
                    918: Non moving objects can only think
                    919: =============
                    920: */
                    921: void SV_Physics_None (edict_t *ent)
                    922: {
                    923: // regular thinking
                    924:        SV_RunThink (ent);
                    925: }
                    926: 
                    927: /*
                    928: =============
                    929: SV_Physics_Noclip
                    930: 
                    931: A moving object that doesn't obey physics
                    932: =============
                    933: */
                    934: void SV_Physics_Noclip (edict_t *ent)
                    935: {
                    936: // regular thinking
                    937:        if (!SV_RunThink (ent))
                    938:                return;
                    939:        
                    940:        VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
                    941:        VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
                    942: 
                    943:        SV_LinkEdict (ent, false);
                    944: }
                    945: 
                    946: /*
                    947: ==============================================================================
                    948: 
                    949: TOSS / BOUNCE
                    950: 
                    951: ==============================================================================
                    952: */
                    953: 
                    954: /*
                    955: =============
                    956: SV_CheckWaterTransition
                    957: 
                    958: =============
                    959: */
                    960: void SV_CheckWaterTransition (edict_t *ent)
                    961: {
                    962:        int             cont;
                    963: 
                    964:        cont = SV_PointContents (ent->v.origin);
                    965:        if (!ent->v.watertype)
                    966:        {       // just spawned here
                    967:                ent->v.watertype = cont;
                    968:                ent->v.waterlevel = 1;
                    969:                return;
                    970:        }
                    971:        
                    972:        if (cont <= CONTENTS_WATER)
                    973:        {
                    974:                if (ent->v.watertype == CONTENTS_EMPTY)
                    975:                {       // just crossed into water
                    976:                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
                    977:                }               
                    978:                ent->v.watertype = cont;
                    979:                ent->v.waterlevel = 1;
                    980:        }
                    981:        else
                    982:        {
                    983:                if (ent->v.watertype != CONTENTS_EMPTY)
                    984:                {       // just crossed into water
                    985:                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
                    986:                }               
                    987:                ent->v.watertype = CONTENTS_EMPTY;
                    988:                ent->v.waterlevel = cont;
                    989:        }
                    990: }
                    991: 
                    992: /*
                    993: =============
                    994: SV_Physics_Toss
                    995: 
                    996: Toss, bounce, and fly movement.  When onground, do nothing.
                    997: =============
                    998: */
                    999: void SV_Physics_Toss (edict_t *ent)
                   1000: {
                   1001:        trace_t trace;
                   1002:        vec3_t  move;
                   1003:        float   backoff;
                   1004: 
                   1005: // regular thinking
                   1006:        if (!SV_RunThink (ent))
                   1007:                return;
                   1008: 
                   1009: // if onground, return without moving
                   1010:        if ( ((int)ent->v.flags & FL_ONGROUND) )
                   1011:                return;
                   1012: 
                   1013:        SV_CheckVelocity (ent);
                   1014: 
                   1015: // add gravity
                   1016:        if (ent->v.movetype != MOVETYPE_FLY
                   1017:        && ent->v.movetype != MOVETYPE_FLYMISSILE)
                   1018:                SV_AddGravity (ent, 1.0);
                   1019: 
                   1020: // move angles
                   1021:        VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
                   1022: 
                   1023: // move origin
                   1024:        VectorScale (ent->v.velocity, host_frametime, move);
                   1025:        trace = SV_PushEntity (ent, move);
                   1026:        if (trace.fraction == 1)
                   1027:                return;
                   1028:        if (ent->free)
                   1029:                return;
                   1030:        
                   1031:        if (ent->v.movetype == MOVETYPE_BOUNCE)
                   1032:                backoff = 1.5;
                   1033:        else
                   1034:                backoff = 1;
                   1035: 
                   1036:        ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
                   1037: 
                   1038: // stop if on ground
                   1039:        if (trace.plane.normal[2] > 0.7)
                   1040:        {               
                   1041:                if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE )
                   1042:                {
                   1043:                        ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
                   1044:                        ent->v.groundentity = EDICT_TO_PROG(trace.ent);
                   1045:                        VectorCopy (vec3_origin, ent->v.velocity);
                   1046:                        VectorCopy (vec3_origin, ent->v.avelocity);
                   1047:                }
                   1048:        }
                   1049:        
                   1050: // check for in water
                   1051:        SV_CheckWaterTransition (ent);
                   1052: }
                   1053: 
                   1054: /*
                   1055: ===============================================================================
                   1056: 
                   1057: STEPPING MOVEMENT
                   1058: 
                   1059: ===============================================================================
                   1060: */
                   1061: 
                   1062: /*
                   1063: =============
                   1064: SV_Physics_Step
                   1065: 
                   1066: Monsters freefall when they don't have a ground entity, otherwise
                   1067: all movement is done with discrete steps.
                   1068: 
                   1069: This is also used for objects that have become still on the ground, but
                   1070: will fall if the floor is pulled out from under them.
                   1071: =============
                   1072: */
                   1073: void SV_Physics_Step (edict_t *ent)
                   1074: {
                   1075:        qboolean        hitsound;
                   1076: 
                   1077: // frefall if not onground
                   1078:        if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
                   1079:        {
                   1080:                if (ent->v.velocity[2] < sv_gravity.value*-0.1)
                   1081:                        hitsound = true;
                   1082:                else
                   1083:                        hitsound = false;
                   1084: 
                   1085:                SV_AddGravity (ent, 1.0);
                   1086:                SV_CheckVelocity (ent);
                   1087:                SV_FlyMove (ent, host_frametime, NULL);
                   1088:                SV_LinkEdict (ent, true);
                   1089: 
                   1090:                if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
                   1091:                {
                   1092:                        if (hitsound)
                   1093:                                SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
                   1094:                }
                   1095:        }
                   1096: 
                   1097: // regular thinking
                   1098:        SV_RunThink (ent);
                   1099:        
                   1100:        SV_CheckWaterTransition (ent);
                   1101: }
                   1102: 
                   1103: //============================================================================
                   1104: 
                   1105: /*
                   1106: ================
                   1107: SV_Physics
                   1108: 
                   1109: ================
                   1110: */
                   1111: void SV_Physics (void)
                   1112: {
                   1113:        int             i;
                   1114:        edict_t *ent;
                   1115: 
                   1116: // let the progs know that a new frame has started
                   1117:        pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
                   1118:        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                   1119:        pr_global_struct->time = sv.time;
                   1120:        PR_ExecuteProgram (pr_global_struct->StartFrame);
                   1121: 
                   1122: //SV_CheckAllEnts ();
                   1123: 
                   1124: //
                   1125: // treat each object in turn
                   1126: //
                   1127:        ent = sv.edicts;
                   1128:        for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
                   1129:        {
                   1130:                if (ent->free)
                   1131:                        continue;
                   1132: 
                   1133:                if (pr_global_struct->force_retouch)
                   1134:                {
                   1135:                        SV_LinkEdict (ent, true);       // force retouch even for stationary
                   1136:                }
                   1137: 
                   1138:                if (i > 0 && i <= svs.maxclients)
                   1139:                        SV_Physics_Client (ent, i);
                   1140:                else if (ent->v.movetype == MOVETYPE_PUSH)
                   1141:                        SV_Physics_Pusher (ent);
                   1142:                else if (ent->v.movetype == MOVETYPE_NONE)
                   1143:                        SV_Physics_None (ent);
                   1144:                else if (ent->v.movetype == MOVETYPE_NOCLIP)
                   1145:                        SV_Physics_Noclip (ent);
                   1146:                else if (ent->v.movetype == MOVETYPE_STEP)
                   1147:                        SV_Physics_Step (ent);
                   1148:                else if (ent->v.movetype == MOVETYPE_TOSS 
                   1149:                || ent->v.movetype == MOVETYPE_BOUNCE
                   1150:                || ent->v.movetype == MOVETYPE_FLY
                   1151:                || ent->v.movetype == MOVETYPE_FLYMISSILE)
                   1152:                        SV_Physics_Toss (ent);
                   1153:                else
                   1154:                        Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);                        
                   1155:        }
                   1156:        
                   1157:        if (pr_global_struct->force_retouch)
                   1158:                pr_global_struct->force_retouch--;      
                   1159: 
                   1160:        sv.time += host_frametime;
                   1161: }

unix.superglobalmegacorp.com

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