Annotation of quake1/sv_phys.c, revision 1.1.1.2

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: 
1.1.1.2 ! root       29: #ifdef QUAKE2
        !            30: static vec3_t  vec_origin = {0.0, 0.0, 0.0};
        !            31: #endif
        !            32: 
1.1       root       33: #define        MOVE_EPSILON    0.01
                     34: 
                     35: void SV_Physics_Toss (edict_t *ent);
                     36: 
                     37: /*
                     38: ================
                     39: SV_CheckAllEnts
                     40: ================
                     41: */
                     42: void SV_CheckAllEnts (void)
                     43: {
                     44:        int                     e;
                     45:        edict_t         *check;
                     46: 
                     47: // see if any solid entities are inside the final position
                     48:        check = NEXT_EDICT(sv.edicts);
                     49:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
                     50:        {
                     51:                if (check->free)
                     52:                        continue;
                     53:                if (check->v.movetype == MOVETYPE_PUSH
                     54:                || check->v.movetype == MOVETYPE_NONE
1.1.1.2 ! root       55: #ifdef QUAKE2
        !            56:                || check->v.movetype == MOVETYPE_FOLLOW
        !            57: #endif
1.1       root       58:                || check->v.movetype == MOVETYPE_NOCLIP)
                     59:                        continue;
                     60: 
                     61:                if (SV_TestEntityPosition (check))
                     62:                        Con_Printf ("entity in invalid position\n");
                     63:        }
                     64: }
                     65: 
                     66: /*
                     67: ================
                     68: SV_CheckVelocity
                     69: ================
                     70: */
                     71: void SV_CheckVelocity (edict_t *ent)
                     72: {
                     73:        int             i;
                     74: 
                     75: //
                     76: // bound velocity
                     77: //
                     78:        for (i=0 ; i<3 ; i++)
                     79:        {
                     80:                if (IS_NAN(ent->v.velocity[i]))
                     81:                {
                     82:                        Con_Printf ("Got a NaN velocity on %s\n", pr_strings + ent->v.classname);
                     83:                        ent->v.velocity[i] = 0;
                     84:                }
                     85:                if (IS_NAN(ent->v.origin[i]))
                     86:                {
                     87:                        Con_Printf ("Got a NaN origin on %s\n", pr_strings + ent->v.classname);
                     88:                        ent->v.origin[i] = 0;
                     89:                }
                     90:                if (ent->v.velocity[i] > sv_maxvelocity.value)
                     91:                        ent->v.velocity[i] = sv_maxvelocity.value;
                     92:                else if (ent->v.velocity[i] < -sv_maxvelocity.value)
                     93:                        ent->v.velocity[i] = -sv_maxvelocity.value;
                     94:        }
                     95: }
                     96: 
                     97: /*
                     98: =============
                     99: SV_RunThink
                    100: 
                    101: Runs thinking code if time.  There is some play in the exact time the think
                    102: function will be called, because it is called before any movement is done
                    103: in a frame.  Not used for pushmove objects, because they must be exact.
                    104: Returns false if the entity removed itself.
                    105: =============
                    106: */
                    107: qboolean SV_RunThink (edict_t *ent)
                    108: {
                    109:        float   thinktime;
                    110: 
                    111:        thinktime = ent->v.nextthink;
                    112:        if (thinktime <= 0 || thinktime > sv.time + host_frametime)
                    113:                return true;
                    114:                
                    115:        if (thinktime < sv.time)
                    116:                thinktime = sv.time;    // don't let things stay in the past.
                    117:                                                                // it is possible to start that way
                    118:                                                                // by a trigger with a local time.
                    119:        ent->v.nextthink = 0;
                    120:        pr_global_struct->time = thinktime;
                    121:        pr_global_struct->self = EDICT_TO_PROG(ent);
                    122:        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                    123:        PR_ExecuteProgram (ent->v.think);
                    124:        return !ent->free;
                    125: }
                    126: 
                    127: /*
                    128: ==================
                    129: SV_Impact
                    130: 
                    131: Two entities have touched, so run their touch functions
                    132: ==================
                    133: */
                    134: void SV_Impact (edict_t *e1, edict_t *e2)
                    135: {
                    136:        int             old_self, old_other;
                    137:        
                    138:        old_self = pr_global_struct->self;
                    139:        old_other = pr_global_struct->other;
                    140:        
                    141:        pr_global_struct->time = sv.time;
                    142:        if (e1->v.touch && e1->v.solid != SOLID_NOT)
                    143:        {
                    144:                pr_global_struct->self = EDICT_TO_PROG(e1);
                    145:                pr_global_struct->other = EDICT_TO_PROG(e2);
                    146:                PR_ExecuteProgram (e1->v.touch);
                    147:        }
                    148:        
                    149:        if (e2->v.touch && e2->v.solid != SOLID_NOT)
                    150:        {
                    151:                pr_global_struct->self = EDICT_TO_PROG(e2);
                    152:                pr_global_struct->other = EDICT_TO_PROG(e1);
                    153:                PR_ExecuteProgram (e2->v.touch);
                    154:        }
                    155: 
                    156:        pr_global_struct->self = old_self;
                    157:        pr_global_struct->other = old_other;
                    158: }
                    159: 
                    160: 
                    161: /*
                    162: ==================
                    163: ClipVelocity
                    164: 
                    165: Slide off of the impacting object
                    166: returns the blocked flags (1 = floor, 2 = step / wall)
                    167: ==================
                    168: */
                    169: #define        STOP_EPSILON    0.1
                    170: 
                    171: int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
                    172: {
                    173:        float   backoff;
                    174:        float   change;
                    175:        int             i, blocked;
                    176:        
                    177:        blocked = 0;
                    178:        if (normal[2] > 0)
                    179:                blocked |= 1;           // floor
                    180:        if (!normal[2])
                    181:                blocked |= 2;           // step
                    182:        
                    183:        backoff = DotProduct (in, normal) * overbounce;
                    184: 
                    185:        for (i=0 ; i<3 ; i++)
                    186:        {
                    187:                change = normal[i]*backoff;
                    188:                out[i] = in[i] - change;
                    189:                if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
                    190:                        out[i] = 0;
                    191:        }
                    192:        
                    193:        return blocked;
                    194: }
                    195: 
                    196: 
                    197: /*
                    198: ============
                    199: SV_FlyMove
                    200: 
                    201: The basic solid body movement clip that slides along multiple planes
                    202: Returns the clipflags if the velocity was modified (hit something solid)
                    203: 1 = floor
                    204: 2 = wall / step
                    205: 4 = dead stop
                    206: If steptrace is not NULL, the trace of any vertical wall hit will be stored
                    207: ============
                    208: */
                    209: #define        MAX_CLIP_PLANES 5
                    210: int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
                    211: {
                    212:        int                     bumpcount, numbumps;
                    213:        vec3_t          dir;
                    214:        float           d;
                    215:        int                     numplanes;
                    216:        vec3_t          planes[MAX_CLIP_PLANES];
                    217:        vec3_t          primal_velocity, original_velocity, new_velocity;
                    218:        int                     i, j;
                    219:        trace_t         trace;
                    220:        vec3_t          end;
                    221:        float           time_left;
                    222:        int                     blocked;
                    223:        
                    224:        numbumps = 4;
                    225:        
                    226:        blocked = 0;
                    227:        VectorCopy (ent->v.velocity, original_velocity);
                    228:        VectorCopy (ent->v.velocity, primal_velocity);
                    229:        numplanes = 0;
                    230:        
                    231:        time_left = time;
                    232: 
                    233:        for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
                    234:        {
1.1.1.2 ! root      235:                if (!ent->v.velocity[0] && !ent->v.velocity[1] && !ent->v.velocity[2])
        !           236:                        break;
        !           237: 
1.1       root      238:                for (i=0 ; i<3 ; i++)
                    239:                        end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
                    240: 
                    241:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
                    242: 
                    243:                if (trace.allsolid)
                    244:                {       // entity is trapped in another solid
                    245:                        VectorCopy (vec3_origin, ent->v.velocity);
                    246:                        return 3;
                    247:                }
                    248: 
                    249:                if (trace.fraction > 0)
                    250:                {       // actually covered some distance
                    251:                        VectorCopy (trace.endpos, ent->v.origin);
                    252:                        VectorCopy (ent->v.velocity, original_velocity);
                    253:                        numplanes = 0;
                    254:                }
                    255: 
                    256:                if (trace.fraction == 1)
                    257:                         break;         // moved the entire distance
                    258: 
                    259:                if (!trace.ent)
                    260:                        Sys_Error ("SV_FlyMove: !trace.ent");
                    261: 
                    262:                if (trace.plane.normal[2] > 0.7)
                    263:                {
                    264:                        blocked |= 1;           // floor
                    265:                        if (trace.ent->v.solid == SOLID_BSP)
                    266:                        {
                    267:                                ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
                    268:                                ent->v.groundentity = EDICT_TO_PROG(trace.ent);
                    269:                        }
                    270:                }
                    271:                if (!trace.plane.normal[2])
                    272:                {
                    273:                        blocked |= 2;           // step
                    274:                        if (steptrace)
                    275:                                *steptrace = trace;     // save for player extrafriction
                    276:                }
                    277: 
                    278: //
                    279: // run the impact function
                    280: //
                    281:                SV_Impact (ent, trace.ent);
                    282:                if (ent->free)
                    283:                        break;          // removed by the impact function
                    284: 
                    285:                
                    286:                time_left -= time_left * trace.fraction;
                    287:                
                    288:        // cliped to another plane
                    289:                if (numplanes >= MAX_CLIP_PLANES)
                    290:                {       // this shouldn't really happen
                    291:                        VectorCopy (vec3_origin, ent->v.velocity);
                    292:                        return 3;
                    293:                }
                    294: 
                    295:                VectorCopy (trace.plane.normal, planes[numplanes]);
                    296:                numplanes++;
                    297: 
                    298: //
                    299: // modify original_velocity so it parallels all of the clip planes
                    300: //
                    301:                for (i=0 ; i<numplanes ; i++)
                    302:                {
                    303:                        ClipVelocity (original_velocity, planes[i], new_velocity, 1);
                    304:                        for (j=0 ; j<numplanes ; j++)
                    305:                                if (j != i)
                    306:                                {
                    307:                                        if (DotProduct (new_velocity, planes[j]) < 0)
                    308:                                                break;  // not ok
                    309:                                }
                    310:                        if (j == numplanes)
                    311:                                break;
                    312:                }
                    313:                
                    314:                if (i != numplanes)
                    315:                {       // go along this plane
                    316:                        VectorCopy (new_velocity, ent->v.velocity);
                    317:                }
                    318:                else
                    319:                {       // go along the crease
                    320:                        if (numplanes != 2)
                    321:                        {
                    322: //                             Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
                    323:                                VectorCopy (vec3_origin, ent->v.velocity);
                    324:                                return 7;
                    325:                        }
                    326:                        CrossProduct (planes[0], planes[1], dir);
                    327:                        d = DotProduct (dir, ent->v.velocity);
                    328:                        VectorScale (dir, d, ent->v.velocity);
                    329:                }
                    330: 
                    331: //
                    332: // if original velocity is against the original velocity, stop dead
                    333: // to avoid tiny occilations in sloping corners
                    334: //
                    335:                if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
                    336:                {
                    337:                        VectorCopy (vec3_origin, ent->v.velocity);
                    338:                        return blocked;
                    339:                }
                    340:        }
                    341: 
                    342:        return blocked;
                    343: }
                    344: 
                    345: 
                    346: /*
                    347: ============
                    348: SV_AddGravity
                    349: 
                    350: ============
                    351: */
