Annotation of quakeworld/server/sv_phys.c, revision 1.1

1.1     ! root        1: /*
        !             2: Copyright (C) 1996-1997 Id Software, Inc.
        !             3: 
        !             4: This program is free software; you can redistribute it and/or
        !             5: modify it under the terms of the GNU General Public License
        !             6: as published by the Free Software Foundation; either version 2
        !             7: of the License, or (at your option) any later version.
        !             8: 
        !             9: This program is distributed in the hope that it will be useful,
        !            10: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
        !            12: 
        !            13: See the GNU General Public License for more details.
        !            14: 
        !            15: You should have received a copy of the GNU General Public License
        !            16: along with this program; if not, write to the Free Software
        !            17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
        !            18: 
        !            19: */
        !            20: // sv_phys.c
        !            21: 
        !            22: #include "qwsvdef.h"
        !            23: 
        !            24: /*
        !            25: 
        !            26: 
        !            27: 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.
        !            28: 
        !            29: onground is set for toss objects when they come to a complete rest.  it is set for steping or walking objects 
        !            30: 
        !            31: doors, plats, etc are SOLID_BSP, and MOVETYPE_PUSH
        !            32: bonus items are SOLID_TRIGGER touch, and MOVETYPE_TOSS
        !            33: corpses are SOLID_NOT and MOVETYPE_TOSS
        !            34: crates are SOLID_BBOX and MOVETYPE_TOSS
        !            35: walking monsters are SOLID_SLIDEBOX and MOVETYPE_STEP
        !            36: flying/floating monsters are SOLID_SLIDEBOX and MOVETYPE_FLY
        !            37: 
        !            38: solid_edge items only clip against bsp models.
        !            39: 
        !            40: */
        !            41: 
        !            42: cvar_t sv_maxvelocity = {"sv_maxvelocity","2000"}; 
        !            43: 
        !            44: cvar_t sv_gravity                       = { "sv_gravity", "800"};    
        !            45: cvar_t sv_stopspeed             = { "sv_stopspeed", "100"};    
        !            46: cvar_t sv_maxspeed                      = { "sv_maxspeed", "320"};    
        !            47: cvar_t sv_spectatormaxspeed = { "sv_spectatormaxspeed", "500"};
        !            48: cvar_t sv_accelerate            = { "sv_accelerate", "10"};     
        !            49: cvar_t sv_airaccelerate         = { "sv_airaccelerate", "0.7"};    
        !            50: cvar_t sv_wateraccelerate       = { "sv_wateraccelerate", "10"};     
        !            51: cvar_t sv_friction                      = { "sv_friction", "4"};      
        !            52: cvar_t sv_waterfriction         = { "sv_waterfriction", "4"};      
        !            53: 
        !            54: 
        !            55: #define        MOVE_EPSILON    0.01
        !            56: 
        !            57: void SV_Physics_Toss (edict_t *ent);
        !            58: 
        !            59: /*
        !            60: ================
        !            61: SV_CheckAllEnts
        !            62: ================
        !            63: */
        !            64: void SV_CheckAllEnts (void)
        !            65: {
        !            66:        int                     e;
        !            67:        edict_t         *check;
        !            68: 
        !            69: // see if any solid entities are inside the final position
        !            70:        check = NEXT_EDICT(sv.edicts);
        !            71:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
        !            72:        {
        !            73:                if (check->free)
        !            74:                        continue;
        !            75:                if (check->v.movetype == MOVETYPE_PUSH
        !            76:                || check->v.movetype == MOVETYPE_NONE
        !            77:                || check->v.movetype == MOVETYPE_NOCLIP)
        !            78:                        continue;
        !            79: 
        !            80:                if (SV_TestEntityPosition (check))
        !            81:                        Con_Printf ("entity in invalid position\n");
        !            82:        }
        !            83: }
        !            84: 
        !            85: /*
        !            86: ================
        !            87: SV_CheckVelocity
        !            88: ================
        !            89: */
        !            90: void SV_CheckVelocity (edict_t *ent)
        !            91: {
        !            92:        int             i;
        !            93: 
        !            94: //
        !            95: // bound velocity
        !            96: //
        !            97:        for (i=0 ; i<3 ; i++)
        !            98:        {
        !            99:                if (IS_NAN(ent->v.velocity[i]))
        !           100:                {
        !           101:                        Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(ent->v.classname));
        !           102:                        ent->v.velocity[i] = 0;
        !           103:                }
        !           104:                if (IS_NAN(ent->v.origin[i]))
        !           105:                {
        !           106:                        Con_Printf ("Got a NaN origin on %s\n", PR_GetString(ent->v.classname));
        !           107:                        ent->v.origin[i] = 0;
        !           108:                }
        !           109:                if (ent->v.velocity[i] > sv_maxvelocity.value)
        !           110:                        ent->v.velocity[i] = sv_maxvelocity.value;
        !           111:                else if (ent->v.velocity[i] < -sv_maxvelocity.value)
        !           112:                        ent->v.velocity[i] = -sv_maxvelocity.value;
        !           113:        }
        !           114: }
        !           115: 
        !           116: /*
        !           117: =============
        !           118: SV_RunThink
        !           119: 
        !           120: Runs thinking code if time.  There is some play in the exact time the think
        !           121: function will be called, because it is called before any movement is done
        !           122: in a frame.  Not used for pushmove objects, because they must be exact.
        !           123: Returns false if the entity removed itself.
        !           124: =============
        !           125: */
        !           126: qboolean SV_RunThink (edict_t *ent)
        !           127: {
        !           128:        float   thinktime;
        !           129: 
        !           130:        do
        !           131:        {
        !           132:                thinktime = ent->v.nextthink;
        !           133:                if (thinktime <= 0)
        !           134:                        return true;
        !           135:                if (thinktime > sv.time + host_frametime)
        !           136:                        return true;
        !           137:                
        !           138:                if (thinktime < sv.time)
        !           139:                        thinktime = sv.time;    // don't let things stay in the past.
        !           140:                                                                        // it is possible to start that way
        !           141:                                                                        // by a trigger with a local time.
        !           142:                ent->v.nextthink = 0;
        !           143:                pr_global_struct->time = thinktime;
        !           144:                pr_global_struct->self = EDICT_TO_PROG(ent);
        !           145:                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
        !           146:                PR_ExecuteProgram (ent->v.think);
        !           147: 
        !           148:                if (ent->free)
        !           149:                        return false;
        !           150:        } while (1);
        !           151: 
        !           152:        return true;
        !           153: }
        !           154: 
        !           155: /*
        !           156: ==================
        !           157: SV_Impact
        !           158: 
        !           159: Two entities have touched, so run their touch functions
        !           160: ==================
        !           161: */
        !           162: void SV_Impact (edict_t *e1, edict_t *e2)
        !           163: {
        !           164:        int             old_self, old_other;
        !           165:        
        !           166:        old_self = pr_global_struct->self;
        !           167:        old_other = pr_global_struct->other;
        !           168:        
        !           169:        pr_global_struct->time = sv.time;
        !           170:        if (e1->v.touch && e1->v.solid != SOLID_NOT)
        !           171:        {
        !           172:                pr_global_struct->self = EDICT_TO_PROG(e1);
        !           173:                pr_global_struct->other = EDICT_TO_PROG(e2);
        !           174:                PR_ExecuteProgram (e1->v.touch);
        !           175:        }
        !           176:        
        !           177:        if (e2->v.touch && e2->v.solid != SOLID_NOT)
        !           178:        {
        !           179:                pr_global_struct->self = EDICT_TO_PROG(e2);
        !           180:                pr_global_struct->other = EDICT_TO_PROG(e1);
        !           181:                PR_ExecuteProgram (e2->v.touch);
        !           182:        }
        !           183: 
        !           184:        pr_global_struct->self = old_self;
        !           185:        pr_global_struct->other = old_other;
        !           186: }
        !           187: 
        !           188: 
        !           189: /*
        !           190: ==================
        !           191: ClipVelocity
        !           192: 
        !           193: Slide off of the impacting object
        !           194: returns the blocked flags (1 = floor, 2 = step / wall)
        !           195: ==================
        !           196: */
        !           197: #define        STOP_EPSILON    0.1
        !           198: 
        !           199: int ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
        !           200: {
        !           201:        float   backoff;
        !           202:        float   change;
        !           203:        int             i, blocked;
        !           204:        
        !           205:        blocked = 0;
        !           206:        if (normal[2] > 0)
        !           207:                blocked |= 1;           // floor
        !           208:        if (!normal[2])
        !           209:                blocked |= 2;           // step
        !           210:        
        !           211:        backoff = DotProduct (in, normal) * overbounce;
        !           212: 
        !           213:        for (i=0 ; i<3 ; i++)
        !           214:        {
        !           215:                change = normal[i]*backoff;
        !           216:                out[i] = in[i] - change;
        !           217:                if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON)
        !           218:                        out[i] = 0;
        !           219:        }
        !           220:        
        !           221:        return blocked;
        !           222: }
        !           223: 
        !           224: 
        !           225: /*
        !           226: ============
        !           227: SV_FlyMove
        !           228: 
        !           229: The basic solid body movement clip that slides along multiple planes
        !           230: Returns the clipflags if the velocity was modified (hit something solid)
        !           231: 1 = floor
        !           232: 2 = wall / step
        !           233: 4 = dead stop
        !           234: If steptrace is not NULL, the trace of any vertical wall hit will be stored
        !           235: ============
        !           236: */
        !           237: #define        MAX_CLIP_PLANES 5
        !           238: int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace)
        !           239: {
        !           240:        int                     bumpcount, numbumps;
        !           241:        vec3_t          dir;
        !           242:        float           d;
        !           243:        int                     numplanes;
        !           244:        vec3_t          planes[MAX_CLIP_PLANES];
        !           245:        vec3_t          primal_velocity, original_velocity, new_velocity;
        !           246:        int                     i, j;
        !           247:        trace_t         trace;
        !           248:        vec3_t          end;
        !           249:        float           time_left;
        !           250:        int                     blocked;
        !           251:        
        !           252:        numbumps = 4;
        !           253:        
        !           254:        blocked = 0;
        !           255:        VectorCopy (ent->v.velocity, original_velocity);
        !           256:        VectorCopy (ent->v.velocity, primal_velocity);
        !           257:        numplanes = 0;
        !           258:        
        !           259:        time_left = time;
        !           260: 
        !           261:        for (bumpcount=0 ; bumpcount<numbumps ; bumpcount++)
        !           262:        {
        !           263:                for (i=0 ; i<3 ; i++)
        !           264:                        end[i] = ent->v.origin[i] + time_left * ent->v.velocity[i];
        !           265: 
        !           266:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, false, ent);
        !           267: 
        !           268:                if (trace.allsolid)
        !           269:                {       // entity is trapped in another solid
        !           270:                        VectorCopy (vec3_origin, ent->v.velocity);
        !           271:                        return 3;
        !           272:                }
        !           273: 
        !           274:                if (trace.fraction > 0)
        !           275:                {       // actually covered some distance
        !           276:                        VectorCopy (trace.endpos, ent->v.origin);
        !           277:                        VectorCopy (ent->v.velocity, original_velocity);
        !           278:                        numplanes = 0;
        !           279:                }
        !           280: 
        !           281:                if (trace.fraction == 1)
        !           282:                         break;         // moved the entire distance
        !           283: 
        !           284:                if (!trace.ent)
        !           285:                        SV_Error ("SV_FlyMove: !trace.ent");
        !           286: 
        !           287:                if (trace.plane.normal[2] > 0.7)
        !           288:                {
        !           289:                        blocked |= 1;           // floor
        !           290:                        if (trace.ent->v.solid == SOLID_BSP)
        !           291:                        {
        !           292:                                ent->v.flags =  (int)ent->v.flags | FL_ONGROUND;
        !           293:                                ent->v.groundentity = EDICT_TO_PROG(trace.ent);
        !           294:                        }
        !           295:                }
        !           296:                if (!trace.plane.normal[2])
        !           297:                {
        !           298:                        blocked |= 2;           // step
        !           299:                        if (steptrace)
        !           300:                                *steptrace = trace;     // save for player extrafriction
        !           301:                }
        !           302: 
        !           303: //
        !           304: // run the impact function
        !           305: //
        !           306:                SV_Impact (ent, trace.ent);
        !           307:                if (ent->free)
        !           308:                        break;          // removed by the impact function
        !           309: 
        !           310:                
        !           311:                time_left -= time_left * trace.fraction;
        !           312:                
        !           313:        // cliped to another plane
        !           314:                if (numplanes >= MAX_CLIP_PLANES)
        !           315:                {       // this shouldn't really happen
        !           316:                        VectorCopy (vec3_origin, ent->v.velocity);
        !           317:                        return 3;
        !           318:                }
        !           319: 
        !           320:                VectorCopy (trace.plane.normal, planes[numplanes]);
        !           321:                numplanes++;
        !           322: 
        !           323: //
        !           324: // modify original_velocity so it parallels all of the clip planes
        !           325: //
        !           326:                for (i=0 ; i<numplanes ; i++)
        !           327:                {
        !           328:                        ClipVelocity (original_velocity, planes[i], new_velocity, 1);
        !           329:                        for (j=0 ; j<numplanes ; j++)
        !           330:                                if (j != i)
        !           331:                                {
        !           332:                                        if (DotProduct (new_velocity, planes[j]) < 0)
        !           333:                                                break;  // not ok
        !           334:                                }
        !           335:                        if (j == numplanes)
        !           336:                                break;
        !           337:                }
        !           338:                
        !           339:                if (i != numplanes)
        !           340:                {       // go along this plane
        !           341:                        VectorCopy (new_velocity, ent->v.velocity);
        !           342:                }
        !           343:                else
        !           344:                {       // go along the crease
        !           345:                        if (numplanes != 2)
        !           346:                        {
        !           347: //                             Con_Printf ("clip velocity, numplanes == %i\n",numplanes);
        !           348:                                VectorCopy (vec3_origin, ent->v.velocity);
        !           349:                                return 7;
        !           350:                        }
        !           351:                        CrossProduct (planes[0], planes[1], dir);
        !           352:                        d = DotProduct (dir, ent->v.velocity);
        !           353:                        VectorScale (dir, d, ent->v.velocity);
        !           354:                }
        !           355: 
        !           356: //
        !           357: // if original velocity is against the original velocity, stop dead
        !           358: // to avoid tiny occilations in sloping corners
        !           359: //
        !           360:                if (DotProduct (ent->v.velocity, primal_velocity) <= 0)
        !           361:                {
        !           362:                        VectorCopy (vec3_origin, ent->v.velocity);
        !           363:                        return blocked;
        !           364:                }
        !           365:        }
        !           366: 
        !           367:        return blocked;
        !           368: }
        !           369: 
        !           370: 
        !           371: /*
        !           372: ============
        !           373: SV_AddGravity
        !           374: 
        !           375: ============
        !           376: */
        !           377: void SV_AddGravity (edict_t *ent, float scale)
        !           378: {
        !           379:        ent->v.velocity[2] -= scale * movevars.gravity * host_frametime;
        !           380: }
        !           381: 
        !           382: /*
        !           383: ===============================================================================
        !           384: 
        !           385: PUSHMOVE
        !           386: 
        !           387: ===============================================================================
        !           388: */
        !           389: 
        !           390: /*
        !           391: ============
        !           392: SV_PushEntity
        !           393: 
        !           394: Does not change the entities velocity at all
        !           395: ============
        !           396: */
        !           397: trace_t SV_PushEntity (edict_t *ent, vec3_t push)
        !           398: {
        !           399:        trace_t trace;
        !           400:        vec3_t  end;
        !           401:                
        !           402:        VectorAdd (ent->v.origin, push, end);
        !           403: 
        !           404:        if (ent->v.movetype == MOVETYPE_FLYMISSILE)
        !           405:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_MISSILE, ent);
        !           406:        else if (ent->v.solid == SOLID_TRIGGER || ent->v.solid == SOLID_NOT)
        !           407:        // only clip against bmodels
        !           408:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NOMONSTERS, ent);
        !           409:        else
        !           410:                trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent);
        !           411:        
        !           412:        VectorCopy (trace.endpos, ent->v.origin);
        !           413:        SV_LinkEdict (ent, true);
        !           414: 
        !           415:        if (trace.ent)
        !           416:                SV_Impact (ent, trace.ent);             
        !           417: 
        !           418:        return trace;
        !           419: }                                      
        !           420: 
        !           421: 
        !           422: /*
        !           423: ============
        !           424: SV_Push
        !           425: 
        !           426: ============
        !           427: */
        !           428: qboolean SV_Push (edict_t *pusher, vec3_t move)
        !           429: {
        !           430:        int                     i, e;
        !           431:        edict_t         *check, *block;
        !           432:        vec3_t          mins, maxs;
        !           433:        vec3_t          pushorig;
        !           434:        int                     num_moved;
        !           435:        edict_t         *moved_edict[MAX_EDICTS];
        !           436:        vec3_t          moved_from[MAX_EDICTS];
        !           437: 
        !           438:        for (i=0 ; i<3 ; i++)
        !           439:        {
        !           440:                mins[i] = pusher->v.absmin[i] + move[i];
        !           441:                maxs[i] = pusher->v.absmax[i] + move[i];
        !           442:        }
        !           443: 
        !           444:        VectorCopy (pusher->v.origin, pushorig);
        !           445:        
        !           446: // move the pusher to it's final position
        !           447: 
        !           448:        VectorAdd (pusher->v.origin, move, pusher->v.origin);
        !           449:        SV_LinkEdict (pusher, false);
        !           450: 
        !           451: // see if any solid entities are inside the final position
        !           452:        num_moved = 0;
        !           453:        check = NEXT_EDICT(sv.edicts);
        !           454:        for (e=1 ; e<sv.num_edicts ; e++, check = NEXT_EDICT(check))
        !           455:        {
        !           456:                if (check->free)
        !           457:                        continue;
        !           458:                if (check->v.movetype == MOVETYPE_PUSH
        !           459:                || check->v.movetype == MOVETYPE_NONE
        !           460:                || check->v.movetype == MOVETYPE_NOCLIP)
        !           461:                        continue;
        !           462: 
        !           463:                pusher->v.solid = SOLID_NOT;
        !           464:                block = SV_TestEntityPosition (check);
        !           465:                pusher->v.solid = SOLID_BSP;
        !           466:                if (block)
        !           467:                        continue;
        !           468: 
        !           469:        // if the entity is standing on the pusher, it will definately be moved
        !           470:                if ( ! ( ((int)check->v.flags & FL_ONGROUND)
        !           471:                && PROG_TO_EDICT(check->v.groundentity) == pusher) )
        !           472:                {
        !           473:                        if ( check->v.absmin[0] >= maxs[0]
        !           474:                        || check->v.absmin[1] >= maxs[1]
        !           475:                        || check->v.absmin[2] >= maxs[2]
        !           476:                        || check->v.absmax[0] <= mins[0]
        !           477:                        || check->v.absmax[1] <= mins[1]
        !           478:                        || check->v.absmax[2] <= mins[2] )
        !           479:                                continue;
        !           480: 
        !           481:                // see if the ent's bbox is inside the pusher's final position
        !           482:                        if (!SV_TestEntityPosition (check))
        !           483:                                continue;
        !           484:                }
        !           485: 
        !           486:                VectorCopy (check->v.origin, moved_from[num_moved]);
        !           487:                moved_edict[num_moved] = check;
        !           488:                num_moved++;
        !           489: 
        !           490:                // try moving the contacted entity 
        !           491:                VectorAdd (check->v.origin, move, check->v.origin);
        !           492:                block = SV_TestEntityPosition (check);
        !           493:                if (!block)
        !           494:                {       // pushed ok
        !           495:                        SV_LinkEdict (check, false);
        !           496:                        continue;
        !           497:                }
        !           498: 
        !           499:                // if it is ok to leave in the old position, do it
        !           500:                VectorSubtract (check->v.origin, move, check->v.origin);
        !           501:                block = SV_TestEntityPosition (check);
        !           502:                if (!block)
        !           503:                {
        !           504:                        num_moved--;
        !           505:                        continue;
        !           506:                }
        !           507: 
        !           508:        // if it is still inside the pusher, block
        !           509:                if (check->v.mins[0] == check->v.maxs[0])
        !           510:                {
        !           511:                        SV_LinkEdict (check, false);
        !           512:                        continue;
        !           513:                }
        !           514:                if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER)
        !           515:                {       // corpse
        !           516:                        check->v.mins[0] = check->v.mins[1] = 0;
        !           517:                        VectorCopy (check->v.mins, check->v.maxs);
        !           518:                        SV_LinkEdict (check, false);
        !           519:                        continue;
        !           520:                }
        !           521:                
        !           522:                VectorCopy (pushorig, pusher->v.origin);
        !           523:                SV_LinkEdict (pusher, false);
        !           524: 
        !           525:                // if the pusher has a "blocked" function, call it
        !           526:                // otherwise, just stay in place until the obstacle is gone
        !           527:                if (pusher->v.blocked)
        !           528:                {
        !           529:                        pr_global_struct->self = EDICT_TO_PROG(pusher);
        !           530:                        pr_global_struct->other = EDICT_TO_PROG(check);
        !           531:                        PR_ExecuteProgram (pusher->v.blocked);
        !           532:                }
        !           533:                
        !           534:        // move back any entities we already moved
        !           535:                for (i=0 ; i<num_moved ; i++)
        !           536:                {
        !           537:                        VectorCopy (moved_from[i], moved_edict[i]->v.origin);
        !           538:                        SV_LinkEdict (moved_edict[i], false);
        !           539:                }
        !           540:                return false;
        !           541:        }
        !           542: 
        !           543:        return true;
        !           544: }
        !           545: 
        !           546: /*
        !           547: ============
        !           548: SV_PushMove
        !           549: 
        !           550: ============
        !           551: */
        !           552: void SV_PushMove (edict_t *pusher, float movetime)
        !           553: {
        !           554:        int                     i;
        !           555:        vec3_t          move;
        !           556: 
        !           557:        if (!pusher->v.velocity[0] && !pusher->v.velocity[1] && !pusher->v.velocity[2])
        !           558:        {
        !           559:                pusher->v.ltime += movetime;
        !           560:                return;
        !           561:        }
        !           562: 
        !           563:        for (i=0 ; i<3 ; i++)
        !           564:                move[i] = pusher->v.velocity[i] * movetime;
        !           565: 
        !           566:        if (SV_Push (pusher, move))
        !           567:                pusher->v.ltime += movetime;
        !           568: }
        !           569: 
        !           570: 
        !           571: /*
        !           572: ================
        !           573: SV_Physics_Pusher
        !           574: 
        !           575: ================
        !           576: */
        !           577: void SV_Physics_Pusher (edict_t *ent)
        !           578: {
        !           579:        float   thinktime;
        !           580:        float   oldltime;
        !           581:        float   movetime;
        !           582: vec3_t oldorg, move;
        !           583: float  l;
        !           584: 
        !           585:        oldltime = ent->v.ltime;
        !           586:        
        !           587:        thinktime = ent->v.nextthink;
        !           588:        if (thinktime < ent->v.ltime + host_frametime)
        !           589:        {
        !           590:                movetime = thinktime - ent->v.ltime;
        !           591:                if (movetime < 0)
        !           592:                        movetime = 0;
        !           593:        }
        !           594:        else
        !           595:                movetime = host_frametime;
        !           596: 
        !           597:        if (movetime)
        !           598:        {
        !           599:                SV_PushMove (ent, movetime);    // advances ent->v.ltime if not blocked
        !           600:        }
        !           601:                
        !           602:        if (thinktime > oldltime && thinktime <= ent->v.ltime)
        !           603:        {
        !           604: VectorCopy (ent->v.origin, oldorg);
        !           605:                ent->v.nextthink = 0;
        !           606:                pr_global_struct->time = sv.time;
        !           607:                pr_global_struct->self = EDICT_TO_PROG(ent);
        !           608:                pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
        !           609:                PR_ExecuteProgram (ent->v.think);
        !           610:                if (ent->free)
        !           611:                        return;
        !           612: VectorSubtract (ent->v.origin, oldorg, move);
        !           613: 
        !           614: l = Length(move);
        !           615: if (l > 1.0/64)
        !           616: {
        !           617: //     Con_Printf ("**** snap: %f\n", Length (l));
        !           618:        VectorCopy (oldorg, ent->v.origin);
        !           619:        SV_Push (ent, move);
        !           620: }
        !           621: 
        !           622:        }
        !           623: 
        !           624: }
        !           625: 
        !           626: 
        !           627: /*
        !           628: =============
        !           629: SV_Physics_None
        !           630: 
        !           631: Non moving objects can only think
        !           632: =============
        !           633: */
        !           634: void SV_Physics_None (edict_t *ent)
        !           635: {
        !           636: // regular thinking
        !           637:        SV_RunThink (ent);
        !           638: }
        !           639: 
        !           640: /*
        !           641: =============
        !           642: SV_Physics_Noclip
        !           643: 
        !           644: A moving object that doesn't obey physics
        !           645: =============
        !           646: */
        !           647: void SV_Physics_Noclip (edict_t *ent)
        !           648: {
        !           649: // regular thinking
        !           650:        if (!SV_RunThink (ent))
        !           651:                return;
        !           652:        
        !           653:        VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
        !           654:        VectorMA (ent->v.origin, host_frametime, ent->v.velocity, ent->v.origin);
        !           655: 
        !           656:        SV_LinkEdict (ent, false);
        !           657: }
        !           658: 
        !           659: /*
        !           660: ==============================================================================
        !           661: 
        !           662: TOSS / BOUNCE
        !           663: 
        !           664: ==============================================================================
        !           665: */
        !           666: 
        !           667: /*
        !           668: =============
        !           669: SV_CheckWaterTransition
        !           670: 
        !           671: =============
        !           672: */
        !           673: void SV_CheckWaterTransition (edict_t *ent)
        !           674: {
        !           675:        int             cont;
        !           676: 
        !           677:        cont = SV_PointContents (ent->v.origin);
        !           678:        if (!ent->v.watertype)
        !           679:        {       // just spawned here
        !           680:                ent->v.watertype = cont;
        !           681:                ent->v.waterlevel = 1;
        !           682:                return;
        !           683:        }
        !           684:        
        !           685:        if (cont <= CONTENTS_WATER)
        !           686:        {
        !           687:                if (ent->v.watertype == CONTENTS_EMPTY)
        !           688:                {       // just crossed into water
        !           689:                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
        !           690:                }               
        !           691:                ent->v.watertype = cont;
        !           692:                ent->v.waterlevel = 1;
        !           693:        }
        !           694:        else
        !           695:        {
        !           696:                if (ent->v.watertype != CONTENTS_EMPTY)
        !           697:                {       // just crossed into water
        !           698:                        SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1);
        !           699:                }               
        !           700:                ent->v.watertype = CONTENTS_EMPTY;
        !           701:                ent->v.waterlevel = cont;
        !           702:        }
        !           703: }
        !           704: 
        !           705: /*
        !           706: =============
        !           707: SV_Physics_Toss
        !           708: 
        !           709: Toss, bounce, and fly movement.  When onground, do nothing.
        !           710: =============
        !           711: */
        !           712: void SV_Physics_Toss (edict_t *ent)
        !           713: {
        !           714:        trace_t trace;
        !           715:        vec3_t  move;
        !           716:        float   backoff;
        !           717: 
        !           718: // regular thinking
        !           719:        if (!SV_RunThink (ent))
        !           720:                return;
        !           721: 
        !           722:        if (ent->v.velocity[2] > 0)
        !           723:                ent->v.flags = (int)ent->v.flags & ~FL_ONGROUND;
        !           724: 
        !           725: // if onground, return without moving
        !           726:        if ( ((int)ent->v.flags & FL_ONGROUND) )
        !           727:                return;
        !           728: 
        !           729:        SV_CheckVelocity (ent);
        !           730: 
        !           731: // add gravity
        !           732:        if (ent->v.movetype != MOVETYPE_FLY
        !           733:        && ent->v.movetype != MOVETYPE_FLYMISSILE)
        !           734:                SV_AddGravity (ent, 1.0);
        !           735: 
        !           736: // move angles
        !           737:        VectorMA (ent->v.angles, host_frametime, ent->v.avelocity, ent->v.angles);
        !           738: 
        !           739: // move origin
        !           740:        VectorScale (ent->v.velocity, host_frametime, move);
        !           741:        trace = SV_PushEntity (ent, move);
        !           742:        if (trace.fraction == 1)
        !           743:                return;
        !           744:        if (ent->free)
        !           745:                return;
        !           746:        
        !           747:        if (ent->v.movetype == MOVETYPE_BOUNCE)
        !           748:                backoff = 1.5;
        !           749:        else
        !           750:                backoff = 1;
        !           751: 
        !           752:        ClipVelocity (ent->v.velocity, trace.plane.normal, ent->v.velocity, backoff);
        !           753: 
        !           754: // stop if on ground
        !           755:        if (trace.plane.normal[2] > 0.7)
        !           756:        {               
        !           757:                if (ent->v.velocity[2] < 60 || ent->v.movetype != MOVETYPE_BOUNCE )
        !           758:                {
        !           759:                        ent->v.flags = (int)ent->v.flags | FL_ONGROUND;
        !           760:                        ent->v.groundentity = EDICT_TO_PROG(trace.ent);
        !           761:                        VectorCopy (vec3_origin, ent->v.velocity);
        !           762:                        VectorCopy (vec3_origin, ent->v.avelocity);
        !           763:                }
        !           764:        }
        !           765:        
        !           766: // check for in water
        !           767:        SV_CheckWaterTransition (ent);
        !           768: }
        !           769: 
        !           770: /*
        !           771: ===============================================================================
        !           772: 
        !           773: STEPPING MOVEMENT
        !           774: 
        !           775: ===============================================================================
        !           776: */
        !           777: 
        !           778: /*
        !           779: =============
        !           780: SV_Physics_Step
        !           781: 
        !           782: Monsters freefall when they don't have a ground entity, otherwise
        !           783: all movement is done with discrete steps.
        !           784: 
        !           785: This is also used for objects that have become still on the ground, but
        !           786: will fall if the floor is pulled out from under them.
        !           787: FIXME: is this true?
        !           788: =============
        !           789: */
        !           790: void SV_Physics_Step (edict_t *ent)
        !           791: {
        !           792:        qboolean        hitsound;
        !           793: 
        !           794: // frefall if not onground
        !           795:        if ( ! ((int)ent->v.flags & (FL_ONGROUND | FL_FLY | FL_SWIM) ) )
        !           796:        {
        !           797:                if (ent->v.velocity[2] < movevars.gravity*-0.1)
        !           798:                        hitsound = true;
        !           799:                else
        !           800:                        hitsound = false;
        !           801: 
        !           802:                SV_AddGravity (ent, 1.0);
        !           803:                SV_CheckVelocity (ent);
        !           804:                SV_FlyMove (ent, host_frametime, NULL);
        !           805:                SV_LinkEdict (ent, true);
        !           806: 
        !           807:                if ( (int)ent->v.flags & FL_ONGROUND )  // just hit ground
        !           808:                {
        !           809:                        if (hitsound)
        !           810:                                SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1);
        !           811:                }
        !           812:        }
        !           813: 
        !           814: // regular thinking
        !           815:        SV_RunThink (ent);
        !           816:        
        !           817:        SV_CheckWaterTransition (ent);
        !           818: }
        !           819: 
        !           820: //============================================================================
        !           821: 
        !           822: void SV_ProgStartFrame (void)
        !           823: {
        !           824: // let the progs know that a new frame has started
        !           825:        pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
        !           826:        pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
        !           827:        pr_global_struct->time = sv.time;
        !           828:        PR_ExecuteProgram (pr_global_struct->StartFrame);
        !           829: }
        !           830: 
        !           831: /*
        !           832: ================
        !           833: SV_RunEntity
        !           834: 
        !           835: ================
        !           836: */
        !           837: void SV_RunEntity (edict_t *ent)
        !           838: {
        !           839:        if (ent->v.lastruntime == (float)realtime)
        !           840:                return;
        !           841:        ent->v.lastruntime = (float)realtime;
        !           842: 
        !           843:        switch ( (int)ent->v.movetype)
        !           844:        {
        !           845:        case MOVETYPE_PUSH:
        !           846:                SV_Physics_Pusher (ent);
        !           847:                break;
        !           848:        case MOVETYPE_NONE:
        !           849:                SV_Physics_None (ent);
        !           850:                break;
        !           851:        case MOVETYPE_NOCLIP:
        !           852:                SV_Physics_Noclip (ent);
        !           853:                break;
        !           854:        case MOVETYPE_STEP:
        !           855:                SV_Physics_Step (ent);
        !           856:                break;
        !           857:        case MOVETYPE_TOSS:
        !           858:        case MOVETYPE_BOUNCE:
        !           859:        case MOVETYPE_FLY:
        !           860:        case MOVETYPE_FLYMISSILE:
        !           861:                SV_Physics_Toss (ent);
        !           862:                break;
        !           863:        default:
        !           864:                SV_Error ("SV_Physics: bad movetype %i", (int)ent->v.movetype);                 
        !           865:        }
        !           866: }
        !           867: 
        !           868: /*
        !           869: ================
        !           870: SV_RunNewmis
        !           871: 
        !           872: ================
        !           873: */
        !           874: void SV_RunNewmis (void)
        !           875: {
        !           876:        edict_t *ent;
        !           877: 
        !           878:        if (!pr_global_struct->newmis)
        !           879:                return;
        !           880:        ent = PROG_TO_EDICT(pr_global_struct->newmis);
        !           881:        host_frametime = 0.05;
        !           882:        pr_global_struct->newmis = 0;
        !           883:        
        !           884:        SV_RunEntity (ent);             
        !           885: }
        !           886: 
        !           887: /*
        !           888: ================
        !           889: SV_Physics
        !           890: 
        !           891: ================
        !           892: */
        !           893: void SV_Physics (void)
        !           894: {
        !           895:        int             i;
        !           896:        edict_t *ent;
        !           897:        static double   old_time;
        !           898: 
        !           899: // don't bother running a frame if sys_ticrate seconds haven't passed
        !           900:        host_frametime = realtime - old_time;
        !           901:        if (host_frametime < sv_mintic.value)
        !           902:                return;
        !           903:        if (host_frametime > sv_maxtic.value)
        !           904:                host_frametime = sv_maxtic.value;
        !           905:        old_time = realtime;
        !           906: 
        !           907:        pr_global_struct->frametime = host_frametime;
        !           908: 
        !           909:        SV_ProgStartFrame ();
        !           910: 
        !           911: //
        !           912: // treat each object in turn
        !           913: // even the world gets a chance to think
        !           914: //
        !           915:        ent = sv.edicts;
        !           916:        for (i=0 ; i<sv.num_edicts ; i++, ent = NEXT_EDICT(ent))
        !           917:        {
        !           918:                if (ent->free)
        !           919:                        continue;
        !           920: 
        !           921:                if (pr_global_struct->force_retouch)
        !           922:                        SV_LinkEdict (ent, true);       // force retouch even for stationary
        !           923: 
        !           924:                if (i > 0 && i <= MAX_CLIENTS)
        !           925:                        continue;               // clients are run directly from packets
        !           926: 
        !           927:                SV_RunEntity (ent);
        !           928:                SV_RunNewmis ();
        !           929:        }
        !           930:        
        !           931:        if (pr_global_struct->force_retouch)
        !           932:                pr_global_struct->force_retouch--;      
        !           933: }
        !           934: 
        !           935: void SV_SetMoveVars(void)
        !           936: {
        !           937:        movevars.gravity                        = sv_gravity.value; 
        !           938:        movevars.stopspeed                  = sv_stopspeed.value;                
        !           939:        movevars.maxspeed                       = sv_maxspeed.value;                     
        !           940:        movevars.spectatormaxspeed  = sv_spectatormaxspeed.value; 
        !           941:        movevars.accelerate                 = sv_accelerate.value;               
        !           942:        movevars.airaccelerate      = sv_airaccelerate.value;    
        !           943:        movevars.wateraccelerate        = sv_wateraccelerate.value;        
        !           944:        movevars.friction                       = sv_friction.value;                     
        !           945:        movevars.waterfriction      = sv_waterfriction.value;    
        !           946:        movevars.entgravity                     = 1.0;
        !           947: }

unix.superglobalmegacorp.com

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