Annotation of quake2/client/cl_ents.c, revision 1.1

1.1     ! root        1: // cl_ents.c -- entity parsing and management
        !             2: #include "client.h"
        !             3: 
        !             4: extern struct model_s  *cl_mod_powerscreen;
        !             5: /*
        !             6: =========================================================================
        !             7: FRAME PARSING
        !             8: =========================================================================
        !             9: */
        !            10: /*
        !            11: =================
        !            12: CL_ParseEntityBits
        !            13: 
        !            14: Returns the entity number and the header bits
        !            15: =================
        !            16: */
        !            17: int    bitcounts[32];  /// just for protocol profiling
        !            18: int CL_ParseEntityBits (unsigned *bits)
        !            19: {
        !            20:        unsigned        b, total;
        !            21:        int                     i;
        !            22:        int                     number;
        !            23: 
        !            24:        total = MSG_ReadByte (&net_message);
        !            25:        if (total & U_MOREBITS1)
        !            26:        {
        !            27:                b = MSG_ReadByte (&net_message);
        !            28:                total |= b<<8;
        !            29:        }
        !            30:        if (total & U_MOREBITS2)
        !            31:        {
        !            32:                b = MSG_ReadByte (&net_message);
        !            33:                total |= b<<16;
        !            34:        }
        !            35:        if (total & U_MOREBITS3)
        !            36:        {
        !            37:                b = MSG_ReadByte (&net_message);
        !            38:                total |= b<<24;
        !            39:        }
        !            40: 
        !            41:        // count the bits for net profiling
        !            42:        for (i=0 ; i<32 ; i++)
        !            43:                if (total&(1<<i))
        !            44:                        bitcounts[i]++;
        !            45: 
        !            46:        if (total & U_NUMBER16)
        !            47:                number = MSG_ReadShort (&net_message);
        !            48:        else
        !            49:                number = MSG_ReadByte (&net_message);
        !            50: 
        !            51:        *bits = total;
        !            52: 
        !            53:        return number;
        !            54: }
        !            55: /*
        !            56: ==================
        !            57: CL_ParseDelta
        !            58: Can go from either a baseline or a previous packet_entity
        !            59: ==================
        !            60: */
        !            61: void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits)
        !            62: {
        !            63:        // set everything to the state we are delta'ing from
        !            64:        *to = *from;
        !            65: //     VectorCopy (from->origin, to->old_origin);
        !            66:        to->number = number;
        !            67:        if (bits & U_MODEL)
        !            68:                to->modelindex = MSG_ReadByte (&net_message);
        !            69:        if (bits & U_MODEL2)
        !            70:                to->modelindex2 = MSG_ReadByte (&net_message);
        !            71:        if (bits & U_MODEL3)
        !            72:                to->modelindex3 = MSG_ReadByte (&net_message);
        !            73:        if (bits & U_MODEL4)
        !            74:                to->modelindex4 = MSG_ReadByte (&net_message);
        !            75:                
        !            76:        if (bits & U_FRAME8)
        !            77:                to->frame = MSG_ReadByte (&net_message);
        !            78:        if (bits & U_FRAME16)
        !            79:                to->frame = MSG_ReadShort (&net_message);
        !            80:        if ((bits & U_SKIN8) && (bits & U_SKIN16))              //used for laser colors
        !            81:                to->skinnum = MSG_ReadLong(&net_message);
        !            82:        else if (bits & U_SKIN8)
        !            83:                to->skinnum = MSG_ReadByte(&net_message);
        !            84:        else if (bits & U_SKIN16)
        !            85:                to->skinnum = MSG_ReadShort(&net_message);
        !            86: 
        !            87:        if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
        !            88:                to->effects = MSG_ReadLong(&net_message);
        !            89:        else if (bits & U_EFFECTS8)
        !            90:                to->effects = MSG_ReadByte(&net_message);
        !            91:        else if (bits & U_EFFECTS16)
        !            92:                to->effects = MSG_ReadShort(&net_message);
        !            93:        if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
        !            94:                to->renderfx = MSG_ReadLong(&net_message);
        !            95:        else if (bits & U_RENDERFX8)
        !            96:                to->renderfx = MSG_ReadByte(&net_message);
        !            97:        else if (bits & U_RENDERFX16)
        !            98:                to->renderfx = MSG_ReadShort(&net_message);
        !            99:        if (bits & U_ORIGIN1)
        !           100:                to->origin[0] = MSG_ReadCoord (&net_message);
        !           101:        if (bits & U_ORIGIN2)
        !           102:                to->origin[1] = MSG_ReadCoord (&net_message);
        !           103:        if (bits & U_ORIGIN3)
        !           104:                to->origin[2] = MSG_ReadCoord (&net_message);
        !           105:                
        !           106:        if (bits & U_ANGLE1)
        !           107:                to->angles[0] = MSG_ReadAngle(&net_message);
        !           108:        if (bits & U_ANGLE2)
        !           109:                to->angles[1] = MSG_ReadAngle(&net_message);
        !           110:        if (bits & U_ANGLE3)
        !           111:                to->angles[2] = MSG_ReadAngle(&net_message);
        !           112:        if (bits & U_OLDORIGIN)
        !           113:                MSG_ReadPos (&net_message, to->old_origin);
        !           114:        if (bits & U_SOUND)
        !           115:                to->sound = MSG_ReadByte (&net_message);
        !           116: 
        !           117:        if (bits & U_EVENT)
        !           118:                to->event = MSG_ReadByte (&net_message);
        !           119:        else
        !           120:                to->event = 0;
        !           121: 
        !           122:        if (bits & U_SOLID)
        !           123:                to->solid = MSG_ReadShort (&net_message);
        !           124: }
        !           125: 
        !           126: /*
        !           127: ==================
        !           128: CL_DeltaEntity
        !           129: 
        !           130: Parses deltas from the given base and adds the resulting entity
        !           131: to the current frame
        !           132: ==================
        !           133: */
        !           134: void CL_DeltaEntity (frame_t *frame, int newnum, entity_state_t *old, int bits)
        !           135: {
        !           136:        centity_t       *ent;
        !           137:        entity_state_t  *state;
        !           138: 
        !           139:        ent = &cl_entities[newnum];
        !           140: 
        !           141:        state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
        !           142:        cl.parse_entities++;
        !           143:        frame->num_entities++;
        !           144: 
        !           145:        CL_ParseDelta (old, state, newnum, bits);
        !           146: 
        !           147:        // some data changes will force no lerping
        !           148:        if (state->modelindex != ent->current.modelindex
        !           149:                || state->modelindex2 != ent->current.modelindex2
        !           150:                || state->modelindex3 != ent->current.modelindex3
        !           151:                || state->modelindex4 != ent->current.modelindex4
        !           152:                || abs(state->origin[0] - ent->current.origin[0]) > 512
        !           153:                || abs(state->origin[1] - ent->current.origin[1]) > 512
        !           154:                || abs(state->origin[2] - ent->current.origin[2]) > 512
        !           155:                || state->event == EV_PLAYER_TELEPORT
        !           156:                )
        !           157:        {
        !           158:                ent->serverframe = -99;
        !           159:        }
        !           160: 
        !           161:        if (ent->serverframe != cl.frame.serverframe - 1)
        !           162:        {       // wasn't in last update, so initialize some things
        !           163:                ent->trailcount = 1024;         // for diminishing rocket / grenade trails
        !           164:                // duplicate the current state so lerping doesn't hurt anything
        !           165:                ent->prev = *state;
        !           166:                VectorCopy (state->old_origin, ent->prev.origin);
        !           167:                VectorCopy (state->old_origin, ent->lerp_origin);
        !           168:        }
        !           169:        else
        !           170:        {       // shuffle the last state to previous
        !           171:                ent->prev = ent->current;
        !           172:        }
        !           173: 
        !           174:        ent->serverframe = cl.frame.serverframe;
        !           175:        ent->current = *state;
        !           176: }
        !           177: /*
        !           178: ==================
        !           179: CL_ParsePacketEntities
        !           180: An svc_packetentities has just been parsed, deal with the
        !           181: rest of the data stream.
        !           182: ==================
        !           183: */
        !           184: void CL_ParsePacketEntities (frame_t *oldframe, frame_t *newframe)
        !           185: {
        !           186:        int                     newnum;
        !           187:        int                     bits;
        !           188:        entity_state_t  *oldstate;
        !           189:        int                     oldindex, oldnum;
        !           190: 
        !           191:        newframe->parse_entities = cl.parse_entities;
        !           192:        newframe->num_entities = 0;
        !           193: 
        !           194:        // delta from the entities present in oldframe
        !           195:        oldindex = 0;
        !           196:        if (!oldframe)
        !           197:                oldnum = 99999;
        !           198:        else
        !           199:        {
        !           200:                if (oldindex >= oldframe->num_entities)
        !           201:                        oldnum = 99999;
        !           202:                else
        !           203:                {
        !           204:                        oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
        !           205:                        oldnum = oldstate->number;
        !           206:                }
        !           207:        }
        !           208:        while (1)
        !           209:        {
        !           210:                newnum = CL_ParseEntityBits (&bits);
        !           211:                if (newnum >= MAX_EDICTS)
        !           212:                        Com_Error (ERR_DROP,"CL_ParsePacketEntities: bad number:%i", newnum);
        !           213: 
        !           214:                if (net_message.readcount > net_message.cursize)
        !           215:                        Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
        !           216: 
        !           217:                if (!newnum)
        !           218:                        break;
        !           219: 
        !           220:                while (oldnum < newnum)
        !           221:                {       // one or more entities from the old packet are unchanged
        !           222:                        if (cl_shownet->value == 3)
        !           223:                                Com_Printf ("   unchanged: %i\n", oldnum);
        !           224:                        CL_DeltaEntity (newframe, oldnum, oldstate, 0);
        !           225:                        
        !           226:                        oldindex++;
        !           227: 
        !           228:                        if (oldindex >= oldframe->num_entities)
        !           229:                                oldnum = 99999;
        !           230:                        else
        !           231:                        {
        !           232:                                oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
        !           233:                                oldnum = oldstate->number;
        !           234:                        }
        !           235:                }
        !           236: 
        !           237:                if (bits & U_REMOVE)
        !           238:                {       // the entity present in oldframe is not in the current frame
        !           239:                        if (cl_shownet->value == 3)
        !           240:                                Com_Printf ("   remove: %i\n", newnum);
        !           241:                        if (oldnum != newnum)
        !           242:                                Com_Printf ("U_REMOVE: oldnum != newnum\n");
        !           243: 
        !           244:                        oldindex++;
        !           245: 
        !           246:                        if (oldindex >= oldframe->num_entities)
        !           247:                                oldnum = 99999;
        !           248:                        else
        !           249:                        {
        !           250:                                oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
        !           251:                                oldnum = oldstate->number;
        !           252:                        }
        !           253:                        continue;
        !           254:                }
        !           255: 
        !           256:                if (oldnum == newnum)
        !           257:                {       // delta from previous state
        !           258:                        if (cl_shownet->value == 3)
        !           259:                                Com_Printf ("   delta: %i\n", newnum);
        !           260:                        CL_DeltaEntity (newframe, newnum, oldstate, bits);
        !           261: 
        !           262:                        oldindex++;
        !           263: 
        !           264:                        if (oldindex >= oldframe->num_entities)
        !           265:                                oldnum = 99999;
        !           266:                        else
        !           267:                        {
        !           268:                                oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
        !           269:                                oldnum = oldstate->number;
        !           270:                        }
        !           271:                        continue;
        !           272:                }
        !           273: 
        !           274:                if (oldnum > newnum)
        !           275:                {       // delta from baseline
        !           276:                        if (cl_shownet->value == 3)
        !           277:                                Com_Printf ("   baseline: %i\n", newnum);
        !           278:                        CL_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits);
        !           279:                        continue;
        !           280:                }
        !           281: 
        !           282:        }
        !           283: 
        !           284:        // any remaining entities in the old frame are copied over
        !           285:        while (oldnum != 99999)
        !           286:        {       // one or more entities from the old packet are unchanged
        !           287:                if (cl_shownet->value == 3)
        !           288:                        Com_Printf ("   unchanged: %i\n", oldnum);
        !           289:                CL_DeltaEntity (newframe, oldnum, oldstate, 0);
        !           290:                
        !           291:                oldindex++;
        !           292: 
        !           293:                if (oldindex >= oldframe->num_entities)
        !           294:                        oldnum = 99999;
        !           295:                else
        !           296:                {
        !           297:                        oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
        !           298:                        oldnum = oldstate->number;
        !           299:                }
        !           300:        }
        !           301: }
        !           302: /*
        !           303: ===================
        !           304: CL_ParsePlayerstate
        !           305: ===================
        !           306: */
        !           307: void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
        !           308: {
        !           309:        int                     flags;
        !           310:        player_state_t  *state;
        !           311:        int                     i;
        !           312:        int                     statbits;
        !           313:        state = &newframe->playerstate;
        !           314: 
        !           315:        // clear to old value before delta parsing
        !           316:        if (oldframe)
        !           317:                *state = oldframe->playerstate;
        !           318:        else
        !           319:                memset (state, 0, sizeof(*state));
        !           320:        flags = MSG_ReadShort (&net_message);
        !           321: 
        !           322:        //
        !           323:        // parse the pmove_state_t
        !           324:        //
        !           325:        if (flags & PS_M_TYPE)
        !           326:                state->pmove.pm_type = MSG_ReadByte (&net_message);
        !           327: 
        !           328:        if (flags & PS_M_ORIGIN)
        !           329:        {
        !           330:                state->pmove.origin[0] = MSG_ReadShort (&net_message);
        !           331:                state->pmove.origin[1] = MSG_ReadShort (&net_message);
        !           332:                state->pmove.origin[2] = MSG_ReadShort (&net_message);
        !           333:        }
        !           334: 
        !           335:        if (flags & PS_M_VELOCITY)
        !           336:        {
        !           337:                state->pmove.velocity[0] = MSG_ReadShort (&net_message);
        !           338:                state->pmove.velocity[1] = MSG_ReadShort (&net_message);
        !           339:                state->pmove.velocity[2] = MSG_ReadShort (&net_message);
        !           340:        }
        !           341: 
        !           342:        if (flags & PS_M_TIME)
        !           343:                state->pmove.pm_time = MSG_ReadByte (&net_message);
        !           344: 
        !           345:        if (flags & PS_M_FLAGS)
        !           346:                state->pmove.pm_flags = MSG_ReadByte (&net_message);
        !           347: 
        !           348:        if (flags & PS_M_GRAVITY)
        !           349:                state->pmove.gravity = MSG_ReadShort (&net_message);
        !           350: 
        !           351:        if (flags & PS_M_DELTA_ANGLES)
        !           352:        {
        !           353:                state->pmove.delta_angles[0] = MSG_ReadShort (&net_message);
        !           354:                state->pmove.delta_angles[1] = MSG_ReadShort (&net_message);
        !           355:                state->pmove.delta_angles[2] = MSG_ReadShort (&net_message);
        !           356:        }
        !           357: 
        !           358:        if (cl.attractloop)
        !           359:                state->pmove.pm_type = PM_FREEZE;               // demo playback
        !           360: 
        !           361:        //
        !           362:        // parse the rest of the player_state_t
        !           363:        //
        !           364:        if (flags & PS_VIEWOFFSET)
        !           365:        {
        !           366:                state->viewoffset[0] = MSG_ReadChar (&net_message) * 0.25;
        !           367:                state->viewoffset[1] = MSG_ReadChar (&net_message) * 0.25;
        !           368:                state->viewoffset[2] = MSG_ReadChar (&net_message) * 0.25;
        !           369:        }
        !           370: 
        !           371:        if (flags & PS_VIEWANGLES)
        !           372:        {
        !           373:                state->viewangles[0] = MSG_ReadAngle16 (&net_message);
        !           374:                state->viewangles[1] = MSG_ReadAngle16 (&net_message);
        !           375:                state->viewangles[2] = MSG_ReadAngle16 (&net_message);
        !           376:        }
        !           377: 
        !           378:        if (flags & PS_KICKANGLES)
        !           379:        {
        !           380:                state->kick_angles[0] = MSG_ReadChar (&net_message) * 0.25;
        !           381:                state->kick_angles[1] = MSG_ReadChar (&net_message) * 0.25;
        !           382:                state->kick_angles[2] = MSG_ReadChar (&net_message) * 0.25;
        !           383:        }
        !           384:        if (flags & PS_WEAPONINDEX)
        !           385:        {
        !           386:                state->gunindex = MSG_ReadByte (&net_message);
        !           387:        }
        !           388:        if (flags & PS_WEAPONFRAME)
        !           389:        {
        !           390:                state->gunframe = MSG_ReadByte (&net_message);
        !           391:                state->gunoffset[0] = MSG_ReadChar (&net_message)*0.25;
        !           392:                state->gunoffset[1] = MSG_ReadChar (&net_message)*0.25;
        !           393:                state->gunoffset[2] = MSG_ReadChar (&net_message)*0.25;
        !           394:                state->gunangles[0] = MSG_ReadChar (&net_message)*0.25;
        !           395:                state->gunangles[1] = MSG_ReadChar (&net_message)*0.25;
        !           396:                state->gunangles[2] = MSG_ReadChar (&net_message)*0.25;
        !           397:        }
        !           398:        if (flags & PS_BLEND)
        !           399:        {
        !           400:                state->blend[0] = MSG_ReadByte (&net_message)/255.0;
        !           401:                state->blend[1] = MSG_ReadByte (&net_message)/255.0;
        !           402:                state->blend[2] = MSG_ReadByte (&net_message)/255.0;
        !           403:                state->blend[3] = MSG_ReadByte (&net_message)/255.0;
        !           404:        }
        !           405:        if (flags & PS_FOV)
        !           406:                state->fov = MSG_ReadByte (&net_message);
        !           407:        if (flags & PS_RDFLAGS)
        !           408:                state->rdflags = MSG_ReadByte (&net_message);
        !           409:        // parse stats
        !           410:        statbits = MSG_ReadLong (&net_message);
        !           411:        for (i=0 ; i<MAX_STATS ; i++)
        !           412:                if (statbits & (1<<i) )
        !           413:                        state->stats[i] = MSG_ReadShort(&net_message);
        !           414: }
        !           415: /*
        !           416: ==================
        !           417: CL_FireEntityEvents
        !           418: 
        !           419: ==================
        !           420: */
        !           421: void CL_FireEntityEvents (frame_t *frame)
        !           422: {
        !           423:        entity_state_t          *s1;
        !           424:        int                                     pnum, num;
        !           425: 
        !           426:        for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
        !           427:        {
        !           428:                num = (frame->parse_entities + pnum)&(MAX_PARSE_ENTITIES-1);
        !           429:                s1 = &cl_parse_entities[num];
        !           430:                if (s1->event)
        !           431:                        CL_EntityEvent (s1);
        !           432: 
        !           433:                // EF_TELEPORTER acts like an event, but is not cleared each frame
        !           434:                if (s1->effects & EF_TELEPORTER)
        !           435:                        CL_TeleporterParticles (s1);
        !           436:        }
        !           437: }
        !           438: 
        !           439: 
        !           440: /*
        !           441: ================
        !           442: CL_ParseFrame
        !           443: ================
        !           444: */
        !           445: void CL_ParseFrame (void)
        !           446: {
        !           447:        int                     cmd;
        !           448:        int                     len;
        !           449:        frame_t         *old;
        !           450:        memset (&cl.frame, 0, sizeof(cl.frame));
        !           451:        cl.frame.serverframe = MSG_ReadLong (&net_message);
        !           452:        cl.frame.deltaframe = MSG_ReadLong (&net_message);
        !           453:        cl.frame.servertime = cl.frame.serverframe*100;
        !           454: 
        !           455:        // BIG HACK to let old demos continue to work
        !           456:        if (cls.serverProtocol != 26)
        !           457:                cl.surpressCount = MSG_ReadByte (&net_message);
        !           458: 
        !           459:        if (cl_shownet->value == 3)
        !           460:                Com_Printf ("   frame:%i  delta:%i\n", cl.frame.serverframe,
        !           461:                cl.frame.deltaframe);
        !           462: 
        !           463:        // If the frame is delta compressed from data that we
        !           464:        // no longer have available, we must suck up the rest of
        !           465:        // the frame, but not use it, then ask for a non-compressed
        !           466:        // message 
        !           467:        if (cl.frame.deltaframe <= 0)
        !           468:        {
        !           469:                cl.frame.valid = true;          // uncompressed frame
        !           470:                old = NULL;
        !           471:                cls.demowaiting = false;        // we can start recording now
        !           472:        }
        !           473:        else
        !           474:        {
        !           475:                old = &cl.frames[cl.frame.deltaframe & UPDATE_MASK];
        !           476:                if (!old->valid)
        !           477:                {       // should never happen
        !           478:                        Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
        !           479:                }
        !           480:                if (old->serverframe != cl.frame.deltaframe)
        !           481:                {       // The frame that the server did the delta from
        !           482:                        // is too old, so we can't reconstruct it properly.
        !           483:                        Com_Printf ("Delta frame too old.\n");
        !           484:                }
        !           485:                else if (cl.parse_entities - old->parse_entities > MAX_PARSE_ENTITIES-128)
        !           486:                {
        !           487:                        Com_Printf ("Delta parse_entities too old.\n");
        !           488:                }
        !           489:                else
        !           490:                        cl.frame.valid = true;  // valid delta parse
        !           491:        }
        !           492:        // clamp time 
        !           493:        if (cl.time > cl.frame.servertime)
        !           494:                cl.time = cl.frame.servertime;
        !           495:        else if (cl.time < cl.frame.servertime - 100)
        !           496:                cl.time = cl.frame.servertime - 100;
        !           497: 
        !           498:        // read areabits
        !           499:        len = MSG_ReadByte (&net_message);
        !           500:        MSG_ReadData (&net_message, &cl.frame.areabits, len);
        !           501: 
        !           502:        // read playerinfo
        !           503:        cmd = MSG_ReadByte (&net_message);
        !           504:        SHOWNET(svc_strings[cmd]);
        !           505:        if (cmd != svc_playerinfo)
        !           506:                Com_Error (ERR_DROP, "CL_ParseFrame: not playerinfo");
        !           507:        CL_ParsePlayerstate (old, &cl.frame);
        !           508: 
        !           509:        // read packet entities
        !           510:        cmd = MSG_ReadByte (&net_message);
        !           511:        SHOWNET(svc_strings[cmd]);
        !           512:        if (cmd != svc_packetentities)
        !           513:                Com_Error (ERR_DROP, "CL_ParseFrame: not packetentities");
        !           514:        CL_ParsePacketEntities (old, &cl.frame);
        !           515: 
        !           516:        // save the frame off in the backup array for later delta comparisons
        !           517:        cl.frames[cl.frame.serverframe & UPDATE_MASK] = cl.frame;
        !           518: 
        !           519:        if (cl.frame.valid)
        !           520:        {
        !           521:                // getting a valid frame message ends the connection process
        !           522:                if (cls.state != ca_active)
        !           523:                {
        !           524:                        cls.state = ca_active;
        !           525:                        cl.force_refdef = true;
        !           526:                        cl.predicted_origin[0] = cl.frame.playerstate.pmove.origin[0]*0.125;
        !           527:                        cl.predicted_origin[1] = cl.frame.playerstate.pmove.origin[1]*0.125;
        !           528:                        cl.predicted_origin[2] = cl.frame.playerstate.pmove.origin[2]*0.125;
        !           529:                        VectorCopy (cl.frame.playerstate.viewangles, cl.predicted_angles);
        !           530:                        if (cls.disable_servercount != cl.servercount
        !           531:                                && cl.refresh_prepped)
        !           532:                                SCR_EndLoadingPlaque ();        // get rid of loading plaque
        !           533:                }
        !           534:                cl.sound_prepped = true;        // can start mixing ambient sounds
        !           535:        
        !           536:                // fire entity events
        !           537:                CL_FireEntityEvents (&cl.frame);
        !           538:                CL_CheckPredictionError ();
        !           539:        }
        !           540: }
        !           541: /*
        !           542: ==========================================================================
        !           543: 
        !           544: INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS
        !           545: 
        !           546: ==========================================================================
        !           547: */
        !           548: 
        !           549: /*
        !           550: ===============
        !           551: CL_AddPacketEntities
        !           552: 
        !           553: ===============
        !           554: */
        !           555: void CL_AddPacketEntities (frame_t *frame)
        !           556: {
        !           557:        entity_t                        ent;
        !           558:        entity_state_t          *s1;
        !           559:        float                           autorotate;
        !           560:        int                                     i;
        !           561:        int                                     pnum;
        !           562:        centity_t                       *cent;
        !           563:        int                                     autoanim;
        !           564:        clientinfo_t            *ci;
        !           565:        int                                     effects, renderfx;
        !           566: 
        !           567:        // bonus items rotate at a fixed rate
        !           568:        autorotate = anglemod(cl.time/10);
        !           569: 
        !           570:        // brush models can auto animate their frames
        !           571:        autoanim = 2*cl.time/1000;
        !           572: 
        !           573:        memset (&ent, 0, sizeof(ent));
        !           574: 
        !           575:        for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
        !           576:        {
        !           577:                s1 = &cl_parse_entities[(frame->parse_entities+pnum)&(MAX_PARSE_ENTITIES-1)];
        !           578: 
        !           579:                cent = &cl_entities[s1->number];
        !           580: 
        !           581:                effects = s1->effects;
        !           582:                renderfx = s1->renderfx;
        !           583: 
        !           584:                        // set frame
        !           585:                if (effects & EF_ANIM01)
        !           586:                        ent.frame = autoanim & 1;
        !           587:                else if (effects & EF_ANIM23)
        !           588:                        ent.frame = 2 + (autoanim & 1);
        !           589:                else if (effects & EF_ANIM_ALL)
        !           590:                        ent.frame = autoanim;
        !           591:                else if (effects & EF_ANIM_ALLFAST)
        !           592:                        ent.frame = cl.time / 100;
        !           593:                else
        !           594:                        ent.frame = s1->frame;
        !           595: 
        !           596: 
        !           597:                // quad and pent can do different things on client
        !           598:                if (effects & EF_PENT)
        !           599:                {
        !           600:                        effects &= ~EF_PENT;
        !           601:                        effects |= EF_COLOR_SHELL;
        !           602:                        renderfx |= RF_SHELL_RED;
        !           603:                }
        !           604: 
        !           605:                if (effects & EF_QUAD)
        !           606:                {
        !           607:                        effects &= ~EF_QUAD;
        !           608:                        effects |= EF_COLOR_SHELL;
        !           609:                        renderfx |= RF_SHELL_BLUE;
        !           610:                }
        !           611: 
        !           612:                ent.oldframe = cent->prev.frame;
        !           613:                ent.backlerp = 1.0 - cl.lerpfrac;
        !           614: 
        !           615:                if (renderfx & (RF_FRAMELERP|RF_BEAM))
        !           616:                {       // step origin discretely, because the frames
        !           617:                        // do the animation properly
        !           618:                        VectorCopy (cent->current.origin, ent.origin);
        !           619:                        VectorCopy (cent->current.old_origin, ent.oldorigin);
        !           620:                }
        !           621:                else
        !           622:                {       // interpolate origin
        !           623:                        for (i=0 ; i<3 ; i++)
        !           624:                        {
        !           625:                                ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac * 
        !           626:                                        (cent->current.origin[i] - cent->prev.origin[i]);
        !           627:                        }
        !           628:                }
        !           629: 
        !           630:                // create a new entity
        !           631:        
        !           632:                // tweak the color of beams
        !           633:                if ( renderfx & RF_BEAM )
        !           634:                {       // the four beam colors are encoded in 32 bits of skinnum (hack)
        !           635:                        ent.alpha = 0.30;
        !           636:                        ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff;
        !           637:                        ent.model = NULL;
        !           638:                }
        !           639:                else
        !           640:                {
        !           641:                        // set skin
        !           642:                        if (s1->modelindex == 255)
        !           643:                        {       // use custom player skin
        !           644:                                ent.skinnum = 0;
        !           645:                                ci = &cl.clientinfo[s1->skinnum];
        !           646:                                ent.skin = ci->skin;
        !           647:                                ent.model = ci->model;
        !           648:                                if (!ent.skin || !ent.model)
        !           649:                                {
        !           650:                                        ent.skin = cl.baseclientinfo.skin;
        !           651:                                        ent.model = cl.baseclientinfo.model;
        !           652:                                }
        !           653:                        }
        !           654:                        else
        !           655:                        {
        !           656:                                ent.skinnum = s1->skinnum;
        !           657:                                ent.skin = NULL;
        !           658:                                ent.model = cl.model_draw[s1->modelindex];
        !           659:                        }
        !           660:                }
        !           661: 
        !           662:                // only used for black hole model right now, FIXME: do better
        !           663:                if (renderfx == RF_TRANSLUCENT)
        !           664:                        ent.alpha = 0.70;
        !           665: 
        !           666:                // render effects (fullbright, translucent, etc)
        !           667:                if ((effects & EF_COLOR_SHELL))
        !           668:                        ent.flags = 0;  // renderfx go on color shell entity
        !           669:                else
        !           670:                        ent.flags = renderfx;
        !           671: 
        !           672:                // calculate angles
        !           673:                if (effects & EF_ROTATE)
        !           674:                {       // some bonus items auto-rotate
        !           675:                        ent.angles[0] = 0;
        !           676:                        ent.angles[1] = autorotate;
        !           677:                        ent.angles[2] = 0;
        !           678:                }
        !           679:                else
        !           680:                {       // interpolate angles
        !           681:                        float   a1, a2;
        !           682: 
        !           683:                        for (i=0 ; i<3 ; i++)
        !           684:                        {
        !           685:                                a1 = cent->current.angles[i];
        !           686:                                a2 = cent->prev.angles[i];
        !           687:                                ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac);
        !           688:                        }
        !           689:                }
        !           690: 
        !           691:                if (s1->number == cl.playernum+1)
        !           692:                {
        !           693:                        ent.flags |= RF_VIEWERMODEL;    // only draw from mirrors
        !           694:                        // FIXME: still pass to refresh
        !           695: 
        !           696:                        if (effects & EF_FLAG1)
        !           697:                                V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1);
        !           698:                        else if (effects & EF_FLAG2)
        !           699:                                V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0);
        !           700: 
        !           701:                        continue;
        !           702:                }
        !           703: 
        !           704:                // if set to invisible, skip
        !           705:                if (!s1->modelindex)
        !           706:                        continue;
        !           707: 
        !           708:                if (effects & EF_BFG)
        !           709:                {
        !           710:                        ent.flags |= RF_TRANSLUCENT;
        !           711:                        ent.alpha = 0.30;
        !           712:                }
        !           713: 
        !           714:                // add to refresh list
        !           715:                V_AddEntity (&ent);
        !           716: 
        !           717:                // color shells generate a seperate entity for the main model
        !           718:                if (effects & EF_COLOR_SHELL)
        !           719:                {
        !           720:                        ent.flags = renderfx | RF_TRANSLUCENT;
        !           721:                        ent.alpha = 0.30;
        !           722:                        V_AddEntity (&ent);
        !           723:                }
        !           724: 
        !           725:                ent.skin = NULL;                // never use a custom skin on others
        !           726:                ent.skinnum = 0;
        !           727:                ent.flags = 0;
        !           728:                ent.alpha = 0;
        !           729: 
        !           730:                // duplicate for linked models
        !           731:                if (s1->modelindex2)
        !           732:                {
        !           733:                        if (s1->modelindex2 == 255)
        !           734:                        {       // custom weapon
        !           735:                                ci = &cl.clientinfo[s1->skinnum];
        !           736:                                ent.model = ci->weaponmodel;
        !           737:                                if (!ent.model)
        !           738:                                        ent.model = cl.baseclientinfo.weaponmodel;
        !           739:                        }
        !           740:                        else
        !           741:                                ent.model = cl.model_draw[s1->modelindex2];
        !           742:                        V_AddEntity (&ent);
        !           743:                }
        !           744:                if (s1->modelindex3)
        !           745:                {
        !           746:                        ent.model = cl.model_draw[s1->modelindex3];
        !           747:                        V_AddEntity (&ent);
        !           748:                }
        !           749:                if (s1->modelindex4)
        !           750:                {
        !           751:                        ent.model = cl.model_draw[s1->modelindex4];
        !           752:                        V_AddEntity (&ent);
        !           753:                }
        !           754: 
        !           755:                if ( effects & EF_POWERSCREEN )
        !           756:                {
        !           757:                        ent.model = cl_mod_powerscreen;
        !           758:                        ent.oldframe = 0;
        !           759:                        ent.frame = 0;
        !           760:                        ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN);
        !           761:                        ent.alpha = 0.30;
        !           762:                        V_AddEntity (&ent);
        !           763:                }
        !           764: 
        !           765:                // add automatic particle trails
        !           766:                if ( (effects&~EF_ROTATE) )
        !           767:                {
        !           768:                        if (effects & EF_ROCKET)
        !           769:                        {
        !           770:                                CL_RocketTrail (cent->lerp_origin, ent.origin, cent);
        !           771:                                V_AddLight (ent.origin, 200, 1, 1, 0);
        !           772:                        }
        !           773:                        else if (effects & EF_BLASTER)
        !           774:                        {
        !           775:                                CL_BlasterTrail (cent->lerp_origin, ent.origin);
        !           776:                                V_AddLight (ent.origin, 200, 1, 1, 0);
        !           777:                        }
        !           778:                        else if (effects & EF_HYPERBLASTER)
        !           779:                        {
        !           780:                                V_AddLight (ent.origin, 200, 1, 1, 0);
        !           781:                        }
        !           782:                        else if (effects & EF_GIB)
        !           783:                        {
        !           784:                                CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
        !           785:                        }
        !           786:                        else if (effects & EF_GRENADE)
        !           787:                        {
        !           788:                                CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
        !           789:                        }
        !           790:                        else if (effects & EF_FLIES)
        !           791:                        {
        !           792:                                CL_FlyEffect (cent, ent.origin);
        !           793:                        }
        !           794:                        else if (effects & EF_BFG)
        !           795:                        {
        !           796:                                static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75};
        !           797: 
        !           798:                                if (effects & EF_ANIM_ALLFAST)
        !           799:                                {
        !           800:                                        CL_BfgParticles (&ent);
        !           801:                                        i = 200;
        !           802:                                }
        !           803:                                else
        !           804:                                {
        !           805:                                        i = bfg_lightramp[s1->frame];
        !           806:                                }
        !           807:                                V_AddLight (ent.origin, i, 0, 1, 0);
        !           808:                        }
        !           809:                        else if (effects & EF_FLAG1)
        !           810:                        {
        !           811:                                CL_FlagTrail (cent->lerp_origin, ent.origin, 242);
        !           812:                                V_AddLight (ent.origin, 225, 1, 0.1, 0.1);
        !           813:                        }
        !           814:                        else if (effects & EF_FLAG2)
        !           815:                        {
        !           816:                                CL_FlagTrail (cent->lerp_origin, ent.origin, 115);
        !           817:                                V_AddLight (ent.origin, 225, 0.1, 0.1, 1);
        !           818:                        }
        !           819:                        else if (effects & EF_GREENGIB)
        !           820:                        {
        !           821:                                CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);                             
        !           822:                        }
        !           823:                        else if (effects & EF_BOOMER)
        !           824:                        {
        !           825:                                CL_BoomerTrail (cent->lerp_origin, ent.origin);
        !           826:                                V_AddLight (ent.origin, 100, 1, 0.5, 0.5);
        !           827:                        }
        !           828:                }
        !           829: 
        !           830:                VectorCopy (ent.origin, cent->lerp_origin);
        !           831:        }
        !           832: }
        !           833: 
        !           834: 
        !           835: 
        !           836: /*
        !           837: ==============
        !           838: CL_AddViewWeapon
        !           839: ==============
        !           840: */
        !           841: void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops)
        !           842: {
        !           843:        entity_t        gun;            // view model
        !           844:        int                     i;
        !           845: 
        !           846:        // allow the gun to be completely removed
        !           847:        if (!cl_gun->value)
        !           848:                return;
        !           849: 
        !           850:        // don't draw gun if in wide angle view
        !           851:        if (ps->fov > 90)
        !           852:                return;
        !           853: 
        !           854:        memset (&gun, 0, sizeof(gun));
        !           855: 
        !           856:        if (gun_model)
        !           857:                gun.model = gun_model;  // development tool
        !           858:        else
        !           859:                gun.model = cl.model_draw[ps->gunindex];
        !           860:        if (!gun.model)
        !           861:                return;
        !           862: 
        !           863:        // set up gun position
        !           864:        for (i=0 ; i<3 ; i++)
        !           865:        {
        !           866:                gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i]
        !           867:                        + cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
        !           868:                gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i],
        !           869:                        ps->gunangles[i], cl.lerpfrac);
        !           870:        }
        !           871: 
        !           872:        if (gun_frame)
        !           873:        {
        !           874:                gun.frame = gun_frame;  // development tool
        !           875:                gun.oldframe = gun_frame;       // development tool
        !           876:        }
        !           877:        else
        !           878:        {
        !           879:                gun.frame = ps->gunframe;
        !           880:                if (gun.frame == 0)
        !           881:                        gun.oldframe = 0;       // just changed weapons, don't lerp from old
        !           882:                else
        !           883:                        gun.oldframe = ops->gunframe;
        !           884:        }
        !           885: 
        !           886:        gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
        !           887:        gun.backlerp = 1.0 - cl.lerpfrac;
        !           888:        VectorCopy (gun.origin, gun.oldorigin); // don't lerp at all
        !           889:        V_AddEntity (&gun);
        !           890: }
        !           891: 
        !           892: /*
        !           893: ===============
        !           894: CL_CalcViewValues
        !           895: Sets cl.refdef view values
        !           896: ===============
        !           897: */
        !           898: void CL_CalcViewValues (void)
        !           899: {
        !           900:        int                     i;
        !           901:        float           lerp, backlerp;
        !           902:        centity_t       *ent;
        !           903:        frame_t         *oldframe;
        !           904:        player_state_t  *ps, *ops;
        !           905: 
        !           906:        // find the previous frame to interpolate from
        !           907:        ps = &cl.frame.playerstate;
        !           908:        i = (cl.frame.serverframe - 1) & UPDATE_MASK;
        !           909:        oldframe = &cl.frames[i];
        !           910:        if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
        !           911:                oldframe = &cl.frame;           // previous frame was dropped or involid
        !           912:        ops = &oldframe->playerstate;
        !           913:        // see if the player entity was teleported this frame
        !           914:        if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8
        !           915:                || abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256*8
        !           916:                || abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256*8)
        !           917:                ops = ps;               // don't interpolate
        !           918: 
        !           919:        ent = &cl_entities[cl.playernum+1];
        !           920:        lerp = cl.lerpfrac;
        !           921: 
        !           922:        // calculate the origin
        !           923:        if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
        !           924:        {       // use predicted values
        !           925:                unsigned        delta;
        !           926: 
        !           927:                backlerp = 1.0 - lerp;
        !           928:                for (i=0 ; i<3 ; i++)
        !           929:                {
        !           930:                        cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i] 
        !           931:                                + cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i])
        !           932:                                - backlerp * cl.prediction_error[i];
        !           933:                }
        !           934: 
        !           935:                // smooth out stair climbing
        !           936:                delta = cls.realtime - cl.predicted_step_time;
        !           937:                if (delta < 100)
        !           938:                        cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01;
        !           939:        }
        !           940:        else
        !           941:        {       // just use interpolated values
        !           942:                for (i=0 ; i<3 ; i++)
        !           943:                        cl.refdef.vieworg[i] = ops->pmove.origin[i]*0.125 + ops->viewoffset[i] 
        !           944:                                + lerp * (ps->pmove.origin[i]*0.125 + ps->viewoffset[i] 
        !           945:                                - (ops->pmove.origin[i]*0.125 + ops->viewoffset[i]) );
        !           946:        }
        !           947: 
        !           948:        // if not running a demo or on a locked frame, add the local angle movement
        !           949:        if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD )
        !           950:        {       // use predicted values
        !           951:                for (i=0 ; i<3 ; i++)
        !           952:                        cl.refdef.viewangles[i] = cl.predicted_angles[i];
        !           953:        }
        !           954:        else
        !           955:        {       // just use interpolated values
        !           956:                for (i=0 ; i<3 ; i++)
        !           957:                        cl.refdef.viewangles[i] = LerpAngle (ops->viewangles[i], ps->viewangles[i], lerp);
        !           958:        }
        !           959: 
        !           960:        for (i=0 ; i<3 ; i++)
        !           961:                cl.refdef.viewangles[i] += LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp);
        !           962:        AngleVectors (cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up);
        !           963: 
        !           964:        // interpolate field of view
        !           965:        cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov);
        !           966:        // don't interpolate blend color
        !           967:        for (i=0 ; i<4 ; i++)
        !           968:                cl.refdef.blend[i] = ps->blend[i];
        !           969: 
        !           970:        // add the weapon
        !           971:        CL_AddViewWeapon (ps, ops);
        !           972: }
        !           973: /*
        !           974: ===============
        !           975: CL_AddEntities
        !           976: Emits all entities, particles, and lights to the refresh
        !           977: ===============
        !           978: */
        !           979: void CL_AddEntities (void)
        !           980: {
        !           981:        if (cls.state != ca_active)
        !           982:                return;
        !           983:        if (cl.time > cl.frame.servertime)
        !           984:        {
        !           985:                if (cl_showclamp->value)
        !           986:                        Com_Printf ("high clamp %i\n", cl.time - cl.frame.servertime);
        !           987:                cl.time = cl.frame.servertime;
        !           988:                cl.lerpfrac = 1.0;
        !           989:        }
        !           990:        else if (cl.time < cl.frame.servertime - 100)
        !           991:        {
        !           992:                if (cl_showclamp->value)
        !           993:                        Com_Printf ("low clamp %i\n", cl.frame.servertime-100 - cl.time);
        !           994:                cl.time = cl.frame.servertime - 100;
        !           995:                cl.lerpfrac = 0;
        !           996:        }
        !           997:        else
        !           998:                cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01;
        !           999: 
        !          1000:        if (cl_timedemo->value)
        !          1001:                cl.lerpfrac = 1.0;
        !          1002: 
        !          1003:        CL_AddPacketEntities (&cl.frame);
        !          1004:        CL_AddTEnts ();
        !          1005:        CL_AddParticles ();
        !          1006:        CL_AddDLights ();
        !          1007:        CL_AddLightStyles ();
        !          1008:        CL_CalcViewValues ();
        !          1009: }
        !          1010: /*
        !          1011: ===============
        !          1012: CL_GetEntitySoundOrigin
        !          1013: Called to get the sound spatialization origin
        !          1014: ===============
        !          1015: */
        !          1016: void CL_GetEntitySoundOrigin (int ent, vec3_t org)
        !          1017: {
        !          1018:        centity_t       *old;
        !          1019:        if (ent < 0 || ent >= MAX_EDICTS)
        !          1020:                Com_Error (ERR_DROP, "CL_GetEntitySoundOrigin: bad ent");
        !          1021:        old = &cl_entities[ent];
        !          1022:        VectorCopy (old->lerp_origin, org);
        !          1023:        // FIXME: bmodel issues...
        !          1024: }

unix.superglobalmegacorp.com

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