1.1.1.2 ! root      352: void SV_AddGravity (edict_t *ent)
1.1       root      353: {
1.1.1.2 ! root      354:        float   ent_gravity;
        !           355: 
        !           356: #ifdef QUAKE2
        !           357:        if (ent->v.gravity)
        !           358:                ent_gravity = ent->v.gravity;
        !           359:        else
        !           360:                ent_gravity = 1.0;
        !           361: #else
        !           362:        eval_t  *val;
        !           363: 
        !           364:        val = GetEdictFieldValue(ent, "gravity");
        !           365:        if (val && val->_float)
        !           366:                ent_gravity = val->_float;
        !           367:        else
        !           368:                ent_gravity = 1.0;
        !           369: #endif
        !           370:        ent->v.velocity[2] -= ent_gravity * sv_gravity.value * host_frametime;
1.1       root      371: }
                    372: 
1.1.1.2 ! root      373: 
1.1       root      374: /*
                    375: ===============================================================================
                    376: 
                    377: PUSHMOVE
                    378: 
                    379: ===============================================================================
                    380: */
                    381: 
                    382: /*
                    383: ============
                    384: SV_PushEntity
                    385: 
                    386: Does not change the entities velocity at all
                    387: ============
                    388: */
                    389: trace_t SV_PushEntity (edict_t *ent, vec3_t push)
                    390: {
                    391:        trace_t trace;
                    392:        vec3_t  end;
                    393:                
                    394:        VectorAdd (ent->v.origin, push, end);
                    395: 
                    396:        if (ent->v.movetype == MOVETYPE_FLYMISSILE)
                    397:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
                    398:        else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
                    399:        // only clip against bmodels
                    400:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
                    401:        else
                    402:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);       
                    403:        
                    404:        VectorCopy (trace.endpos, ent->v.origin);
                    405:        SV_LinkEdict (ent, true);
                    406: 
                    407:        if (trace.ent)
                    408:                SV_Impact (ent, trace.ent);             
                    409: 
                    410:        return trace;
                    411: }                                      
                    412: 
                    413: 
                    414: /*
                    415: ============
                    416: SV_PushMove
                    417: 
                    418: ============
                    419: */
                    420: void SV_PushMove (edict_t *pusher, float movetime)
                    421: {
                    422:        int                     i, e;
                    423:        edict_t         *check, *block;
                    424:        vec3_t          mins, maxs, move;
                    425:        vec3_t          entorig, pushorig;
                    426:        int                     num_moved;
                    427:        edict_t         *moved_edict[MAX_EDICTS];
                    428:        vec3_t          moved_from[MAX_EDICTS];
                    429: 
                    430:        if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
                    431:        {
                    432:                pusher->v.ltime += movetime;
                    433:                return;
                    434:        }
                    435: 
                    436:        for (i=0 ; i<3 ; i++)
                    437:        {
                    438:                move[i] = pusher->v.velocity[i] * movetime;
                    439:                mins[i] = pusher->v.absmin[i] + move[i];
                    440:                maxs[i] = pusher->v.absmax[i] + move[i];
                    441:        }
                    442: 
                    443:        VectorCopy (pusher->v.origin, pushorig);
                    444:        
                    445: // move the pusher to it's final position
                    446: 
                    447:        VectorAdd (pusher->v.origin, move, pusher->v.origin);
                    448:        pusher->v.ltime += movetime;
                    449:        SV_LinkEdict (pusher, false);
                    450: 
                    451: 
                    452: // see if any solid entities are inside the final position
                    453:        num_moved = 0;
                    454:        check = NEXT_EDICT(sv.edicts);
                    455:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
                    456:        {
                    457:                if (check->free)
                    458:                        continue;
                    459:                if (check->v.movetype == MOVETYPE_PUSH
                    460:                || check->v.movetype == MOVETYPE_NONE
1.1.1.2 ! root      461: #ifdef QUAKE2
        !           462:                || check->v.movetype == MOVETYPE_FOLLOW
        !           463: #endif
1.1       root      464:                || check->v.movetype == MOVETYPE_NOCLIP)
                    465:                        continue;
                    466: 
                    467:        // if the entity is standing on the pusher, it will definately be moved
                    468:                if ( ! ( ((int)check->v.flags & FL_ONGROUND)
                    469:                && PROG_TO_EDICT(check->v.groundentity) == pusher) )
                    470:                {
                    471:                        if ( check->v.absmin[0] >= maxs[0]
                    472:                        || check->v.absmin[1] >= maxs[1]
                    473:                        || check->v.absmin[2] >= maxs[2]
                    474:                        || check->v.absmax[0] <= mins[0]
                    475:                        || check->v.absmax[1] <= mins[1]
                    476:                        || check->v.absmax[2] <= mins[2] )
                    477:                                continue;
                    478: 
                    479:                // see if the ent's bbox is inside the pusher's final position
                    480:                        if (!SV_TestEntityPosition (check))
                    481:                                continue;
                    482:                }
                    483: 
                    484:        // remove the onground flag for non-players
                    485:                if (check->v.movetype != MOVETYPE_WALK)
                    486:                        check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
                    487:                
                    488:                VectorCopy (check->v.origin, entorig);
                    489:                VectorCopy (check->v.origin, moved_from[num_moved]);
                    490:                moved_edict[num_moved] = check;
                    491:                num_moved++;
                    492: 
                    493:                // try moving the contacted entity 
                    494:                pusher->v.solid = SOLID_NOT;
                    495:                SV_PushEntity (check, move);
                    496:                pusher->v.solid = SOLID_BSP;
                    497: 
                    498:        // if it is still inside the pusher, block
                    499:                block = SV_TestEntityPosition (check);
                    500:                if (block)
                    501:                {       // fail the move
                    502:                        if (check->v.mins[0] == check->v.maxs[0])
                    503:                                continue;
                    504:                        if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
                    505:                        {       // corpse
                    506:                                check->v.mins[0] = check->v.mins[1] = 0;
                    507:                                VectorCopy (check->v.mins, check->v.maxs);
                    508:                                continue;
                    509:                        }
                    510:                        
                    511:                        VectorCopy (entorig, check->v.origin);
                    512:                        SV_LinkEdict (check, true);
                    513: 
                    514:                        VectorCopy (pushorig, pusher->v.origin);
                    515:                        SV_LinkEdict (pusher, false);
                    516:                        pusher->v.ltime -= movetime;
                    517: 
                    518:                        // if the pusher has a "blocked" function, call it
                    519:                        // otherwise, just stay in place until the obstacle is gone
                    520:                        if (pusher->v.blocked)
                    521:                        {
                    522:                                pr_global_struct->self = EDICT_TO_PROG(pusher);
                    523:                                pr_global_struct->other = EDICT_TO_PROG(check);
                    524:                                PR_ExecuteProgram (pusher->v.blocked);
                    525:                        }
                    526:                        
                    527:                // move back any entities we already moved
                    528:                        for (i=0 ; i<num_moved ; i++)
                    529:                        {
                    530:                                VectorCopy (moved_from[i], moved_edict[i]->v.origin);
                    531:                                SV_LinkEdict (moved_edict[i], false);
                    532:                        }
                    533:                        return;
                    534:                }       
                    535:        }
                    536: 
                    537:        
                    538: }
                    539: 
