diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 01e4d1d0a..ab4d6ece1 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -383,74 +383,6 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean if (morebits & U_EFFECTS16) to->effects = (to->effects&0x00ff)|(MSG_ReadByte()<<8); - - if (to->number>=cl.maxlerpents) - { - cl.maxlerpents = to->number+16; - cl.lerpents = BZ_Realloc(cl.lerpents, sizeof(entity_state_t)*cl.maxlerpents); - } - - VectorSubtract(to->origin, from->origin, move); - - if (to->frame != from->frame) - { - cl.lerpents[to->number].oldframechange = cl.lerpents[to->number].framechange; //marked for hl models - cl.lerpents[to->number].framechange = cl.servertime; //marked for hl models - } - - if (to->modelindex != from->modelindex || to->number != from->number || VectorLength(move)>500) //model changed... or entity changed... - { - cl.lerpents[to->number].oldframechange = cl.lerpents[to->number].framechange; //marked for hl models - cl.lerpents[to->number].framechange = cl.servertime; //marked for hl models - - cl.lerpents[to->number].lerptime = -10; - cl.lerpents[to->number].lerprate = 0; - - if (!new) - return; - move[0] = 1; //make sure it enters the next block. - } - if (to->frame != from->frame || move[0] || move[1] || move[2]) - { - if (new) //lerp from the new position instead of old, so no lerp - { - cl.lerpents[to->number].origin[0] = to->origin[0]; - cl.lerpents[to->number].origin[1] = to->origin[1]; - cl.lerpents[to->number].origin[2] = to->origin[2]; - - cl.lerpents[to->number].angles[0] = to->angles[0]; - cl.lerpents[to->number].angles[1] = to->angles[1]; - cl.lerpents[to->number].angles[2] = to->angles[2]; - } - else - { - cl.lerpents[to->number].origin[0] = from->origin[0]; - cl.lerpents[to->number].origin[1] = from->origin[1]; - cl.lerpents[to->number].origin[2] = from->origin[2]; - - cl.lerpents[to->number].angles[0] = from->angles[0]; - cl.lerpents[to->number].angles[1] = from->angles[1]; - cl.lerpents[to->number].angles[2] = from->angles[2]; - } -//we have three sorts of movement. -//1: stepping monsters. These have frames and tick at 10fps. -//2: physics. Objects moving acording to gravity. -//3: both. This is really awkward. And I'm really lazy. -//the real solution would be to seperate the two. - cl.lerpents[to->number].lerprate = cl.servertime-cl.lerpents[to->number].lerptime; //time per update -// Con_Printf("%f=%f-%f\n", cl.lerpents[to->number].lerprate, cl.time, cl.lerpents[to->number].lerptime); - cl.lerpents[to->number].frame = from->frame; - cl.lerpents[to->number].lerptime = cl.servertime; - - if (cl.lerpents[to->number].lerprate>0.2) - cl.lerpents[to->number].lerprate=0.2; - - //store this off for new ents to use. - if (new) - cl.lerpents[to->number].lerprate = newlerprate; - if (to->frame == from->frame && !new) //(h2 runs at 20fps) - newlerprate = cl.lerpents[to->number].lerprate; - } } @@ -514,6 +446,8 @@ void CL_ParsePacketEntities (qboolean delta) newp = &cl.frames[newpacket].packet_entities; cl.frames[newpacket].invalid = false; + newp->servertime = cl.gametime; + if (delta) { from = MSG_ReadByte (); @@ -944,6 +878,7 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o( /*cl.servermovesequence =*/ MSG_ReadLong(); pack = &cl.frames[(cls.netchan.incoming_sequence)&UPDATE_MASK].packet_entities; + pack->servertime = cl.gametime; oldpack = &cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities; from = oldpack->entities; @@ -988,11 +923,6 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o( pack->max_entities = pack->num_entities+16; pack->entities = BZ_Realloc(pack->entities, sizeof(entity_state_t)*pack->max_entities); } - if (read>=cl.maxlerpents) - { - cl.maxlerpents = read+16; - cl.lerpents = BZ_Realloc(cl.lerpents, sizeof(entity_state_t)*cl.maxlerpents); - } to = &pack->entities[pack->num_entities]; pack->num_entities++; @@ -1000,58 +930,6 @@ void CLNQ_ParseDarkPlaces5Entities(void) //the things I do.. :o( to->number = read; DP5_ParseDelta(to); to->flags &= ~0x80000000; - - if (!from || to->modelindex != from->modelindex || to->number != from->number) //model changed... or entity changed... - { - cl.lerpents[to->number].lerptime = -10; - cl.lerpents[to->number].origin[0] = to->origin[0]; - cl.lerpents[to->number].origin[1] = to->origin[1]; - cl.lerpents[to->number].origin[2] = to->origin[2]; - - cl.lerpents[to->number].angles[0] = to->angles[0]; - cl.lerpents[to->number].angles[1] = to->angles[1]; - cl.lerpents[to->number].angles[2] = to->angles[2]; - } - else if (to->frame != from->frame || to->origin[0] != from->origin[0] || to->origin[1] != from->origin[1] || to->origin[2] != from->origin[2]) - { - if (from == &defaultstate) //lerp from the new position instead of old, so no lerp - { - cl.lerpents[to->number].origin[0] = to->origin[0]; - cl.lerpents[to->number].origin[1] = to->origin[1]; - cl.lerpents[to->number].origin[2] = to->origin[2]; - - cl.lerpents[to->number].angles[0] = to->angles[0]; - cl.lerpents[to->number].angles[1] = to->angles[1]; - cl.lerpents[to->number].angles[2] = to->angles[2]; - } - else - { - cl.lerpents[to->number].origin[0] = from->origin[0]; - cl.lerpents[to->number].origin[1] = from->origin[1]; - cl.lerpents[to->number].origin[2] = from->origin[2]; - - cl.lerpents[to->number].angles[0] = from->angles[0]; - cl.lerpents[to->number].angles[1] = from->angles[1]; - cl.lerpents[to->number].angles[2] = from->angles[2]; - } - //we have three sorts of movement. - //1: stepping monsters. These have frames and tick at 10fps. - //2: physics. Objects moving acording to gravity. - //3: both. This is really awkward. And I'm really lazy. - cl.lerpents[to->number].lerprate = cl.oldgametime-cl.lerpents[to->number].lerptime; //time per update - cl.lerpents[to->number].frame = from->frame; - cl.lerpents[to->number].lerptime = cl.oldgametime; - - if (cl.lerpents[to->number].lerprate>0.2) - cl.lerpents[to->number].lerprate=0.2; - - //store this off for new ents to use. - // if (new) - // cl.lerpents[state->number].lerptime = newlerprate; - // else - if (to->frame == from->frame) - newlerprate = cl.lerpents[to->number].lerprate; - } } //the pack has all the new ones in it, now copy the old ones in that wern't removed (or changed). @@ -1171,12 +1049,6 @@ void CLNQ_ParseEntity(unsigned int bits) state = &pack->entities[pack->num_entities++]; } - if (num>=cl.maxlerpents) - { - cl.maxlerpents = num+16; - cl.lerpents = BZ_Realloc(cl.lerpents, sizeof(entity_state_t)*cl.maxlerpents); - } - from = CL_FindOldPacketEntity(num); //this could be optimised. base = &cl_baselines[num]; @@ -1250,37 +1122,6 @@ void CLNQ_ParseEntity(unsigned int bits) state->angles[1] = cl.viewangles[pnum][1]; state->angles[2] = cl.viewangles[pnum][2]; } - - - if (!from || state->modelindex != from->modelindex || state->number != from->number) //model changed... or entity changed... - cl.lerpents[state->number].lerprate = newlerprate; - else if (state->frame != from->frame || state->origin[0] != from->origin[0] || state->origin[1] != from->origin[1] || state->origin[2] != from->origin[2]) - { - cl.lerpents[state->number].origin[0] = from->origin[0]; - cl.lerpents[state->number].origin[1] = from->origin[1]; - cl.lerpents[state->number].origin[2] = from->origin[2]; - - cl.lerpents[state->number].angles[0] = from->angles[0]; - cl.lerpents[state->number].angles[1] = from->angles[1]; - cl.lerpents[state->number].angles[2] = from->angles[2]; -//we have three sorts of movement. -//1: stepping monsters. These have frames and tick at 10fps. -//2: physics. Objects moving acording to gravity. -//3: both. This is really awkward. And I'm really lazy. - cl.lerpents[state->number].lerprate = cl.gametime-cl.lerpents[state->number].lerptime; //time per update - cl.lerpents[state->number].frame = from->frame; - cl.lerpents[state->number].lerptime = cl.gametime; - - if (cl.lerpents[state->number].lerprate>0.2) - cl.lerpents[state->number].lerprate=0.2; - - //store this off for new ents to use. -// if (new) -// cl.lerpents[state->number].lerprate = newlerprate; -// else - if (state->frame == from->frame) - newlerprate = cl.lerpents[state->number].lerprate; - } } #endif #ifdef PEXT_SETVIEW @@ -1510,6 +1351,468 @@ CL_LinkPacketEntities =============== */ void R_FlameTrail(vec3_t start, vec3_t end, float seperation); +#define DECENTLERP +#ifdef DECENTLERP + +void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entities_t *oldpack, float servertime) +{ + lerpents_t *le; + entity_state_t *snew, *sold; + int i, j; + int oldpnum, newpnum; + + vec3_t move; + + float a1, a2; + + float frac; + /* + seeing as how dropped packets cannot be filled in due to the reliable networking stuff, + We can simply detect changes and lerp towards them + */ + + //we have two index-sorted lists of entities + //we figure out which ones are new, + //we don't care about old, as our caller will use the lerpents array we fill, and the entity numbers from the 'new' packet. + + if (newpack->servertime == oldpack->servertime) + frac = 1; //lerp totally into the new + else + frac = (servertime-oldpack->servertime)/(newpack->servertime-oldpack->servertime); + + oldpnum=0; + for (newpnum=0 ; newpnumnum_entities ; newpnum++) + { + snew = &newpack->entities[newpnum]; + + sold = NULL; + for ( ; oldpnumnum_entities ; oldpnum++) + { + sold = &oldpack->entities[oldpnum]; + if (sold->number >= snew->number) + { + if (sold->number > snew->number) + sold = NULL; //woo, it's a new entity. + break; + } + } + if (!sold) //I'm lazy + sold = snew; + + if (snew->number >= cl.maxlerpents) + { + cl.maxlerpents = snew->number+16; + cl.lerpents = BZ_Realloc(cl.lerpents, cl.maxlerpents*sizeof(lerpents_t)); + } + le = &cl.lerpents[snew->number]; + + VectorSubtract(snew->origin, sold->origin, move) + if (DotProduct(move, move) > 200*200 || snew->modelindex != sold->modelindex) + { + sold = snew; //teleported? + VectorClear(move); + } + + for (i = 0; i < 3; i++) + { + le->origin[i] = sold->origin[i] + frac*(move[i]); + + for (j = 0; j < 3; j++) + { + a1 = sold->angles[i]; + a2 = snew->angles[i]; + if (a1 - a2 > 180) + a1 -= 360; + if (a1 - a2 < -180) + a1 += 360; + le->angles[i] = a1 + frac * (a2 - a1); + } + } + + if (snew == sold || (sold->frame != le->frame && sold->frame != snew->frame) || snew->modelindex != sold->modelindex) + { + le->oldframechange = le->framechange; + le->framechange = newpack->servertime; + + le->frame = sold->frame; + } + } +} + +packet_entities_t *CL_ProcessPacketEntities(float *servertime, qboolean nolerp) +{ + packet_entities_t *packnew, *packold; + entity_state_t *snew, *sold; + int i; + static float oldoldtime; + //, spnum; + + *servertime -= 0.1; + + if (nolerp) + { //force our emulated time to as late as we can. + //this will disable all position interpolation + *servertime = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime; + Con_DPrintf("No lerp\n"); + } + + packnew = NULL; + packold = NULL; + //choose the two packets. + //we should be picking the packet just after the server time, and the one just before + for (i = cls.netchan.incoming_sequence; i >= cls.netchan.incoming_sequence-UPDATE_MASK; i--) + { + if (cl.frames[i&UPDATE_MASK].receivedtime < 0 || cl.frames[i&UPDATE_MASK].invalid) + continue; //packetloss/choke, it's really only a problem for the oldframe, but... + + if (cl.frames[i&UPDATE_MASK].packet_entities.servertime >= *servertime) + { + if (cl.frames[i&UPDATE_MASK].packet_entities.servertime) + { + if (!packnew || packnew->servertime != cl.frames[i&UPDATE_MASK].packet_entities.servertime) //if it's a duplicate, pick the latest (so just-shot rockets are still present) + packnew = &cl.frames[i&UPDATE_MASK].packet_entities; + } + } + else if (packnew) + { + if (cl.frames[i&UPDATE_MASK].packet_entities.servertime != packnew->servertime) + { //it does actually lerp, and isn't an identical frame. + packold = &cl.frames[i&UPDATE_MASK].packet_entities; + break; + } + } + } + + //Note, hacking this to return anyway still needs the lerpent array to be valid for all contained entities. + + if (!packnew) //should never happen + { + Con_DPrintf("Warning: No lerp-to frame packet\n"); + return NULL; + } + if (!packold) //can happem at map start, and really laggy games, but really shouldn't in a normal game + { + Con_DPrintf("Warning: No lerp-from frame packet\n"); + packold = packnew; + } + + CL_TransitionPacketEntities(packnew, packold, *servertime); + + Con_DPrintf("%f %f %f %f %f %f\n", packnew->servertime, *servertime, packold->servertime, cl.gametime, cl.oldgametime, cl.servertime); + +// if (packold->servertime < oldoldtime) +// Con_Printf("Spike screwed up\n"); +// oldoldtime = packold->servertime; + + return packnew; +} + +void CL_LinkPacketEntities (void) +{ + entity_t *ent; + packet_entities_t *pack; + entity_state_t *state; + lerpents_t *le; + float f; + model_t *model; + vec3_t old_origin; + float autorotate; + int i; + int oldpnum, newpnum; + //, spnum; + dlight_t *dl; + vec3_t angles; + int flicker; + + float servertime; + + CL_CalcClientTime(); + servertime = cl.servertime; + + pack = CL_ProcessPacketEntities(&servertime, !!cl_nolerp.value); + if (!pack) + return; + + servertime = cl.servertime; + + + autorotate = anglemod(100*servertime); + + for (newpnum=0 ; newpnumnum_entities ; newpnum++) + { + state = &pack->entities[newpnum]; + + + + if (cl_numvisedicts == MAX_VISEDICTS) + { + Con_Printf("Too many visible entities\n"); + break; + } + ent = &cl_visedicts[cl_numvisedicts]; +#ifdef Q3SHADERS + ent->forcedshader = NULL; +#endif + + le = &cl.lerpents[state->number]; + + if (le->framechange == le->oldframechange) + ent->lerpfrac = 0; + else + { + ent->lerpfrac = 1-(servertime - le->oldframechange) / (le->framechange - le->oldframechange); + } + + + VectorCopy(le->origin, ent->origin) + + //bots or powerup glows. Bots always glow, powerups can be disabled + if (state->modelindex != cl_playerindex && r_powerupglow.value); + { + flicker = r_lightflicker.value?(rand()&31):0; + // spawn light flashes, even ones coming from invisible objects + if ((state->effects & (EF_BLUE | EF_RED)) == (EF_BLUE | EF_RED)) + CL_NewDlight (state->number, state->origin[0], state->origin[1], state->origin[2], 200 + flicker, 0, 3); + else if (state->effects & EF_BLUE) + CL_NewDlight (state->number, state->origin[0], state->origin[1], state->origin[2], 200 + flicker, 0, 1); + else if (state->effects & EF_RED) + CL_NewDlight (state->number, state->origin[0], state->origin[1], state->origin[2], 200 + flicker, 0, 2); + else if (state->effects & EF_BRIGHTLIGHT) + CL_NewDlight (state->number, state->origin[0], state->origin[1], state->origin[2] + 16, 400 + flicker, 0, 0); + else if (state->effects & EF_DIMLIGHT) + CL_NewDlight (state->number, state->origin[0], state->origin[1], state->origin[2], 200 + flicker, 0, 0); + } + if (state->light[3]) + { + CL_NewDlightRGB (state->number, state->origin[0], state->origin[1], state->origin[2], state->light[3], 0, state->light[0]/1024.0f, state->light[1]/1024.0f, state->light[2]/1024.0f); + } + + // if set to invisible, skip + if (state->modelindex<1) + continue; + + // create a new entity + if (cl_numvisedicts == MAX_VISEDICTS) + break; // object list is full + + if (CL_FilterModelindex(state->modelindex, state->frame)) + continue; + + model = cl.model_precache[state->modelindex]; + if (!model) + { + Con_DPrintf("Bad modelindex (%i)\n", state->modelindex); + continue; + } + + cl_numvisedicts++; + +#ifdef Q3SHADERS + ent->forcedshader = NULL; +#endif + + ent->visframe = 0; + + ent->keynum = state->number; + + if (cl_r2g.value && state->modelindex == cl_rocketindex && cl_rocketindex && cl_grenadeindex) + ent->model = cl.model_precache[cl_grenadeindex]; + else + ent->model = model; + + ent->flags = state->flags; + if (state->effects & NQEF_ADDATIVE) + ent->flags |= Q2RF_ADDATIVE; + if (state->effects & EF_NODEPTHTEST) + ent->flags |= RF_NODEPTHTEST; + + // set colormap + if (state->colormap && (state->colormap <= MAX_CLIENTS) + && (gl_nocolors.value == -1 || (ent->model/* && state->modelindex == cl_playerindex*/))) + { + ent->colormap = cl.players[state->colormap-1].translations; + ent->scoreboard = &cl.players[state->colormap-1]; + } + else + { + ent->colormap = vid.colormap; + ent->scoreboard = NULL; + } + + // set skin + ent->skinnum = state->skinnum; + + ent->abslight = state->abslight; + ent->drawflags = state->hexen2flags; + + // set frame + ent->frame = state->frame; + ent->oldframe = le->frame; + + ent->frame1time = cl.servertime - le->framechange; + ent->frame2time = cl.servertime - le->oldframechange; + +// f = (sin(realtime)+1)/2; + +#ifdef PEXT_SCALE + //set scale + ent->scale = state->scale/16.0; +#endif +#ifdef PEXT_TRANS + //set trans + ent->alpha = state->trans/255.0; +#endif +#ifdef PEXT_FATNESS + //set trans + ent->fatness = state->fatness/2.0; +#endif + + // rotate binary objects locally + if (model && model->flags & EF_ROTATE) + { + angles[0] = 0; + angles[1] = autorotate; + angles[2] = 0; + + if (cl_item_bobbing.value) + ent->origin[2] += 5+sin(cl.time*3)*5; //don't let it into the ground + } + else + { + float a1, a2; + + for (i=0 ; i<3 ; i++) + { + angles[i] = le->angles[i]; + } + } + + VectorCopy(angles, ent->angles); + angles[0]*=-1; + AngleVectors(angles, ent->axis[0], ent->axis[1], ent->axis[2]); + VectorInverse(ent->axis[1]); + + if (ent->keynum <= MAX_CLIENTS +#ifdef NQPROT + && cls.protocol == CP_QUAKEWORLD +#endif + ) + ent->keynum += MAX_EDICTS; + + if (state->tagentity) + { //ent is attached to a tag, rotate this ent accordingly. + CL_RotateAroundTag(ent, state->number, state->tagentity, state->tagindex); + } + + // add automatic particle trails + if (!model || (!(model->flags&~EF_ROTATE) && model->particletrail<0 && model->particleeffect<0)) + continue; + + if (!cls.allow_anyparticles && !(model->flags & ~EF_ROTATE)) + continue; + + // scan the old entity display list for a matching + for (i=0 ; ikeynum) + { + VectorCopy (cl_oldvisedicts[i].origin, old_origin); + break; + } + } + if (i == cl_oldnumvisedicts) + { + P_DelinkTrailstate(&(cl.lerpents[state->number].trailstate)); + P_DelinkTrailstate(&(cl.lerpents[state->number].emitstate)); + continue; // not in last message + } + + for (i=0 ; i<3 ; i++) + if ( abs(old_origin[i] - ent->origin[i]) > 128) + { // no trail if too far + VectorCopy (ent->origin, old_origin); + break; + } + + if (model->particletrail>=0) + { +// Con_Printf("(%f %f %f) (%f %f %f)\n", ent->origin[0], ent->origin[1], ent->origin[2], old_origin[0], old_origin[1], old_origin[2]); +/* + if (ent->origin[0] == old_origin[0] || ent->origin[1] == old_origin[1] || ent->origin[2] == old_origin[2]) + { + if (ent->origin[0] == old_origin[0] && ent->origin[1] == old_origin[1] && ent->origin[2] == old_origin[2]) + { + Con_Printf("Total match!!\n"); + } + else + Con_Printf("impartial match!!\n"); + }*/ + + + P_ParticleTrail (old_origin, ent->origin, model->particletrail, &(le->trailstate)); + } + + { + extern cvar_t gl_part_flame; + if (cls.allow_anyparticles && gl_part_flame.value) + { + P_EmitEffect (ent->origin, model->particleeffect, &(le->emitstate)); + } + } + + + //dlights are not so customisable. + if (r_rocketlight.value) + { + float rad = 0; + vec3_t dclr; + + dclr[0] = 0.20; + dclr[1] = 0.10; + dclr[2] = 0; + + if (model->flags & EF_ROCKET) + { + if (strncmp(model->name, "models/sflesh", 13)) + { //hmm. hexen spider gibs... + rad = 200; + dclr[2] = 0.05; + } + } + else if (model->flags & EF_FIREBALL) + { + rad = 120 - (rand() % 20); + } + else if (model->flags & EF_ACIDBALL) + { + rad = 120 - (rand() % 20); + } + else if (model->flags & EF_SPIT) + { + // as far as I can tell this effect inverses the light... + dclr[0] = -dclr[0]; + dclr[0] = -dclr[1]; + dclr[0] = -dclr[2]; + rad = 120 - (rand() % 20); + } + + if (rad) + { + dl = CL_AllocDlight (state->number); + VectorCopy (ent->origin, dl->origin); + dl->die = (float)cl.time; + if (model->flags & EF_ROCKET) + dl->origin[2] += 1; // is this even necessary + dl->radius = rad * bound(0, r_rocketlight.value, 1); + VectorCopy(dclr, dl->color); + } + + + } + } +} +#else + void CL_LinkPacketEntities (void) { entity_t *ent; @@ -1824,7 +2127,7 @@ void CL_LinkPacketEntities (void) } } } - +#endif /* ========================================================================= diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 0586d1f99..360945e74 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -3399,11 +3399,11 @@ void CL_PrintStandardMessage(char *msg) v = strstr(v+len, name); continue; } - + { int i; char aftername = *(v + len); - + // search for accepted chars in char after name in msg for (i = 0; i < sizeof(acceptedchars); i++) { @@ -3732,7 +3732,7 @@ void CL_ParseServerMessage (void) i = MSG_ReadByte (); if (i >= MAX_CLIENTS) Host_EndGame ("CL_ParseServerMessage: svc_updateentertime > MAX_SCOREBOARD"); - cl.players[i].entertime = realtime - MSG_ReadFloat (); + cl.players[i].entertime = cl.servertime - MSG_ReadFloat (); break; case svc_spawnbaseline: @@ -3804,7 +3804,7 @@ void CL_ParseServerMessage (void) if (!cl.intermission) TP_ExecTrigger ("f_mapend"); cl.intermission = 1; - cl.completed_time = realtime; + cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen for (i=0 ; i<3 ; i++) cl.simorg[0][i] = MSG_ReadCoord (); @@ -3819,7 +3819,7 @@ void CL_ParseServerMessage (void) case svc_finale: cl.intermission = 2; - cl.completed_time = realtime; + cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (destsplit, MSG_ReadString ()); break; @@ -4150,7 +4150,7 @@ void CLNQ_ParseProQuakeMessage (char *s) s++; cmd = *s++; - + switch (cmd) { default: @@ -4188,7 +4188,7 @@ void CLNQ_ParseProQuakeMessage (char *s) frags = frags - 65536; cl.teamscores[team].frags = frags; //Con_Printf("pqc_team_frags %d %d\n", team, frags); - break; + break; case pqc_match_time: Sbar_Changed (); @@ -4398,13 +4398,13 @@ void CLNQ_ParseServerMessage (void) cl.oldgametime = cl.gametime; cl.oldgametimemark = cl.gametimemark; cl.gametime = MSG_ReadFloat(); - cl.gametimemark = realtime; if (nq_dp_protocol<5) { // cl.frames[(cls.netchan.incoming_sequence-1)&UPDATE_MASK].packet_entities = cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities; cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.num_entities=0; + cl.frames[cls.netchan.incoming_sequence&UPDATE_MASK].packet_entities.servertime = cl.gametime; } break; @@ -4502,20 +4502,20 @@ void CLNQ_ParseServerMessage (void) if (!cl.intermission) TP_ExecTrigger ("f_mapend"); cl.intermission = 1; - cl.completed_time = cl.time; + cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen break; case svc_finale: cl.intermission = 2; - cl.completed_time = cl.time; + cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (0, MSG_ReadString ()); break; case svc_cutscene: cl.intermission = 3; - cl.completed_time = cl.time; + cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen SCR_CenterPrint (0, MSG_ReadString ()); break; diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 33a87e664..30d85bb24 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -81,7 +81,7 @@ void CLQ2_CheckPredictionError (void) else { // if (/*cl_showmiss->value && */(delta[0] || delta[1] || delta[2]) ) -// Con_Printf ("prediction miss on %i: %i\n", cl.q2frame.serverframe, +// Con_Printf ("prediction miss on %i: %i\n", cl.q2frame.serverframe, // delta[0] + delta[1] + delta[2]); VectorCopy (cl.q2frame.playerstate.pmove.origin, cl_predicted_origins[frame]); @@ -271,7 +271,7 @@ void CLQ2_PredictMovement (void) //q2 doesn't support split clients. { // if (cl_showmiss->value) // Con_Printf ("exceeded CMD_BACKUP\n"); - return; + return; } // copy current state to pmove @@ -637,14 +637,14 @@ short LerpAngles16(short to, short from, float frac) void CL_CalcClientTime(void) { - + { float want; - want = cl.oldgametime + realtime - cl.gametimemark; + want = cl.oldgametime + (realtime - cl.gametimemark); if (want>cl.servertime) cl.servertime = want; - + if (cl.servertime > cl.gametime) cl.servertime = cl.gametime; if (cl.servertime < cl.oldgametime) @@ -662,7 +662,7 @@ void CL_CalcClientTime(void) cl.time = want; // Con_Printf("Drifted to %f off by %f\n", cl.time, off); - + // Con_Printf("\n"); if (cl.time > cl.gametime) { @@ -674,7 +674,7 @@ void CL_CalcClientTime(void) cl.time = cl.oldgametime; // Con_Printf("old TimeClamp\n"); } - + } else { @@ -713,7 +713,7 @@ void CL_PredictMovePNum (int pnum) if (cl_pushlatency.value > 0) Cvar_Set (&cl_pushlatency, "0"); - if (cl.paused && !cls.demoplayback!=DPB_MVD && (!cl.spectator || !autocam[pnum])) + if (cl.paused && !cls.demoplayback!=DPB_MVD && (!cl.spectator || !autocam[pnum])) return; CL_CalcClientTime(); @@ -750,11 +750,19 @@ void CL_PredictMovePNum (int pnum) #ifdef PEXT_SETVIEW if (cl.viewentity[pnum]) { - entity_state_t *CL_FindOldPacketEntity(int num); + if (cl.viewentity[pnum] < cl.maxlerpents) + { +// Con_Printf("Using lerped pos\n"); + org = cl.lerpents[cl.viewentity[pnum]].origin; + vel = vec3_origin; + goto fixedorg; + } + Con_Printf("Not lerped\n"); +/* entity_state_t *CL_FindOldPacketEntity(int num); entity_state_t *CL_FindPacketEntity(int num); entity_state_t *state; state = CL_FindPacketEntity (cl.viewentity[pnum]); - if (state) + if (state && state->number < cl.maxlerpents) { float f; extern cvar_t cl_nolerp; @@ -784,7 +792,7 @@ void CL_PredictMovePNum (int pnum) goto fixedorg; } - } +*/ } #endif if (((cl_nopred.value && cls.demoplayback!=DPB_MVD)|| cl.fixangle)) { @@ -852,7 +860,7 @@ fixedorg: break; from = to; } - + if (independantphysics[pnum].msec) { from = to; @@ -895,12 +903,12 @@ fixedorg: VectorCopy (to->playerstate[cl.playernum[pnum]].origin, cl.simorg[pnum]); goto out; } - + for (i=0 ; i<3 ; i++) { - cl.simorg[pnum][i] = org[i] + cl.simorg[pnum][i] = org[i] + f*(to->playerstate[cl.playernum[pnum]].origin[i] - org[i]); - cl.simvel[pnum][i] = vel[i] + cl.simvel[pnum][i] = vel[i] + f*(to->playerstate[cl.playernum[pnum]].velocity[i] - vel[i]); } CL_CatagorizePosition(pnum); diff --git a/engine/client/client.h b/engine/client/client.h index 94a92a998..239956938 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -77,7 +77,7 @@ typedef struct #if defined(Q2CLIENT) || defined(Q2SERVER) -typedef enum +typedef enum { // can accelerate and turn Q2PM_NORMAL, @@ -119,7 +119,7 @@ typedef struct int gunframe; float blend[4]; // rgba full screen effect - + float fov; // horizontal field of view int rdflags; // refdef flags @@ -424,7 +424,7 @@ typedef struct // render a frame yet int movemessages; // since connecting to this server // throw out the first couple, so the player - // doesn't accidentally do something the + // doesn't accidentally do something the // first frame int spectator; @@ -491,10 +491,10 @@ typedef struct qboolean paused; // send over by server float punchangle[MAX_SPLITS]; // temporar yview kick from weapon firing - + int intermission; // don't change view angle, full screen, etc int completed_time; // latched ffrom time at intermission start - + // // information that is static for the entire time connected to a server // @@ -794,6 +794,7 @@ void CLQ3_SendConnectPacket(netadr_t to); void CLQ3_SendCmd(usercmd_t *cmd); qboolean CLQ3_Netchan_Process(void); void CLQ3_ParseServerMessage (void); +struct snapshot_s; qboolean CG_FillQ3Snapshot(int snapnum, struct snapshot_s *snapshot); void CG_InsertIntoGameState(int num, char *str); diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 55804d2ee..6f3c21575 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -292,7 +292,7 @@ void DrawHUDString (char *string, int x, int y, int centerwidth, int xor) } } #define STAT_MINUS 10 // num frame for '-' stats digit -char *q2sb_nums[2][11] = +char *q2sb_nums[2][11] = { {"num_0", "num_1", "num_2", "num_3", "num_4", "num_5", "num_6", "num_7", "num_8", "num_9", "num_minus"}, @@ -845,7 +845,7 @@ void Sbar_Start (void) //if one of these fails, skip the entire status bar. sb_face_invuln = Sbar_PicFromWad ("face_invul2"); sb_face_invis_invuln = Sbar_PicFromWad ("face_inv2"); sb_face_quad = Sbar_PicFromWad ("face_quad"); - + sb_sbar = Sbar_PicFromWad ("sbar"); sb_ibar = Sbar_PicFromWad ("ibar"); sb_scorebar = Sbar_PicFromWad ("scorebar"); @@ -887,7 +887,7 @@ void Sbar_Init (void) { Cmd_AddCommand ("+showscores", Sbar_ShowScores); Cmd_AddCommand ("-showscores", Sbar_DontShowScores); - + Cmd_AddCommand ("+showteamscores", Sbar_ShowTeamScores); Cmd_AddCommand ("-showteamscores", Sbar_DontShowTeamScores); } @@ -913,7 +913,7 @@ Sbar_DrawSubPic JACK: Draws a portion of the picture in the status bar. */ -void Sbar_DrawSubPic(int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height) +void Sbar_DrawSubPic(int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height) { Draw_SubPic (sbar_rect.x + x, sbar_rect.y + y+(sbar_rect.height-SBAR_HEIGHT), pic, srcx, srcy, width, height); } @@ -966,18 +966,18 @@ int Sbar_itoa (int num, char *buf) char *str; int pow10; int dig; - + str = buf; - + if (num < 0) { *str++ = '-'; num = -num; } - + for (pow10 = 10 ; num >= pow10 ; pow10 *= 10) ; - + do { pow10 /= 10; @@ -985,9 +985,9 @@ int Sbar_itoa (int num, char *buf) *str++ = '0'+dig; num -= dig*pow10; } while (pow10 != 1); - + *str = 0; - + return str-buf; } @@ -1068,7 +1068,7 @@ Sbar_SortFrags void Sbar_SortFrags (qboolean includespec) { int i, j, k; - + // sort by frags scoreboardlines = 0; for (i=0 ; i200) Sbar_DrawSubPic ((hudswap) ? 0 : (sbar_rect.width-24),-68-(7-i)*16 , sb_weapons[flashon][i],0,0,24,16); - - } else + + } else Sbar_DrawPic (i*24, -16, sb_weapons[flashon][i]); // Sbar_DrawSubPic (0,0,20,20,i*24, -16, sb_weapons[flashon][i]); @@ -1292,8 +1290,8 @@ void Sbar_DrawInventory (int pnum) if (headsup) { if (sbar_rect.height>200) Sbar_DrawSubPic ((hudswap) ? 0 : (sbar_rect.width-24),-68-(5-i)*16 , rsb_weapons[i],0,0,24,16); - - } else + + } else Sbar_DrawPic ((i+2)*24, -16, rsb_weapons[i]); } } @@ -1325,7 +1323,7 @@ void Sbar_DrawInventory (int pnum) Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0'); } } - + flashon = 0; // items for (i=0 ; i<6 ; i++) @@ -1337,7 +1335,7 @@ void Sbar_DrawInventory (int pnum) sb_updates = 0; } else - Sbar_DrawPic (192 + i*16, -16, sb_items[i]); + Sbar_DrawPic (192 + i*16, -16, sb_items[i]); if (time && time > cl.time - 2) sb_updates = 0; } @@ -1377,7 +1375,7 @@ void Sbar_DrawInventory (int pnum) sb_updates = 0; } else - Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]); + Sbar_DrawPic (320-32 + i*8, -16, sb_sigil[i]); if (time && time > cl.time - 2) sb_updates = 0; } @@ -1392,18 +1390,18 @@ Sbar_DrawFrags =============== */ void Sbar_DrawFrags (void) -{ +{ int i, k, l; int top, bottom; int x, y, f; char num[12]; player_info_t *s; - + Sbar_SortFrags (false); // draw the text l = scoreboardlines <= 4 ? scoreboardlines : 4; - + x = 23; // xofs = (sbar_rect.width - 320)>>1; y = sbar_rect.height - SBAR_HEIGHT - 23; @@ -1425,7 +1423,7 @@ void Sbar_DrawFrags (void) top = Sbar_ColorForMap (top); bottom = Sbar_ColorForMap (bottom); - + // Draw_Fill (xofs + x*8 + 10, y, 28, 4, top); // Draw_Fill (xofs + x*8 + 10, y+4, 28, 3, bottom); Draw_Fill (sbar_rect.x+x*8 + 10, sbar_rect.y+y, 28, 4, top); @@ -1434,7 +1432,7 @@ void Sbar_DrawFrags (void) // draw number f = s->frags; sprintf (num, "%3i",f); - + Sbar_DrawCharacter ( (x+1)*8 , -24, num[0]); Sbar_DrawCharacter ( (x+2)*8 , -24, num[1]); Sbar_DrawCharacter ( (x+3)*8 , -24, num[2]); @@ -1466,17 +1464,17 @@ void Sbar_DrawFace (int pnum) Sbar_DrawPic (112, 0, sb_face_invis_invuln); return; } - if (cl.stats[pnum][STAT_ITEMS] & IT_QUAD) + if (cl.stats[pnum][STAT_ITEMS] & IT_QUAD) { Sbar_DrawPic (112, 0, sb_face_quad ); return; } - if (cl.stats[pnum][STAT_ITEMS] & IT_INVISIBILITY) + if (cl.stats[pnum][STAT_ITEMS] & IT_INVISIBILITY) { Sbar_DrawPic (112, 0, sb_face_invis ); return; } - if (cl.stats[pnum][STAT_ITEMS] & IT_INVULNERABILITY) + if (cl.stats[pnum][STAT_ITEMS] & IT_INVULNERABILITY) { Sbar_DrawPic (112, 0, sb_face_invuln); return; @@ -1489,7 +1487,7 @@ void Sbar_DrawFace (int pnum) if (f < 0) f=0; - + if (cl.time <= cl.faceanimtime[pnum]) { anim = 1; @@ -1541,10 +1539,10 @@ void Sbar_DrawNormal (int pnum) Sbar_DrawPic (0, 0, sb_armor[0]); } } - + // face Sbar_DrawFace (pnum); - + // health Sbar_DrawNum (136, 0, cl.stats[pnum][STAT_HEALTH], 3 , cl.stats[pnum][STAT_HEALTH] <= 25); @@ -1578,7 +1576,7 @@ void Sbar_DrawNormal (int pnum) else if (cl.stats[pnum][STAT_ITEMS] & IT_CELLS) Sbar_DrawPic (224, 0, sb_ammo[3]); } - + Sbar_DrawNum (248, 0, cl.stats[pnum][STAT_AMMO], 3 , cl.stats[pnum][STAT_AMMO] <= 10); } @@ -1664,7 +1662,7 @@ void Sbar_Draw (void) // scr_fullupdate = 0; sb_updates++; - + // top line if (sb_lines > 24) { @@ -1672,7 +1670,7 @@ void Sbar_Draw (void) Sbar_DrawInventory (pnum); if (!headsup || sbar_rect.width<512) Sbar_DrawFrags (); - } + } // main area if (sb_lines > 0) @@ -1736,7 +1734,7 @@ void Sbar_Draw (void) #ifdef RGLQUAKE if (cl.splitclients) { - if (sb_showscores || sb_showteamscores || + if (sb_showscores || sb_showteamscores || deadcount == cl.splitclients) sb_updates = 0; // clear unused areas in gl @@ -1876,16 +1874,16 @@ void Sbar_TeamOverlay (void) // draw total sprintf (num, "%5i", tm->frags); Draw_String (x + 104 + 40, y, num); - + // draw players sprintf (num, "%5i", tm->players); Draw_String (x + 104 + 88, y, num); - + if (!strncmp(cl.players[cl.playernum[0]].team, tm->team, 16)) { Draw_Character ( x + 104 - 8, y, 16); Draw_Character ( x + 104 + 32, y, 17); } - + y += 8; } y += 8; @@ -1932,7 +1930,7 @@ void Sbar_DeathmatchOverlay (int start) Draw_Pic ((vid.width - 320)/2 + 160-pic->width/2, 0, pic); } -// scores +// scores Sbar_SortFrags (true); // draw the text @@ -1948,7 +1946,7 @@ void Sbar_DeathmatchOverlay (int start) x = vid.width/2 + (vid.width/2 - 320)/2 + 4; else x = (vid.width - 320)/2 + 4; -// 0 40 64 104 152 192 +// 0 40 64 104 152 192 Draw_String ( x , y, "ping pl time frags team name"); y += 8; // Draw_String ( x , y, "---- -- ---- ----- ---- ----------------"); @@ -2008,7 +2006,7 @@ void Sbar_DeathmatchOverlay (int start) if (cl.intermission) total = cl.completed_time - s->entertime; else - total = realtime - s->entertime; + total = cl.servertime - s->entertime; minutes = (int)total/60; sprintf (num, "%4i", minutes); Draw_String ( x+64 , y, num); @@ -2018,7 +2016,7 @@ void Sbar_DeathmatchOverlay (int start) bottom = s->bottomcolor; top = Sbar_ColorForMap (top); bottom = Sbar_ColorForMap (bottom); - + if (largegame) Draw_Fill ( x+104, y+1, 40, 3, top); else @@ -2028,7 +2026,7 @@ void Sbar_DeathmatchOverlay (int start) // draw number f = s->frags; sprintf (num, "%3i",f); - + Draw_Character ( x+112 , y, num[0]); Draw_Character ( x+120 , y, num[1]); Draw_Character ( x+128 , y, num[2]); @@ -2039,7 +2037,7 @@ void Sbar_DeathmatchOverlay (int start) Draw_Character ( x + 104, y, 16); Draw_Character ( x + 136, y, 17); } - + // team if (cl.teamplay) Draw_FunStringLen (x+152, y, s->team, 4); @@ -2049,10 +2047,10 @@ void Sbar_DeathmatchOverlay (int start) Draw_FunString (x+152+40, y, s->name); else Draw_FunString (x+152, y, s->name); - + y += skip; } - + Draw_Character(0,0,COLOR_WHITE<<8); if (y >= vid.height-10) // we ran over the screen size, squish @@ -2082,7 +2080,7 @@ void Sbar_ChatModeOverlay(void) scr_copyeverything = 1; scr_fullupdate = 0; -// scores +// scores Sbar_SortFrags (true); if (Cam_TrackNum(0)>=0) @@ -2119,7 +2117,7 @@ void Sbar_ChatModeOverlay(void) bottom = s->bottomcolor; top = Sbar_ColorForMap (top); bottom = Sbar_ColorForMap (bottom); - + if (largegame) Draw_Fill ( x, y+1, 8*4, 3, top); else @@ -2150,10 +2148,10 @@ void Sbar_ChatModeOverlay(void) Draw_FunString (x+8*4, y, s->name); else Draw_FunString (x+8*4, y, s->name); - + y += skip; } - + Draw_Character(0,0,COLOR_WHITE<<8); if (y >= vid.height-10) // we ran over the screen size, squish @@ -2186,7 +2184,7 @@ void Sbar_MiniDeathmatchOverlay (void) scr_copyeverything = 1; scr_fullupdate = 0; -// scores +// scores Sbar_SortFrags (false); if (sbar_rect.width >= 640) Sbar_SortTeams(); @@ -2229,14 +2227,14 @@ void Sbar_MiniDeathmatchOverlay (void) bottom = s->bottomcolor; top = Sbar_ColorForMap (top); bottom = Sbar_ColorForMap (bottom); - + Draw_Fill ( x, y+1, 40, 3, top); Draw_Fill ( x, y+4, 40, 4, bottom); // draw number f = s->frags; sprintf (num, "%3i",f); - + Draw_ColouredCharacter ( x+8 , y, (COLOR_WHITE<<8)|num[0]); Draw_Character ( x+16, y, num[1]); Draw_Character ( x+24, y, num[2]); @@ -2247,7 +2245,7 @@ void Sbar_MiniDeathmatchOverlay (void) Draw_Character ( x, y, 16); Draw_Character ( x + 32, y, 17); } - + Q_strncpyz(name, s->name, sizeof(name)); // team and name if (cl.teamplay) @@ -2283,12 +2281,12 @@ void Sbar_MiniDeathmatchOverlay (void) // draw total sprintf (num, "%5i", tm->frags); Draw_FunString(x + 40, y, num); - + if (!strncmp(cl.players[cl.playernum[0]].team, tm->team, 16)) { Draw_Character ( x - 8, y, 16); Draw_Character ( x + 32, y, 17); } - + y += 8; } diff --git a/engine/client/snd_alsa.c b/engine/client/snd_alsa.c index 5a00a6125..93480949c 100755 --- a/engine/client/snd_alsa.c +++ b/engine/client/snd_alsa.c @@ -133,7 +133,9 @@ static qboolean Alsa_InitAlsa(void) alsasharedobject = dlopen("libasound.so", RTLD_LAZY|RTLD_LOCAL); if (!alsasharedobject) + { return false; + } psnd_pcm_open = dlsym(alsasharedobject, "snd_pcm_open"); @@ -202,7 +204,10 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum) snd_pcm_uframes_t frag_size; if (!Alsa_InitAlsa()) + { + Con_Printf("Alsa does not appear to be installed or compatable\n"); return 2; + } hw = alloca(psnd_pcm_hw_params_sizeof()); sw = alloca(psnd_pcm_sw_params_sizeof()); @@ -221,6 +226,8 @@ static int ALSA_InitCard (soundcardinfo_t *sc, int cardnum) sc->inactive_sound = true; //linux sound devices always play sound, even when we're not the active app... + Con_Printf("Initing ALSA sound device %s\n", pcmname); + // COMMANDLINEOPTION: Linux ALSA Sound: -sndbits sets sound precision to 8 or 16 bit (email me if you want others added) if ((i=COM_CheckParm("-sndbits")) != 0) { diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 95105184d..d8a8d9e66 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -156,19 +156,26 @@ sounddriver pALSA_InitCard; sounddriver pOSS_InitCard; sounddriver pSDL_InitCard; sounddriver pWAV_InitCard; +sounddriver pAHI_InitCard; -sounddriver *drivers[] = { - &pDSOUND_InitCard, - &pALSA_InitCard, - &pOSS_InitCard, - &pSDL_InitCard, - &pWAV_InitCard, - NULL +typedef struct { + char *name; + sounddriver *ptr; +} sdriver_t; +sdriver_t drivers[] = { +//in order of preference + {"DSound", &pDSOUND_InitCard}, + {"ALSA", &pALSA_InitCard}, + {"OSS", &pOSS_InitCard}, + {"SDL", &pSDL_InitCard}, + {"WaveOut", &pWAV_InitCard}, + {"AHI", &pAHI_InitCard}, + {NULL, NULL} }; static int SNDDMA_Init(soundcardinfo_t *sc, int *cardnum, int *drivernum) { - sounddriver *sd; + sdriver_t *sd; int st = 0; memset(sc, 0, sizeof(*sc)); @@ -181,13 +188,20 @@ static int SNDDMA_Init(soundcardinfo_t *sc, int *cardnum, int *drivernum) else sc->sn.speed = 11025; - sd = drivers[*drivernum]; - if (!sd) + sd = &drivers[*drivernum]; + if (!sd->ptr) return 2; //no more cards. - if (!*sd) //driver not loaded + if (!*sd->ptr) //driver not loaded + { + Con_DPrintf("Sound driver %s is not loaded\n", sd->name); st = 2; + } else - st = (**sd)(sc, *cardnum); + { + Con_DPrintf("Trying to load a %s sound device\n", sd->name); + st = (**sd->ptr)(sc, *cardnum); + } + if (st == 1) //worked { *cardnum += 1; //use the next card next time diff --git a/engine/client/snd_linux.c b/engine/client/snd_linux.c index 365ea7302..bb106936a 100644 --- a/engine/client/snd_linux.c +++ b/engine/client/snd_linux.c @@ -81,7 +81,7 @@ static int OSS_InitCard(soundcardinfo_t *sc, int cardnum) // open the sound device, confirm capability to mmap, and get size of dma buffer - printf("Initing sound device %s\n", snddev); + Con_Printf("Initing OSS sound device %s\n", snddev); sc->audio_fd = open(snddev, O_RDWR | O_NONBLOCK); //try the primary device if (sc->audio_fd < 0) diff --git a/engine/client/sound.h b/engine/client/sound.h index 4dcfae0ff..7b0db6504 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -203,6 +203,7 @@ extern sounddriver pALSA_InitCard; extern sounddriver pOSS_InitCard; extern sounddriver pSDL_InitCard; extern sounddriver pWAV_InitCard; +extern sounddriver pAHI_InitCard; struct soundcardinfo_s { //windows has one defined AFTER directsound char name[256]; //a description of the card. diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index ade5298e4..10cf7098c 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -308,11 +308,27 @@ int Sys_EnumerateFiles (char *gpath, char *match, int (*func)(char *, int, void return true; } + +int secbase; +unsigned int Sys_Milliseconds (void) +{ + struct timeval tp; + struct timezone tzp; + + gettimeofday(&tp, &tzp); + + if (!secbase) + { + secbase = tp.tv_sec; + return tp.tv_usec/1000; + } + return (tp.tv_sec - secbase) + tp.tv_usec/1000; +} + double Sys_DoubleTime (void) { struct timeval tp; struct timezone tzp; - static int secbase; gettimeofday(&tp, &tzp); diff --git a/engine/client/valid.c b/engine/client/valid.c index bc2daf865..87c17c6bb 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -30,6 +30,7 @@ typedef struct f_modified_s { f_modified_t *f_modified_list; qboolean care_f_modified; qboolean f_modified_particles; +qboolean f_modified_staticlights; cvar_t allow_f_version = {"allow_f_version", "1"}; @@ -246,6 +247,7 @@ void ValidationPrintVersion(char *f_query_string) } void Validation_FilesModified (void) { + Con_Printf ("Not implemented\n", RESTRICT_RCON); } void Validation_CheckIfResponse(char *text) { @@ -443,6 +445,7 @@ void Validation_IncludeFile(char *filename, char *file, int filelen) } qboolean f_modified_particles; +qboolean f_modified_staticlights; qboolean care_f_modified; @@ -477,11 +480,6 @@ qboolean care_f_modified; #define SECURE_ANSWER_NO 'n' #define SECURE_ANSWER_ERROR 'n' -cvar_t allow_f_version = {"allow_f_version", "1"}; -cvar_t allow_f_server = {"allow_f_server", "1"}; -cvar_t allow_f_modified = {"allow_f_modified", "1"}; -cvar_t allow_f_skins = {"allow_f_skins", "1"}; -cvar_t auth_validateclients = {"auth_validateclients", "1"}; // // last f_queries @@ -502,13 +500,7 @@ f_query_t; f_query_t f_last_queries[F_QUERIES_REMEMBERED]; int f_last_query_pos = 0; -typedef struct f_modified_s { - char name[MAX_QPATH]; - qboolean ismodified; - struct f_modified_s *next; -} f_modified_t; -f_modified_t *f_modified_list; qboolean care_f_modified; qboolean f_modified_particles; @@ -750,7 +742,7 @@ void Validation_FilesModified (void) } if (count == 0) strcat(buf, "all models ok"); - + Cbuf_AddText("say ", RESTRICT_LOCAL); Cbuf_AddText(buf, RESTRICT_LOCAL); Cbuf_AddText("\n", RESTRICT_LOCAL); diff --git a/engine/client/view.c b/engine/client/view.c index 51398baee..ba1b8f2fe 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1514,8 +1514,11 @@ void V_RenderView (void) if (cl.worldmodel) { RSpeedMark(); + CL_AllowIndependantSendCmd(false); + CL_EmitEntities(); + //work out which packet entities are solid CL_SetSolidEntities (); @@ -1529,7 +1532,7 @@ void V_RenderView (void) CL_SetUpPlayerPrediction(true); // build a refresh entity list - CL_EmitEntities (); +// CL_EmitEntities (); CL_AllowIndependantSendCmd(true); diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index cee7657eb..f225b07e1 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -146,7 +146,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. //fix things a little... #ifdef MINGW - #undef ZLIB #undef AVAIL_ZLIB #endif @@ -154,10 +153,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define AVAIL_MP3 //suposedly anti-gpl. don't use in a distributed binary #endif -#ifndef ZLIB - #undef AVAIL_ZLIB //no zip/pk3 support -#endif - #ifndef _WIN32 #undef QTERM #endif diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 3db2f8706..0156d8b8b 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -88,12 +88,12 @@ typedef struct cvar_group_s //freestyle #define CVAR_POINTER 32 // q2 style. May be converted to q1 if needed. These are often specified on the command line and then converted into q1 when registered properly. -#define CVAR_NOTFROMSERVER 64 +#define CVAR_NOTFROMSERVER 64 // the console will ignore changes to cvars if set at from the server or any gamecode. This is to protect against security flaws - like qterm #define CVAR_USERCREATED 128 //write a 'set' or 'seta' in front of the var name. #define CVAR_CHEAT 256 //latch to the default, unless cheats are enabled. #define CVAR_SEMICHEAT 512 //if strict ruleset, force to 0/blank. -#define CVAR_RENDERERLATCH 1024 -#define CVAR_SERVEROVERRIDE 2048 // +#define CVAR_RENDERERLATCH 1024 //requires a vid_restart to reapply. +#define CVAR_SERVEROVERRIDE 2048 //the server has overridden out local value - should probably be called SERVERLATCH #define CVAR_LASTFLAG CVAR_SERVEROVERRIDE diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 01b8e1ca9..45a8c3bd4 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -723,6 +723,7 @@ typedef struct entity_state_s #define MAX_MVDPACKET_ENTITIES 196 // doesn't count nails typedef struct { + float servertime; int num_entities; int max_entities; entity_state_t *entities; diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 57ddcf850..df9bdfef1 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -214,15 +214,15 @@ void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) QCRC_Init(&crc); for (len = buffersize, p = buffer; len; len--, p++) QCRC_ProcessByte(&crc, *p); - + sprintf(st, "%d", (int) crc); - Info_SetValueForKey (cls.userinfo, + Info_SetValueForKey (cls.userinfo, !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, st, MAX_INFO_STRING); if (cls.state >= ca_connected) { - CL_SendClientCommand(true, "setinfo %s %d", + CL_SendClientCommand(true, "setinfo %s %d", !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, (int)crc); } @@ -496,7 +496,7 @@ static void R_LerpBones(float *plerp, float **pose, int poses, galiasbone_t *bon for (b = 0;b < poses;b++) { matrix = pose[b] + i*12; - + for (k = 0;k < 12;k++) m[k] += matrix[k] * plerp[b]; } @@ -922,7 +922,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur Skin_Find(e->scoreboard); tc = e->scoreboard->topcolor; bc = e->scoreboard->bottomcolor; - + //colour forcing if (cl.splitclients<2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. { @@ -955,7 +955,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur tc = 1; bc = 1; } - + if (tc != 1 || bc != 1 || (e->scoreboard && e->scoreboard->skin)) { int inwidth, inheight; @@ -979,10 +979,10 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur } else skinname = modelname; - + if (!skincolourmapped.numbuckets) Hash_InitTable(&skincolourmapped, 256, BZ_Malloc(Hash_BytesForBuckets(256))); - + for (cm = Hash_Get(&skincolourmapped, skinname); cm; cm = Hash_GetNext(&skincolourmapped, skinname, cm)) { if (cm->colour == cc && cm->skinnum == e->skinnum) @@ -990,7 +990,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur return &cm->texnum; } } - + if (!inf->numskins) { skins = NULL; @@ -1018,7 +1018,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur if (!texnums) { //load just the skin if (e->scoreboard && e->scoreboard->skin) - { + { original = Skin_Cache8(e->scoreboard->skin); if (!original) return NULL; @@ -1069,41 +1069,41 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur static unsigned pixels[512*512]; unsigned *out; unsigned frac, fracstep; - + unsigned scaled_width, scaled_height; qbyte *inrow; - + texnums = &cm->texnum; - + texnums->base = 0; texnums->fullbright = 0; - + scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512; scaled_height = gl_max_size.value < 512 ? gl_max_size.value : 512; - + for (i=0 ; i<256 ; i++) translate[i] = i; - + tc<<=4; bc<<=4; - + for (i=0 ; i<16 ; i++) { if (tc < 128) // the artists made some backwards ranges. sigh. translate[TOP_RANGE+i] = tc+i; else translate[TOP_RANGE+i] = tc+15-i; - + if (bc < 128) translate[BOTTOM_RANGE+i] = bc+i; else translate[BOTTOM_RANGE+i] = bc+15-i; } - - + + for (i=0 ; i<256 ; i++) translate32[i] = d_8to24rgbtable[translate[i]]; - + out = pixels; fracstep = tinwidth*0x10000/scaled_width; for (i=0 ; ibase = texture_extension_number++; GL_Bind(texnums->base); qglTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - + + //now do the fullbrights. out = pixels; fracstep = tinwidth*0x10000/scaled_width; @@ -1147,7 +1147,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur texnums->fullbright = texture_extension_number++; GL_Bind(texnums->fullbright); qglTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); - + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } @@ -1156,10 +1156,10 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur skins = (galiasskin_t*)((char *)inf + inf->ofsskins); if (e->skinnum >= 0 && e->skinnum < inf->numskins) skins += e->skinnum; - + if (!skins->texnums) return NULL; - + frame = cl.time*skins->skinspeed; frame = frame%skins->texnums; texnums = (galiastexnum_t*)((char *)skins + skins->ofstexnums + frame*sizeof(galiastexnum_t)); @@ -1184,7 +1184,7 @@ static galiastexnum_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int sur frame = cl.time*skins->skinspeed; frame = frame%skins->texnums; texnums = (galiastexnum_t*)((char *)skins + skins->ofstexnums + frame*sizeof(galiastexnum_t)); - + return texnums; } @@ -1200,7 +1200,7 @@ static void R_CalcFacing(mesh_t *mesh, vec3_t lightpos) index_t *indexes = mesh->indexes; int numtris = mesh->numindexes/3; - + if (numFacing < numtris) { @@ -1319,7 +1319,7 @@ void GL_DrawAliasMesh_Sketch (mesh_t *mesh) qglDepthFunc(gldepthfunc); qglDepthMask(1); - if (gldepthmin == 0.5) + if (gldepthmin == 0.5) qglCullFace ( GL_BACK ); else qglCullFace ( GL_FRONT ); @@ -1402,7 +1402,7 @@ void GL_KnownState(void) extern int gldepthfunc; qglDepthFunc(gldepthfunc); qglDepthMask(1); - if (gldepthmin == 0.5) + if (gldepthmin == 0.5) qglCullFace ( GL_BACK ); else qglCullFace ( GL_FRONT ); @@ -1425,7 +1425,7 @@ void GL_DrawAliasMesh (mesh_t *mesh, int texnum) qglDepthMask(1); GL_Bind(texnum); - if (gldepthmin == 0.5) + if (gldepthmin == 0.5) qglCullFace ( GL_BACK ); else qglCullFace ( GL_FRONT ); @@ -1464,11 +1464,46 @@ void GL_DrawAliasMesh (mesh_t *mesh, int texnum) #endif } +qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs) +{ + int i; + vec3_t wmin, wmax; + float fmin, fmax; + + //convert the model's bbox to the expanded maximum size of the entity, as drawn with this model. + //The result is an axial box, which we pass to R_CullBox + + for (i = 0; i < 3; i++) + { + fmin = DotProduct(modmins, e->axis[i]); + fmax = DotProduct(modmaxs, e->axis[i]); + + if (fmin > -16) + fmin = -16; + if (fmax < 16) + fmax = 16; + + if (fmin < fmax) + { + wmin[i] = e->origin[i]+fmin; + wmax[i] = e->origin[i]+fmax; + } + else + { //box went inside out + wmin[i] = e->origin[i]+fmax; + wmax[i] = e->origin[i]+fmin; + } + } + + + return R_CullBox(wmin, wmax); +} + + void R_DrawGAliasModel (entity_t *e) { extern cvar_t r_drawflat; model_t *clmodel; - vec3_t mins, maxs; vec3_t dist; vec_t add; int i; @@ -1506,11 +1541,8 @@ void R_DrawGAliasModel (entity_t *e) clmodel = e->model; } - VectorAdd (e->origin, clmodel->mins, mins); - VectorAdd (e->origin, clmodel->maxs, maxs); - if (!(e->flags & Q2RF_WEAPONMODEL)) - if (R_CullBox (mins, maxs)) + if (R_CullEntityBox (e, clmodel->mins, clmodel->maxs)) return; if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) @@ -1637,11 +1669,11 @@ void R_DrawGAliasModel (entity_t *e) shadelight[2] += sin(cl.time)*0.25; } -/* +/* VectorClear(ambientlight); VectorClear(shadelight); */ - + /* an = e->angles[1]/180*M_PI; shadevector[0] = cos(-an); @@ -1792,7 +1824,7 @@ void R_DrawGAliasModel (entity_t *e) qglTranslatef (tmatrix[0][3],tmatrix[1][3],tmatrix[2][3]); qglScalef (tmatrix[0][0],tmatrix[1][1],tmatrix[2][2]); - + qglScalef( 1/scale[0], 1/scale[1], 1/scale[2]); @@ -1959,7 +1991,7 @@ qglColor3f(0,0,1); qglShadeModel (GL_FLAT); if (gl_affinemodels.value) - qglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + qglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); if (e->flags & Q2RF_DEPTHHACK) qglDepthRange (gldepthmin, gldepthmax); @@ -2222,7 +2254,7 @@ void R_DrawMeshBumpmap(mesh_t *mesh, galiastexnum_t *skin, vec3_t lightdir) //the bumpmap we use is tangent-space (so I'm told) qglDepthFunc(gldepthfunc); qglDepthMask(0); - if (gldepthmin == 0.5) + if (gldepthmin == 0.5) qglCullFace ( GL_BACK ); else qglCullFace ( GL_FRONT ); @@ -2414,7 +2446,7 @@ void R_DrawGAliasModelLighting (entity_t *e, vec3_t lightpos, vec3_t colours, fl qglShadeModel (GL_FLAT); if (gl_affinemodels.value) - qglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + qglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); qglDisable(GL_POLYGON_OFFSET_FILL); if (e->flags & Q2RF_DEPTHHACK) @@ -2482,10 +2514,10 @@ static int R_FindTriangleWithEdge ( int *indexes, int numtris, int start, int en { int i; int match, count; - + count = 0; match = -1; - + for (i = 0; i < numtris; i++, indexes += 3) { if ( (indexes[0] == start && indexes[1] == end) @@ -2605,7 +2637,7 @@ static qboolean VARGS TryAddSkin(char *skinname, ...) //make sure we don't add it twice int i; - + va_start (argptr, skinname); _vsnprintf (string,sizeof(string)-1, skinname,argptr); va_end (argptr); @@ -2683,8 +2715,8 @@ int GL_BuildSkinFileList(char *modelname) } } - COM_EnumerateFiles(va("%s_*.skin", modelname), GL_EnumerateSkins, NULL); - COM_EnumerateFiles(va("%s_*.skin", skinfilename), GL_EnumerateSkins, NULL); + COM_EnumerateFiles(va("%s_*.skin", modelname), GL_EnumerateSkins, NULL); + COM_EnumerateFiles(va("%s_*.skin", skinfilename), GL_EnumerateSkins, NULL); return skinfilecount; } @@ -3098,7 +3130,7 @@ static void *Q1_LoadSkins (daliasskintype_t *pskintype, qboolean alpha) */ texnums->base = texture; texnums->fullbright = fbtexture; - } + } pskintype = (daliasskintype_t *)data; break; } @@ -3128,7 +3160,7 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) loadmodel=mod; Mod_DoCRC(loadmodel, buffer, com_filesize); - + hunkstart = Hunk_LowMark (); pq1inmodel = (dmdl_t *)buffer; @@ -3246,11 +3278,11 @@ void GL_LoadQ1Model (model_t *mod, void *buffer) VectorMA (mod->mins, 255, pq1inmodel->scale, mod->maxs); // // move the complete, relocatable alias model to the cache -// +// hunkend = Hunk_LowMark (); Hunk_Alloc(0); hunktotal = hunkend - hunkstart; - + Cache_Alloc (&mod->cache, hunktotal, loadname); mod->type = mod_alias; if (!mod->cache.data) @@ -3353,7 +3385,7 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) dmd2aliasframe_t *pinframe; int framesize; vec3_t *verts; - + int indremap[MD2_MAX_TRIANGLES*3]; unsigned short ptempindex[MD2_MAX_TRIANGLES*3], ptempstindex[MD2_MAX_TRIANGLES*3]; @@ -3459,7 +3491,7 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) galias->numverts = numverts; // remap remaining indexes - for ( i = 0; i < numindexes; i++ ) + for ( i = 0; i < numindexes; i++ ) { if ( indremap[i] != i ) { indexes[i] = indexes[indremap[i]]; @@ -3555,11 +3587,11 @@ void GL_LoadQ2Model (model_t *mod, void *buffer) */ // // move the complete, relocatable alias model to the cache -// +// hunkend = Hunk_LowMark (); Hunk_Alloc(0); hunktotal = hunkend - hunkstart; - + Cache_Alloc (&mod->cache, hunktotal, loadname); mod->type = mod_alias; if (!mod->cache.data) @@ -3688,7 +3720,7 @@ qboolean Mod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2 for (b = 0;b < numposes;b++) { matrix = pose[b] + tagnum*12; - + for (k = 0;k < 12;k++) m[k] += matrix[k] * plerp[b]; } @@ -3719,7 +3751,7 @@ qboolean Mod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2 t1 = (md3tag_t*)((char*)inf + inf->ofstags); t1 += tagnum; t1 += inf->numtags*frame1; - + t2 = (md3tag_t*)((char*)inf + inf->ofstags); t2 += tagnum; t2 += inf->numtags*frame2; @@ -3830,7 +3862,7 @@ typedef struct { int flags; //Does anyone know what these are? int numFrames; - int numTags; + int numTags; int numSurfaces; int numSkins; @@ -3851,7 +3883,7 @@ typedef struct md3Frame_s { //there are header->numSurfaces of these at header->ofsSurfaces, following from ofsEnd typedef struct { - int ident; // + int ident; // char name[MAX_QPATH]; // polyset name @@ -4031,7 +4063,7 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) pose->scale[0] = 1; pose->scale[1] = 1; pose->scale[2] = 1; - + pose->scale_origin[0] = 0; pose->scale_origin[1] = 0; pose->scale_origin[2] = 0; @@ -4213,7 +4245,7 @@ void GL_LoadQ3Model(model_t *mod, void *buffer) Hunk_Alloc(0); hunktotal = hunkend - hunkstart; - + Cache_Alloc (&mod->cache, hunktotal, loadname); mod->type = mod_alias; if (!mod->cache.data) @@ -4437,7 +4469,7 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) stcoords[i][0] = BigFloat(inst[i][0]); stcoords[i][1] = 1-BigFloat(inst[i][1]); //hmm. upside down skin coords? } - + #ifndef SERVERONLY skinfiles = GL_BuildSkinFileList(loadmodel->name); if (skinfiles < 1) @@ -4506,7 +4538,7 @@ void GLMod_LoadZymoticModel(model_t *mod, void *buffer) Hunk_Alloc(0); hunktotal = hunkend - hunkstart; - + Cache_Alloc (&mod->cache, hunktotal, loadname); mod->type = mod_alias; if (!mod->cache.data) @@ -4607,7 +4639,7 @@ typedef struct dpmbonevert_s } dpmbonevert_t; // variable size, parsed sequentially -typedef struct dpmvertex_s +typedef struct dpmvertex_s { unsigned int numbones; // immediately followed by 1 or more dpmbonevert_t structures @@ -4842,7 +4874,7 @@ void GLMod_LoadDarkPlacesModel(model_t *mod, void *buffer) Hunk_Alloc(0); hunktotal = hunkend - hunkstart; - + Cache_Alloc (&mod->cache, hunktotal, loadname); mod->type = mod_alias; if (!mod->cache.data) @@ -4876,7 +4908,7 @@ static void GenMatrix(float x, float y, float z, float qx, float qy, float qz, f if (term < 0) qw = 0; else - qw = - (float) sqrt(term); + qw = - (float) sqrt(term); } { //generate the matrix @@ -5015,7 +5047,7 @@ galiasinfo_t *GLMod_ParseMD5MeshModel(char *buffer) EXPECT("{"); //"name" parent (x y z) (s t u) //stu are a normalized quaternion, which we will convert to a 3*4 matrix for no apparent reason - + for (i = 0; i < numjoints; i++) { buffer = COM_Parse(buffer); @@ -5297,7 +5329,7 @@ void GLMod_LoadMD5MeshModel(model_t *mod, void *buffer) Hunk_Alloc(0); hunktotal = hunkend - hunkstart; - + Cache_Alloc (&mod->cache, hunktotal, loadname); mod->type = mod_alias; if (!mod->cache.data) @@ -5642,7 +5674,7 @@ void GLMod_LoadCompositeAnim(model_t *mod, void *buffer) Hunk_Alloc(0); hunktotal = hunkend - hunkstart; - + Cache_Alloc (&mod->cache, hunktotal, loadname); mod->type = mod_alias; if (!mod->cache.data) diff --git a/engine/makeconfig.sh b/engine/makeconfig.sh new file mode 100644 index 000000000..2bd4e4d45 --- /dev/null +++ b/engine/makeconfig.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +#This is a fairly lame shell script +#It could be written so much better... +#Anyway, what it does is ask the user lots of questions and then pipes some text to a file which can be used by the engine. +#the Makefile explicitally tests for config.h, and will pass the right precompiler to gcc so that this file is actually used. +#And so we don't break in the absence of this file. + +if [ $1 = y ]; then + defaulttoyes=true + echo "Checking installed libraries" +else + echo "Answer the questions to generate a config.h file" + echo "If you wish to remove the config, delete it and recompile, make will sort stuff out" + echo "Many of these questions are irrelevent if you want to build only a dedicated server, for instance" + echo "Some of them depend on others" + echo "Usage of this script is not fully supported by the FTE team, and not every combination will likly work" + echo "If using this script does produce compile errors, you can try reporting the issue preferably via irc" +fi + +#clear out the config +echo "//warning: generated file." > config.h +echo "//Use 'make config' to alter this file" >> config.h +echo "//it is safe to delete this file if you want to use the default settings" >> config.h +echo "" >> config.h + +query() +{ + if [ $defaulttoyes = true ]; then + ans=y + else + read -n 1 -p "$1 " ans + echo "" + fi + if [ $ans = y -o $ans = Y ]; then + echo "#define $2" >> config.h + else + echo "//#define $2" >> config.h + fi +} +querylibrary() +{ + if [ -f /usr/include/$3 ] ; then + query "$1" "$2" + return + fi + if [ -f /usr/local/include/$4 ] ; then + query "$1" "$2" + return + fi + echo "$1 n" + echo "//#define $2" >> config.h +} + +querylibrary "Is libz (zlib) available on this system (zip support)?" AVAIL_ZLIB "zlib.h" +querylibrary "Is libvorbis (a free media library) available on this system (ogg support) ?" AVAIL_OGGVORBIS "vorbis/vorbisfile.h" +# querylibrary "Is libmad (an mp3 library) available on this system (mp3 support) ?" AVAIL_MP3 +querylibrary "Is libpng available on this system (png support)?" AVAIL_PNGLIB "png.h" +querylibrary "Is libjpeg available on this system (jpeg support)?" AVAIL_JPEGLIB "jpeglib.h" +query "Do you want to enable the dds support ?" DDS +query "Do you want to enable on-server rankings?" SVRANKING +query "Do you want to enable stainmaps in software rendering?" SWSTAINS +query "Do you want to enable secondary/reverse views?" "SIDEVIEWS 4" +query "Do you want to enable quake2 sprites (sp2) ?" SP2MODELS +query "Do you want to enable quake2 models (md2) ?" MD2MODELS +query "Do you want to enable quake3arena models (md3) ?" MD3MODELS +query "Do you want to enable doom3 models (md5) ?" MD5MODELS +query "Do you want to enable 'zymotic' models (zym, used by nexuiz) ?" ZYMOTICMODELS +query "Do you want to enable basic halflife model support (mdl) ?" HALFLIFEMODELS +query "Do you want to enable network compression (huffman) ?" HUFFNETWORK +#query "Do you want to enable doom wad, map and sprite support (best to say no here) ?" DOOMWADS +query "Do you want to enable quake2 map support ?" Q2BSPS +query "Do you want to enable quake3 map support ?" Q3BSPS +query "Do you want to enable fte's heightmap support ?" TERRAIN +query "Do you want to enable the built in master server ?" SV_MASTER +query "Do you want to enable the FTE_NPCCHAT qc extention ?" SVCHAT +query "Do you want to enable the quake2 server ?" Q2SERVER +query "Do you want to enable the quake2 client ?" Q2CLIENT +query "Do you want to enable the quake3 server ?" Q3SERVER +query "Do you want to enable the quake3 client ?" Q3CLIENT +query "Do you want to enable netquake compatability ?" NQPROT +query "Do you want to allow connections via tcp (for suppose3rd party firewalls) ?" TCPCONNECT +query "Do you want to enable fish-eye views (only in software) ?" FISH +query "Do you want to enable the built in http/ftp server ?" WEBSERVER +query "Do you want to enable the built in http/ftp clients ?" WEBCLIENT +query "Do you want to enable the deluxemap generation routine ?" RUNTIMELIGHTING +query "Do you want to enable the 'qterm' (this is a major security risk) ?" QTERM +query "Do you want to enable the server browser ?" CL_MASTER +query "Do you want to enable the serial-mouse support (used in splitscreen) ?" SERIALMOUSE +query "Do you want to enable the per-pixel lighting routines ?" PPL +query "Do you want to enable the text editor ?" TEXTEDITOR +query "Do you want to enable the plugin support ?" PLUGINS +query "Do you want to enable csqc support ?" CSQC_DAT +query "Do you want to enable menu.dat support (used by nexuiz) ?" MENU_DAT +query "Do you want to enable quake3 shader support ?" Q3SHADERS +query "Do you want to enable the built in irc client (note that there is also a plugin irc client, which cooler) ?" IRCCLIENT + + + + + + + + + +echo "#define R_XFLIP" >> config.h +echo "#define IN_XFLIP" >> config.h + diff --git a/engine/qclib/Makefile b/engine/qclib/Makefile index eaea47d27..5180a6527 100644 --- a/engine/qclib/Makefile +++ b/engine/qclib/Makefile @@ -1,5 +1,6 @@ QCC_OBJS=qccmain.o qcc_cmdlib.o qcc_pr_comp.o qcc_pr_lex.o comprout.o hash.o qcd_main.o GTKGUI_OBJS=qcc_gtk.o qccguistuff.c +LIB_OBJS= CC=gcc -Wall -DQCCONLY @@ -10,6 +11,7 @@ all: qcc BASE_CFLAGS=-ggdb CFLAGS = +lib: win_nocyg: $(QCC_OBJS) qccgui.c qccguistuff.c $(CC) $(BASE_CFLAGS) -o fteqcc.exe -O3 -s $(QCC_OBJS) -mno-cygwin -mwindows diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index 37e7464c7..2c3158154 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -399,6 +399,13 @@ reeval: pr_xstatement = st-pr_statements; PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); } + +//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods. +// if (ed->isfree) +// { +// pr_xstatement = st-pr_statements; +// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); +// } OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); break;