1.1.1.2 ! root      540: #ifdef QUAKE2
        !           541: /*
        !           542: ============
        !           543: SV_PushRotate
        !           544: 
        !           545: ============
        !           546: */
        !           547: void SV_PushRotate (edict_t *pusher, float movetime)
        !           548: {
        !           549:        int                     i, e;
        !           550:        edict_t         *check, *block;
        !           551:        vec3_t          move, a, amove;
        !           552:        vec3_t          entorig, pushorig;
        !           553:        int                     num_moved;
        !           554:        edict_t         *moved_edict[MAX_EDICTS];
        !           555:        vec3_t          moved_from[MAX_EDICTS];
        !           556:        vec3_t          org, org2;
        !           557:        vec3_t          forward, right, up;
        !           558: 
        !           559:        if (!pusher->v.avelocity[0] && !pusher->v.avelocity[1] && !pusher->v.avelocity[2])
        !           560:        {
        !           561:                pusher->v.ltime += movetime;
        !           562:                return;
        !           563:        }
        !           564: 
        !           565:        for (i=0 ; i<3 ; i++)
        !           566:                amove[i] = pusher->v.avelocity[i] * movetime;
        !           567: 
        !           568:        VectorSubtract (vec3_origin, amove, a);
        !           569:        AngleVectors (a, forward, right, up);
        !           570: 
        !           571:        VectorCopy (pusher->v.angles, pushorig);
        !           572:        
        !           573: // move the pusher to it's final position
        !           574: 
        !           575:        VectorAdd (pusher->v.angles, amove, pusher->v.angles);
        !           576:        pusher->v.ltime += movetime;
        !           577:        SV_LinkEdict (pusher, false);
        !           578: 
        !           579: 
        !           580: // see if any solid entities are inside the final position
        !           581:        num_moved = 0;
        !           582:        check = NEXT_EDICT(sv.edicts);
        !           583:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
        !           584:        {
        !           585:                if (check->free)
        !           586:                        continue;
        !           587:                if (check->v.movetype == MOVETYPE_PUSH
        !           588:                || check->v.movetype == MOVETYPE_NONE
        !           589:                || check->v.movetype == MOVETYPE_FOLLOW
        !           590:                || check->v.movetype == MOVETYPE_NOCLIP)
        !           591:                        continue;
        !           592: 
        !           593:        // if the entity is standing on the pusher, it will definately be moved
        !           594:                if ( ! ( ((int)check->v.flags & FL_ONGROUND)
        !           595:                && PROG_TO_EDICT(check->v.groundentity) == pusher) )
        !           596:                {
        !           597:                        if ( check->v.absmin[0] >= pusher->v.absmax[0]
        !           598:                        || check->v.absmin[1] >= pusher->v.absmax[1]
        !           599:                        || check->v.absmin[2] >= pusher->v.absmax[2]
        !           600:                        || check->v.absmax[0] <= pusher->v.absmin[0]
        !           601:                        || check->v.absmax[1] <= pusher->v.absmin[1]
        !           602:                        || check->v.absmax[2] <= pusher->v.absmin[2] )
        !           603:                                continue;
        !           604: 
        !           605:                // see if the ent's bbox is inside the pusher's final position
        !           606:                        if (!SV_TestEntityPosition (check))
        !           607:                                continue;
        !           608:                }
        !           609: 
        !           610:        // remove the onground flag for non-players
        !           611:                if (check->v.movetype != MOVETYPE_WALK)
        !           612:                        check->v.flags = (int)check->v.flags & ~FL_ONGROUND;
        !           613:                
        !           614:                VectorCopy (check->v.origin, entorig);
        !           615:                VectorCopy (check->v.origin, moved_from[num_moved]);
        !           616:                moved_edict[num_moved] = check;
        !           617:                num_moved++;
        !           618: 
        !           619:                // calculate destination position
        !           620:                VectorSubtract (check->v.origin, pusher->v.origin, org);
        !           621:                org2[0] = DotProduct (org, forward);
        !           622:                org2[1] = -DotProduct (org, right);
        !           623:                org2[2] = DotProduct (org, up);
        !           624:                VectorSubtract (org2, org, move);
        !           625: 
        !           626:                // try moving the contacted entity 
        !           627:                pusher->v.solid = SOLID_NOT;
        !           628:                SV_PushEntity (check, move);
        !           629:                pusher->v.solid = SOLID_BSP;
        !           630: 
        !           631:        // if it is still inside the pusher, block
        !           632:                block = SV_TestEntityPosition (check);
        !           633:                if (block)
        !           634:                {       // fail the move
        !           635:                        if (check->v.mins[0] == check->v.maxs[0])
        !           636:                                continue;
        !           637:                        if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
        !           638:                        {       // corpse
        !           639:                                check->v.mins[0] = check->v.mins[1] = 0;
        !           640:                                VectorCopy (check->v.mins, check->v.maxs);
        !           641:                                continue;
        !           642:                        }
        !           643:                        
        !           644:                        VectorCopy (entorig, check->v.origin);
        !           645:                        SV_LinkEdict (check, true);
        !           646: 
        !           647:                        VectorCopy (pushorig, pusher->v.angles);
        !           648:                        SV_LinkEdict (pusher, false);
        !           649:                        pusher->v.ltime -= movetime;
        !           650: 
        !           651:                        // if the pusher has a "blocked" function, call it
        !           652:                        // otherwise, just stay in place until the obstacle is gone
        !           653:                        if (pusher->v.blocked)
        !           654:                        {
        !           655:                                pr_global_struct->self = EDICT_TO_PROG(pusher);
        !           656:                                pr_global_struct->other = EDICT_TO_PROG(check);
        !           657:                                PR_ExecuteProgram (pusher->v.blocked);
        !           658:                        }
        !           659:                        
        !           660:                // move back any entities we already moved
        !           661:                        for (i=0 ; i<num_moved ; i++)
        !           662:                        {
        !           663:                                VectorCopy (moved_from[i], moved_edict[i]->v.origin);
        !           664:                                VectorSubtract (moved_edict[i]->v.angles, amove, moved_edict[i]->v.angles);
        !           665:                                SV_LinkEdict (moved_edict[i], false);
        !           666:                        }
        !           667:                        return;
        !           668:                }
        !           669:                else
        !           670:                {
        !           671:                        VectorAdd (check->v.angles, amove, check->v.angles);
        !           672:                }
        !           673:        }
        !           674: 
        !           675:        
        !           676: }
        !           677: #endif
1.1       root      678: 
                    679: /*
                    680: ================
                    681: SV_Physics_Pusher
                    682: 
                    683: ================
                    684: */
                    685: void SV_Physics_Pusher (edict_t *ent)
                    686: {
                    687:        float   thinktime;
                    688:        float   oldltime;
                    689:        float   movetime;
                    690: 
                    691:        oldltime = ent->v.ltime;
                    692:        
                    693:        thinktime = ent->v.nextthink;
                    694:        if (thinktime < ent->v.ltime + host_frametime)
                    695:        {
                    696:                movetime = thinktime - ent->v.ltime;
                    697:                if (movetime < 0)
                    698:                        movetime = 0;
                    699:        }
                    700:        else
                    701:                movetime = host_frametime;
                    702: 
                    703:        if (movetime)
                    704:        {
1.1.1.2 ! root      705: #ifdef QUAKE2
        !           706:                if (ent->v.avelocity[0] || ent->v.avelocity[1] || ent->v.avelocity[2])
        !           707:                        SV_PushRotate (ent, movetime);
        !           708:                else
        !           709: #endif
        !           710:                        SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
1.1       root      711:        }
                    712:                
                    713:        if (thinktime > oldltime && thinktime <= ent->v.ltime)
                    714:        {
                    715:                ent->v.nextthink = 0;
                    716:                pr_global_struct->time = sv.time;
                    717:                pr_global_struct->self = EDICT_TO_PROG(ent);
                    718:                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                    719:                PR_ExecuteProgram (ent->v.think);
                    720:                if (ent->free)
                    721:                        return;
                    722:        }
                    723: 
                    724: }
                    725: 
                    726: 
                    727: /*
                    728: ===============================================================================
                    729: 
                    730: CLIENT MOVEMENT
                    731: 
                    732: ===============================================================================
                    733: */
                    734: 
                    735: /*
                    736: =============
                    737: SV_CheckStuck
                    738: 
                    739: This is a big hack to try and fix the rare case of getting stuck in the world
                    740: clipping hull.
                    741: =============
                    742: */
                    743: void SV_CheckStuck (edict_t *ent)
                    744: {
                    745:        int             i, j;
                    746:        int             z;
                    747:        vec3_t  org;
                    748: 
                    749:        if (!SV_TestEntityPosition(ent))
                    750:        {
                    751:                VectorCopy (ent->v.origin, ent->v.oldorigin);
                    752:                return;
                    753:        }
                    754: 
                    755:        VectorCopy (ent->v.origin, org);
                    756:        VectorCopy (ent->v.oldorigin, ent->v.origin);
                    757:        if (!SV_TestEntityPosition(ent))
                    758:        {
1.1.1.2 ! root      759:                Con_DPrintf ("Unstuck.\n");
1.1       root      760:                SV_LinkEdict (ent, true);
                    761:                return;
                    762:        }
                    763:        
                    764:        for (z=0 ; z< 18 ; z++)
                    765:                for (i=-1 ; i <= 1 ; i++)
                    766:                        for (j=-1 ; j <= 1 ; j++)
                    767:                        {
                    768:                                ent->v.origin[0] = org[0] + i;
                    769:                                ent->v.origin[1] = org[1] + j;
                    770:                                ent->v.origin[2] = org[2] + z;
                    771:                                if (!SV_TestEntityPosition(ent))
                    772:                                {
                    773:                                        Con_DPrintf ("Unstuck.\n");
                    774:                                        SV_LinkEdict (ent, true);
                    775:                                        return;
                    776:                                }
                    777:                        }
                    778:                        
                    779:        VectorCopy (org, ent->v.origin);
                    780:        Con_DPrintf ("player is stuck.\n");
                    781: }
                    782: 
                    783: 
                    784: /*
                    785: =============
                    786: SV_CheckWater
                    787: =============
                    788: */
                    789: qboolean SV_CheckWater (edict_t *ent)
                    790: {
                    791:        vec3_t  point;
                    792:        int             cont;
1.1.1.2 ! root      793: #ifdef QUAKE2
        !           794:        int             truecont;
        !           795: #endif
        !           796: 
1.1       root      797:        point[0] = ent->v.origin[0];
                    798:        point[1] = ent->v.origin[1];
1.1.1.2 ! root      799:        point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;       
1.1       root      800:        
                    801:        ent->v.waterlevel = 0;
                    802:        ent->v.watertype = CONTENTS_EMPTY;
                    803:        cont = SV_PointContents (point);
                    804:        if (cont <= CONTENTS_WATER)
                    805:        {
1.1.1.2 ! root      806: #ifdef QUAKE2
        !           807:                truecont = SV_TruePointContents (point);
        !           808: #endif
1.1       root      809:                ent->v.watertype = cont;
                    810:                ent->v.waterlevel = 1;
                    811:                point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5;
                    812:                cont = SV_PointContents (point);
                    813:                if (cont <= CONTENTS_WATER)
                    814:                {
                    815:                        ent->v.waterlevel = 2;
                    816:                        point[2] = ent->v.origin[2] + ent->v.view_ofs[2];
                    817:                        cont = SV_PointContents (point);
                    818:                        if (cont <= CONTENTS_WATER)
                    819:                                ent->v.waterlevel = 3;
                    820:                }
1.1.1.2 ! root      821: #ifdef QUAKE2
        !           822:                if (truecont <= CONTENTS_CURRENT_0 && truecont >= CONTENTS_CURRENT_DOWN)
        !           823:                {
        !           824:                        static vec3_t current_table[] =
        !           825:                        {
        !           826:                                {1, 0, 0},
        !           827:                                {0, 1, 0},
        !           828:                                {-1, 0, 0},
        !           829:                                {0, -1, 0},
        !           830:                                {0, 0, 1},
        !           831:                                {0, 0, -1}
        !           832:                        };
        !           833: 
        !           834:                        VectorMA (ent->v.basevelocity, 150.0*ent->v.waterlevel/3.0, current_table[CONTENTS_CURRENT_0 - truecont], ent->v.basevelocity);
        !           835:                }
        !           836: #endif
1.1       root      837:        }
                    838:        
                    839:        return ent->v.waterlevel > 1;
                    840: }
                    841: 
                    842: /*
                    843: ============
                    844: SV_WallFriction
                    845: 
                    846: ============
                    847: */
                    848: void SV_WallFriction (edict_t *ent, trace_t *trace)
                    849: {
                    850:        vec3_t          forward, right, up;
                    851:        float           d, i;
                    852:        vec3_t          into, side;
                    853:        
                    854:        AngleVectors (ent->v.v_angle, forward, right, up);
                    855:        d = DotProduct (trace->plane.normal, forward);
                    856:        
                    857:        d += 0.5;
                    858:        if (d >= 0)
                    859:                return;
                    860:                
                    861: // cut the tangential velocity
                    862:        i = DotProduct (trace->plane.normal, ent->v.velocity);
                    863:        VectorScale (trace->plane.normal, i, into);
                    864:        VectorSubtract (ent->v.velocity, into, side);
                    865:        
                    866:        ent->v.velocity[0] = side[0] * (1 + d);
                    867:        ent->v.velocity[1] = side[1] * (1 + d);
                    868: }
                    869: 
                    870: /*
                    871: =====================
                    872: SV_TryUnstick
                    873: 
                    874: Player has come to a dead stop, possibly due to the problem with limited
                    875: float precision at some angle joins in the BSP hull.
                    876: 
                    877: Try fixing by pushing one pixel in each direction.
                    878: 
                    879: This is a hack, but in the interest of good gameplay...
                    880: ======================
                    881: */
                    882: int SV_TryUnstick (edict_t *ent, vec3_t oldvel)
                    883: {
                    884:        int             i;
                    885:        vec3_t  oldorg;
                    886:        vec3_t  dir;
                    887:        int             clip;
                    888:        trace_t steptrace;
                    889:        
                    890:        VectorCopy (ent->v.origin, oldorg);
                    891:        VectorCopy (vec3_origin, dir);
                    892: 
                    893:        for (i=0 ; i<8 ; i++)
                    894:        {
                    895: // try pushing a little in an axial direction
                    896:                switch (i)
                    897:                {
                    898:                        case 0: dir[0] = 2; dir[1] = 0; break;
                    899:                        case 1: dir[0] = 0; dir[1] = 2; break;
                    900:                        case 2: dir[0] = -2; dir[1] = 0; break;
                    901:                        case 3: dir[0] = 0; dir[1] = -2; break;
                    902:                        case 4: dir[0] = 2; dir[1] = 2; break;
                    903:                        case 5: dir[0] = -2; dir[1] = 2; break;
                    904:                        case 6: dir[0] = 2; dir[1] = -2; break;
                    905:                        case 7: dir[0] = -2; dir[1] = -2; break;
                    906:                }
                    907:                
                    908:                SV_PushEntity (ent, dir);
                    909: 
                    910: // retry the original move
                    911:                ent->v.velocity[0] = oldvel[0];
                    912:                ent->v. velocity[1] = oldvel[1];
                    913:                ent->v. velocity[2] = 0;
                    914:                clip = SV_FlyMove (ent, 0.1, &steptrace);
                    915: 
                    916:                if ( fabs(oldorg[1] - ent->v.origin[1]) > 4
                    917:                || fabs(oldorg[0] - ent->v.origin[0]) > 4 )
                    918:                {
1.1.1.2 ! root      919: //Con_DPrintf ("unstuck!\n");
1.1       root      920:                        return clip;
                    921:                }
                    922:                        
                    923: // go back to the original pos and try again
                    924:                VectorCopy (oldorg, ent->v.origin);
                    925:        }
                    926:        
                    927:        VectorCopy (vec3_origin, ent->v.velocity);
                    928:        return 7;               // still not moving
                    929: }
                    930: 
                    931: /*
                    932: =====================
                    933: SV_WalkMove
                    934: 
                    935: Only used by players
                    936: ======================
                    937: */
                    938: #define        STEPSIZE        18
                    939: void SV_WalkMove (edict_t *ent)
                    940: {
                    941:        vec3_t          upmove, downmove;
                    942:        vec3_t          oldorg, oldvel;
                    943:        vec3_t          nosteporg, nostepvel;
                    944:        int                     clip;
                    945:        int                     oldonground;
                    946:        trace_t         steptrace, downtrace;
                    947:        
                    948: //
                    949: // do a regular slide move unless it looks like you ran into a step
                    950: //
                    951:        oldonground = (int)ent->v.flags & FL_ONGROUND;
                    952:        ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
                    953:        
                    954:        VectorCopy (ent->v.origin, oldorg);
                    955:        VectorCopy (ent->v.velocity, oldvel);
                    956:        
                    957:        clip = SV_FlyMove (ent, host_frametime, &steptrace);
                    958: 
                    959:        if ( !(clip & 2) )
                    960:                return;         // move didn't block on a step
                    961: 
                    962:        if (!oldonground && ent->v.waterlevel == 0)
                    963:                return;         // don't stair up while jumping
                    964:        
                    965:        if (ent->v.movetype != MOVETYPE_WALK)
                    966:                return;         // gibbed by a trigger
                    967:        
                    968:        if (sv_nostep.value)
                    969:                return;
                    970:        
                    971:        if ( (int)sv_player->v.flags & FL_WATERJUMP )
                    972:                return;
                    973: 
                    974:        VectorCopy (ent->v.origin, nosteporg);
                    975:        VectorCopy (ent->v.velocity, nostepvel);
                    976: 
                    977: //
                    978: // try moving up and forward to go up a step
                    979: //
                    980:        VectorCopy (oldorg, ent->v.origin);     // back to start pos
                    981: 
                    982:        VectorCopy (vec3_origin, upmove);
                    983:        VectorCopy (vec3_origin, downmove);
                    984:        upmove[2] = STEPSIZE;
                    985:        downmove[2] = -STEPSIZE + oldvel[2]*host_frametime;
                    986: 
                    987: // move up
                    988:        SV_PushEntity (ent, upmove);    // FIXME: don't link?
                    989: 
                    990: // move forward
                    991:        ent->v.velocity[0] = oldvel[0];
                    992:        ent->v. velocity[1] = oldvel[1];
                    993:        ent->v. velocity[2] = 0;
                    994:        clip = SV_FlyMove (ent, host_frametime, &steptrace);
                    995: 
                    996: // check for stuckness, possibly due to the limited precision of floats
                    997: // in the clipping hulls
                    998:        if (clip)
                    999:        {
                   1000:                if ( fabs(oldorg[1] - ent->v.origin[1]) < 0.03125
                   1001:                && fabs(oldorg[0] - ent->v.origin[0]) < 0.03125 )
                   1002:                {       // stepping up didn't make any progress
                   1003:                        clip = SV_TryUnstick (ent, oldvel);
                   1004:                }
                   1005:        }
                   1006:        
                   1007: // extra friction based on view angle
                   1008:        if ( clip & 2 )
                   1009:                SV_WallFriction (ent, &steptrace);
                   1010: 
                   1011: // move down
                   1012:        downtrace = SV_PushEntity (ent, downmove);      // FIXME: don't link?
                   1013: 
                   1014:        if (downtrace.plane.normal[2] > 0.7)
                   1015:        {
                   1016:                if (ent->v.solid == SOLID_BSP)
                   1017:                {
                   1018:                        ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
                   1019:                        ent->v.groundentity = EDICT_TO_PROG(downtrace.ent);
                   1020:                }
                   1021:        }
                   1022:        else
                   1023:        {
                   1024: // if the push down didn't end up on good ground, use the move without
                   1025: // the step up.  This happens near wall / slope combinations, and can
                   1026: // cause the player to hop up higher on a slope too steep to climb     
                   1027:                VectorCopy (nosteporg, ent->v.origin);
                   1028:                VectorCopy (nostepvel, ent->v.velocity);
                   1029:        }
                   1030: }
                   1031: 
                   1032: 
                   1033: /*
                   1034: ================
                   1035: SV_Physics_Client
                   1036: 
                   1037: Player character actions
                   1038: ================
                   1039: */
                   1040: void SV_Physics_Client (edict_t        *ent, int num)
                   1041: {
                   1042:        if ( ! svs.clients[num-1].active )
                   1043:                return;         // unconnected slot
                   1044: 
                   1045: //
                   1046: // call standard client pre-think
                   1047: //     
                   1048:        pr_global_struct->time = sv.time;
                   1049:        pr_global_struct->self = EDICT_TO_PROG(ent);
                   1050:        PR_ExecuteProgram (pr_global_struct->PlayerPreThink);
                   1051:        
                   1052: //
                   1053: // do a move
                   1054: //
                   1055:        SV_CheckVelocity (ent);
                   1056: 
                   1057: //
                   1058: // decide which move function to call
                   1059: //
                   1060:        switch ((int)ent->v.movetype)
                   1061:        {
                   1062:        case MOVETYPE_NONE:
                   1063:                if (!SV_RunThink (ent))
                   1064:                        return;
                   1065:                break;
                   1066: 
                   1067:        case MOVETYPE_WALK:
                   1068:                if (!SV_RunThink (ent))
                   1069:                        return;
                   1070:                if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) )
1.1.1.2 ! root     1071:                        SV_AddGravity (ent);
1.1       root     1072:                SV_CheckStuck (ent);
1.1.1.2 ! root     1073: #ifdef QUAKE2
        !          1074:                VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
        !          1075: #endif
1.1       root     1076:                SV_WalkMove (ent);
1.1.1.2 ! root     1077: 
        !          1078: #ifdef QUAKE2
        !          1079:                VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
        !          1080: #endif
1.1       root     1081:                break;
                   1082:                
                   1083:        case MOVETYPE_TOSS:
                   1084:        case MOVETYPE_BOUNCE:
                   1085:                SV_Physics_Toss (ent);
                   1086:                break;
                   1087: 
                   1088:        case MOVETYPE_FLY:
                   1089:                if (!SV_RunThink (ent))
                   1090:                        return;
                   1091:                SV_FlyMove (ent, host_frametime, NULL);
                   1092:                break;
                   1093:                
                   1094:        case MOVETYPE_NOCLIP:
                   1095:                if (!SV_RunThink (ent))
                   1096:                        return;
                   1097:                VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
                   1098:                break;
                   1099:                
                   1100:        default:
                   1101:                Sys_Error ("SV_Physics_client: bad movetype %i", (int)ent->v.movetype);
                   1102:        }
                   1103: 
                   1104: //
                   1105: // call standard player post-think
                   1106: //             
                   1107:        SV_LinkEdict (ent, true);
                   1108: 
                   1109:        pr_global_struct->time = sv.time;
                   1110:        pr_global_struct->self = EDICT_TO_PROG(ent);
                   1111:        PR_ExecuteProgram (pr_global_struct->PlayerPostThink);
                   1112: }
                   1113: 
                   1114: //============================================================================
                   1115: 
                   1116: /*
                   1117: =============
                   1118: SV_Physics_None
                   1119: 
                   1120: Non moving objects can only think
                   1121: =============
                   1122: */
                   1123: void SV_Physics_None (edict_t *ent)
                   1124: {
                   1125: // regular thinking
                   1126:        SV_RunThink (ent);
                   1127: }
                   1128: 
1.1.1.2 ! root     1129: #ifdef QUAKE2
        !          1130: /*
        !          1131: =============
        !          1132: SV_Physics_Follow
        !          1133: 
        !          1134: Entities that are "stuck" to another entity
        !          1135: =============
        !          1136: */
        !          1137: void SV_Physics_Follow (edict_t *ent)
        !          1138: {
        !          1139: // regular thinking
        !          1140:        SV_RunThink (ent);
        !          1141:        VectorAdd (PROG_TO_EDICT(ent->v.aiment)->v.origin, ent->v.v_angle, ent->v.origin);
        !          1142:        SV_LinkEdict (ent, true);
        !          1143: }
        !          1144: #endif
        !          1145: 
1.1       root     1146: /*
                   1147: =============
                   1148: SV_Physics_Noclip
                   1149: 
                   1150: A moving object that doesn't obey physics
                   1151: =============
                   1152: */
                   1153: void SV_Physics_Noclip (edict_t *ent)
                   1154: {
                   1155: // regular thinking
                   1156:        if (!SV_RunThink (ent))
                   1157:                return;
                   1158:        
                   1159:        VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
                   1160:        VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
                   1161: 
                   1162:        SV_LinkEdict (ent, false);
                   1163: }
                   1164: 
                   1165: /*
                   1166: ==============================================================================
                   1167: 
                   1168: TOSS / BOUNCE
                   1169: 
                   1170: ==============================================================================
                   1171: */
                   1172: 
                   1173: /*
                   1174: =============
                   1175: SV_CheckWaterTransition
                   1176: 
                   1177: =============
                   1178: */
                   1179: void SV_CheckWaterTransition (edict_t *ent)
                   1180: {
                   1181:        int             cont;
1.1.1.2 ! root     1182: #ifdef QUAKE2
        !          1183:        vec3_t  point;
        !          1184:        
        !          1185:        point[0] = ent->v.origin[0];
        !          1186:        point[1] = ent->v.origin[1];
        !          1187:        point[2] = ent->v.origin[2] + ent->v.mins[2] + 1;       
        !          1188:        cont = SV_PointContents (point);
        !          1189: #else
1.1       root     1190:        cont = SV_PointContents (ent->v.origin);
1.1.1.2 ! root     1191: #endif
1.1       root     1192:        if (!ent->v.watertype)
                   1193:        {       // just spawned here
                   1194:                ent->v.watertype = cont;
                   1195:                ent->v.waterlevel = 1;
                   1196:                return;
                   1197:        }
                   1198:        
                   1199:        if (cont <= CONTENTS_WATER)
                   1200:        {
                   1201:                if (ent->v.watertype == CONTENTS_EMPTY)
                   1202:                {       // just crossed into water
                   1203:                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
                   1204:                }               
                   1205:                ent->v.watertype = cont;
                   1206:                ent->v.waterlevel = 1;
                   1207:        }
                   1208:        else
                   1209:        {
                   1210:                if (ent->v.watertype != CONTENTS_EMPTY)
                   1211:                {       // just crossed into water
                   1212:                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
                   1213:                }               
                   1214:                ent->v.watertype = CONTENTS_EMPTY;
                   1215:                ent->v.waterlevel = cont;
                   1216:        }
                   1217: }
                   1218: 
                   1219: /*
                   1220: =============
                   1221: SV_Physics_Toss
                   1222: 
                   1223: Toss, bounce, and fly movement.  When onground, do nothing.
                   1224: =============
                   1225: */
                   1226: void SV_Physics_Toss (edict_t *ent)
                   1227: {
                   1228:        trace_t trace;
                   1229:        vec3_t  move;
                   1230:        float   backoff;
1.1.1.2 ! root     1231: #ifdef QUAKE2
        !          1232:        edict_t *groundentity;
1.1       root     1233: 
1.1.1.2 ! root     1234:        groundentity = PROG_TO_EDICT(ent->v.groundentity);
        !          1235:        if ((int)groundentity->v.flags & FL_CONVEYOR)
        !          1236:                VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
        !          1237:        else
        !          1238:                VectorCopy(vec_origin, ent->v.basevelocity);
        !          1239:        SV_CheckWater (ent);
        !          1240: #endif
        !          1241:        // regular thinking
1.1       root     1242:        if (!SV_RunThink (ent))
                   1243:                return;
                   1244: 
1.1.1.2 ! root     1245: #ifdef QUAKE2
        !          1246:        if (ent->v.velocity[2] > 0)
        !          1247:                ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
        !          1248: 
        !          1249:        if ( ((int)ent->v.flags & FL_ONGROUND) )
        !          1250: //@@
        !          1251:                if (VectorCompare(ent->v.basevelocity, vec_origin))
        !          1252:                        return;
        !          1253: 
        !          1254:        SV_CheckVelocity (ent);
        !          1255: 
        !          1256: // add gravity
        !          1257:        if (! ((int)ent->v.flags & FL_ONGROUND)
        !          1258:                && ent->v.movetype != MOVETYPE_FLY
        !          1259:                && ent->v.movetype != MOVETYPE_BOUNCEMISSILE
        !          1260:                && ent->v.movetype != MOVETYPE_FLYMISSILE)
        !          1261:                        SV_AddGravity (ent);
        !          1262: 
        !          1263: #else
1.1       root     1264: // if onground, return without moving
                   1265:        if ( ((int)ent->v.flags & FL_ONGROUND) )
                   1266:                return;
                   1267: 
                   1268:        SV_CheckVelocity (ent);
                   1269: 
                   1270: // add gravity
                   1271:        if (ent->v.movetype != MOVETYPE_FLY
                   1272:        && ent->v.movetype != MOVETYPE_FLYMISSILE)
1.1.1.2 ! root     1273:                SV_AddGravity (ent);
        !          1274: #endif
1.1       root     1275: 
                   1276: // move angles
                   1277:        VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
                   1278: 
                   1279: // move origin
1.1.1.2 ! root     1280: #ifdef QUAKE2
        !          1281:        VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
        !          1282: #endif
1.1       root     1283:        VectorScale (ent->v.velocity, host_frametime, move);
                   1284:        trace = SV_PushEntity (ent, move);
1.1.1.2 ! root     1285: #ifdef QUAKE2
        !          1286:        VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
        !          1287: #endif
1.1       root     1288:        if (trace.fraction == 1)
                   1289:                return;
                   1290:        if (ent->free)
                   1291:                return;
                   1292:        
                   1293:        if (ent->v.movetype == MOVETYPE_BOUNCE)
                   1294:                backoff = 1.5;
1.1.1.2 ! root     1295: #ifdef QUAKE2
        !          1296:        else if (ent->v.movetype == MOVETYPE_BOUNCEMISSILE)
        !          1297:                backoff = 2.0;
        !          1298: #endif
1.1       root     1299:        else
                   1300:                backoff = 1;
                   1301: 
                   1302:        ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
                   1303: 
                   1304: // stop if on ground
                   1305:        if (trace.plane.normal[2] > 0.7)
                   1306:        {               
1.1.1.2 ! root     1307: #ifdef QUAKE2
        !          1308:                if (ent->v.velocity[2] < 60 || (ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE))
        !          1309: #else
        !          1310:                if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE)
        !          1311: #endif
1.1       root     1312:                {
                   1313:                        ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
                   1314:                        ent->v.groundentity = EDICT_TO_PROG(trace.ent);
                   1315:                        VectorCopy (vec3_origin, ent->v.velocity);
                   1316:                        VectorCopy (vec3_origin, ent->v.avelocity);
                   1317:                }
                   1318:        }
                   1319:        
                   1320: // check for in water
                   1321:        SV_CheckWaterTransition (ent);
                   1322: }
                   1323: 
                   1324: /*
                   1325: ===============================================================================
                   1326: 
                   1327: STEPPING MOVEMENT
                   1328: 
                   1329: ===============================================================================
                   1330: */
                   1331: 
                   1332: /*
                   1333: =============
                   1334: SV_Physics_Step
                   1335: 
                   1336: Monsters freefall when they don't have a ground entity, otherwise
                   1337: all movement is done with discrete steps.
                   1338: 
                   1339: This is also used for objects that have become still on the ground, but
                   1340: will fall if the floor is pulled out from under them.
                   1341: =============
                   1342: */
1.1.1.2 ! root     1343: #ifdef QUAKE2
        !          1344: void SV_Physics_Step (edict_t *ent)
        !          1345: {
        !          1346:        qboolean        wasonground;
        !          1347:        qboolean        inwater;
        !          1348:        qboolean        hitsound = false;
        !          1349:        float           *vel;
        !          1350:        float           speed, newspeed, control;
        !          1351:        float           friction;
        !          1352:        edict_t         *groundentity;
        !          1353: 
        !          1354:        groundentity = PROG_TO_EDICT(ent->v.groundentity);
        !          1355:        if ((int)groundentity->v.flags & FL_CONVEYOR)
        !          1356:                VectorScale(groundentity->v.movedir, groundentity->v.speed, ent->v.basevelocity);
        !          1357:        else
        !          1358:                VectorCopy(vec_origin, ent->v.basevelocity);
        !          1359: //@@
        !          1360:        pr_global_struct->time = sv.time;
        !          1361:        pr_global_struct->self = EDICT_TO_PROG(ent);
        !          1362:        PF_WaterMove();
        !          1363: 
        !          1364:        SV_CheckVelocity (ent);
        !          1365: 
        !          1366:        wasonground = (int)ent->v.flags & FL_ONGROUND;
        !          1367: //     ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
        !          1368: 
        !          1369:        // add gravity except:
        !          1370:        //   flying monsters
        !          1371:        //   swimming monsters who are in the water
        !          1372:        inwater = SV_CheckWater(ent);
        !          1373:        if (! wasonground)
        !          1374:                if (!((int)ent->v.flags & FL_FLY))
        !          1375:                        if (!(((int)ent->v.flags & FL_SWIM) && (ent->v.waterlevel > 0)))
        !          1376:                        {
        !          1377:                                if (ent->v.velocity[2] < sv_gravity.value*-0.1)
        !          1378:                                        hitsound = true;
        !          1379:                                if (!inwater)
        !          1380:                                        SV_AddGravity (ent);
        !          1381:                        }
        !          1382: 
        !          1383:        if (!VectorCompare(ent->v.velocity, vec_origin) || !VectorCompare(ent->v.basevelocity, vec_origin))
        !          1384:        {
        !          1385:                ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
        !          1386:                // apply friction
        !          1387:                // let dead monsters who aren't completely onground slide
        !          1388:                if (wasonground)
        !          1389:                        if (!(ent->v.health <= 0.0 && !SV_CheckBottom(ent)))
        !          1390:                        {
        !          1391:                                vel = ent->v.velocity;
        !          1392:                                speed = sqrt(vel[0]*vel[0] +vel[1]*vel[1]);
        !          1393:                                if (speed)
        !          1394:                                {
        !          1395:                                        friction = sv_friction.value;
        !          1396: 
        !          1397:                                        control = speed < sv_stopspeed.value ? sv_stopspeed.value : speed;
        !          1398:                                        newspeed = speed - host_frametime*control*friction;
        !          1399: 
        !          1400:                                        if (newspeed < 0)
        !          1401:                                                newspeed = 0;
        !          1402:                                        newspeed /= speed;
        !          1403: 
        !          1404:                                        vel[0] = vel[0] * newspeed;
        !          1405:                                        vel[1] = vel[1] * newspeed;
        !          1406:                                }
        !          1407:                        }
        !          1408: 
        !          1409:                VectorAdd (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
        !          1410:                SV_FlyMove (ent, host_frametime, NULL);
        !          1411:                VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
        !          1412: 
        !          1413:                // determine if it's on solid ground at all
        !          1414:                {
        !          1415:                        vec3_t  mins, maxs, point;
        !          1416:                        int             x, y;
        !          1417:                
        !          1418:                        VectorAdd (ent->v.origin, ent->v.mins, mins);
        !          1419:                        VectorAdd (ent->v.origin, ent->v.maxs, maxs);
        !          1420: 
        !          1421:                        point[2] = mins[2] - 1;
        !          1422:                        for     (x=0 ; x<=1 ; x++)
        !          1423:                                for     (y=0 ; y<=1 ; y++)
        !          1424:                                {
        !          1425:                                        point[0] = x ? maxs[0] : mins[0];
        !          1426:                                        point[1] = y ? maxs[1] : mins[1];
        !          1427:                                        if (SV_PointContents (point) == CONTENTS_SOLID)
        !          1428:                                        {
        !          1429:                                                ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
        !          1430:                                                break;
        !          1431:                                        }
        !          1432:                                }
        !          1433: 
        !          1434:                }
        !          1435: 
        !          1436:                SV_LinkEdict (ent, true);
        !          1437: 
        !          1438:                if ((int)ent->v.flags & FL_ONGROUND)
        !          1439:                        if (!wasonground)
        !          1440:                                if (hitsound)
        !          1441:                                        SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
        !          1442:        }
        !          1443: 
        !          1444: // regular thinking
        !          1445:        SV_RunThink (ent);
        !          1446:        SV_CheckWaterTransition (ent);
        !          1447: }
        !          1448: #else
1.1       root     1449: void SV_Physics_Step (edict_t *ent)
                   1450: {
                   1451:        qboolean        hitsound;
                   1452: 
1.1.1.2 ! root     1453: // freefall if not onground
1.1       root     1454:        if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
                   1455:        {
                   1456:                if (ent->v.velocity[2] < sv_gravity.value*-0.1)
                   1457:                        hitsound = true;
                   1458:                else
                   1459:                        hitsound = false;
                   1460: 
1.1.1.2 ! root     1461:                SV_AddGravity (ent);
1.1       root     1462:                SV_CheckVelocity (ent);
                   1463:                SV_FlyMove (ent, host_frametime, NULL);
                   1464:                SV_LinkEdict (ent, true);
                   1465: 
                   1466:                if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
                   1467:                {
                   1468:                        if (hitsound)
                   1469:                                SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
                   1470:                }
                   1471:        }
                   1472: 
                   1473: // regular thinking
                   1474:        SV_RunThink (ent);
                   1475:        
                   1476:        SV_CheckWaterTransition (ent);
                   1477: }
1.1.1.2 ! root     1478: #endif
1.1       root     1479: 
                   1480: //============================================================================
                   1481: 
                   1482: /*
                   1483: ================
                   1484: SV_Physics
                   1485: 
                   1486: ================
                   1487: */
                   1488: void SV_Physics (void)
                   1489: {
                   1490:        int             i;
                   1491:        edict_t *ent;
                   1492: 
                   1493: // let the progs know that a new frame has started
                   1494:        pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
                   1495:        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
                   1496:        pr_global_struct->time = sv.time;
                   1497:        PR_ExecuteProgram (pr_global_struct->StartFrame);
                   1498: 
                   1499: //SV_CheckAllEnts ();
                   1500: 
                   1501: //
                   1502: // treat each object in turn
                   1503: //
                   1504:        ent = sv.edicts;
                   1505:        for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
                   1506:        {
                   1507:                if (ent->free)
                   1508:                        continue;
                   1509: 
                   1510:                if (pr_global_struct->force_retouch)
                   1511:                {
                   1512:                        SV_LinkEdict (ent, true);       // force retouch even for stationary
                   1513:                }
                   1514: 
                   1515:                if (i > 0 && i <= svs.maxclients)
                   1516:                        SV_Physics_Client (ent, i);
                   1517:                else if (ent->v.movetype == MOVETYPE_PUSH)
                   1518:                        SV_Physics_Pusher (ent);
                   1519:                else if (ent->v.movetype == MOVETYPE_NONE)
                   1520:                        SV_Physics_None (ent);
1.1.1.2 ! root     1521: #ifdef QUAKE2
        !          1522:                else if (ent->v.movetype == MOVETYPE_FOLLOW)
        !          1523:                        SV_Physics_Follow (ent);
        !          1524: #endif
1.1       root     1525:                else if (ent->v.movetype == MOVETYPE_NOCLIP)
                   1526:                        SV_Physics_Noclip (ent);
                   1527:                else if (ent->v.movetype == MOVETYPE_STEP)
                   1528:                        SV_Physics_Step (ent);
                   1529:                else if (ent->v.movetype == MOVETYPE_TOSS 
                   1530:                || ent->v.movetype == MOVETYPE_BOUNCE
1.1.1.2 ! root     1531: #ifdef QUAKE2
        !          1532:                || ent->v.movetype == MOVETYPE_BOUNCEMISSILE
        !          1533: #endif
1.1       root     1534:                || ent->v.movetype == MOVETYPE_FLY
                   1535:                || ent->v.movetype == MOVETYPE_FLYMISSILE)
                   1536:                        SV_Physics_Toss (ent);
                   1537:                else
                   1538:                        Sys_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);                        
                   1539:        }
                   1540:        
                   1541:        if (pr_global_struct->force_retouch)
                   1542:                pr_global_struct->force_retouch--;      
                   1543: 
                   1544:        sv.time += host_frametime;
                   1545: }
1.1.1.2 ! root     1546: 
        !          1547: 
        !          1548: #ifdef QUAKE2
        !          1549: trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore)
        !          1550: {
        !          1551:        edict_t tempent, *tent;
        !          1552:        trace_t trace;
        !          1553:        vec3_t  move;
        !          1554:        vec3_t  end;
        !          1555:        double  save_frametime;
        !          1556: //     extern particle_t       *active_particles, *free_particles;
        !          1557: //     particle_t      *p;
        !          1558: 
        !          1559: 
        !          1560:        save_frametime = host_frametime;
        !          1561:        host_frametime = 0.05;
        !          1562: 
        !          1563:        memcpy(&tempent, ent, sizeof(edict_t));
        !          1564:        tent = &tempent;
        !          1565: 
        !          1566:        while (1)
        !          1567:        {
        !          1568:                SV_CheckVelocity (tent);
        !          1569:                SV_AddGravity (tent);
        !          1570:                VectorMA (tent->v.angles, host_frametime, tent->v.avelocity, tent->v.angles);
        !          1571:                VectorScale (tent->v.velocity, host_frametime, move);
        !          1572:                VectorAdd (tent->v.origin, move, end);
        !          1573:                trace = SV_Move (tent->v.origin, tent->v.mins, tent->v.maxs, end, MOVE_NORMAL, tent);   
        !          1574:                VectorCopy (trace.endpos, tent->v.origin);
        !          1575: 
        !          1576: //             p = free_particles;
        !          1577: //             if (p)
        !          1578: //             {
        !          1579: //                     free_particles = p->next;
        !          1580: //                     p->next = active_particles;
        !          1581: //                     active_particles = p;
        !          1582: //             
        !          1583: //                     p->die = 256;
        !          1584: //                     p->color = 15;
        !          1585: //                     p->type = pt_static;
        !          1586: //                     VectorCopy (vec3_origin, p->vel);
        !          1587: //                     VectorCopy (tent->v.origin, p->org);
        !          1588: //             }
        !          1589: 
        !          1590:                if (trace.ent)
        !          1591:                        if (trace.ent != ignore)
        !          1592:                                break;
        !          1593:        }
        !          1594: //     p->color = 224;
        !          1595:        host_frametime = save_frametime;
        !          1596:        return trace;
        !          1597: }
        !          1598: #endif

unix.superglobalmegacorp.com

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