X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=cl_main.c;h=73139f74f19f0b8e117f0945c8b4e417ac45be02;hb=929f9a6fe217e9c8ca40a68a5229b08400233946;hp=73d7adc7ec3c6740d603a70f8ee8131a3ed1fc81;hpb=d57be67cb00229acb8564b92c8b7c58eeed8a0cb;p=xonotic%2Fdarkplaces.git diff --git a/cl_main.c b/cl_main.c index 73d7adc7..73139f74 100644 --- a/cl_main.c +++ b/cl_main.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // cl_main.c -- client main loop #include "quakedef.h" +#include "cl_collision.h" // we need to declare some mouse variables here, because the menu system // references them even when on a unix system. @@ -49,6 +50,7 @@ cvar_t freelook = {CVAR_SAVE, "freelook", "1"}; cvar_t cl_draweffects = {0, "cl_draweffects", "1"}; mempool_t *cl_scores_mempool; +mempool_t *cl_refdef_mempool; client_static_t cls; client_state_t cl; @@ -57,9 +59,6 @@ entity_t cl_entities[MAX_EDICTS]; entity_t cl_static_entities[MAX_STATIC_ENTITIES]; lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; -int cl_numvisedicts; -entity_t *cl_visedicts[MAX_VISEDICTS]; - typedef struct effect_s { int active; @@ -108,8 +107,8 @@ void CL_ClearState (void) memset(cl_beams, 0, sizeof(cl_beams)); memset(cl_dlights, 0, sizeof(cl_dlights)); memset(cl_effect, 0, sizeof(cl_effect)); + CL_Screen_NewMap(); CL_Particles_Clear(); - CL_Decals_Clear(); // LordHavoc: have to set up the baseline info for alpha and other stuff for (i = 0;i < MAX_EDICTS;i++) { @@ -117,29 +116,31 @@ void CL_ClearState (void) ClearStateToDefault(&cl_entities[i].state_previous); ClearStateToDefault(&cl_entities[i].state_current); } + + CL_CGVM_Clear(); } -void CL_LerpUpdate(entity_t *e, int frame, int modelindex) +void CL_LerpUpdate(entity_t *e) { entity_persistent_t *p; entity_render_t *r; p = &e->persistent; r = &e->render; - if (p->modelindex != modelindex) + if (p->modelindex != e->state_current.modelindex) { // reset all interpolation information - p->modelindex = modelindex; - p->frame1 = p->frame2 = frame; + p->modelindex = e->state_current.modelindex; + p->frame1 = p->frame2 = e->state_current.frame; p->frame1time = p->frame2time = cl.time; p->framelerp = 1; } - else if (p->frame2 != frame) + else if (p->frame2 != e->state_current.frame) { // transition to new frame p->frame1 = p->frame2; p->frame1time = p->frame2time; - p->frame2 = frame; + p->frame2 = e->state_current.frame; p->frame2time = cl.time; p->framelerp = 0; } @@ -150,6 +151,9 @@ void CL_LerpUpdate(entity_t *e, int frame, int modelindex) p->framelerp = bound(0, p->framelerp, 1); } + r->model = cl.model_precache[e->state_current.modelindex]; + Mod_CheckLoaded(r->model); + r->frame = e->state_current.frame; r->frame1 = p->frame1; r->frame2 = p->frame2; r->framelerp = p->framelerp; @@ -167,6 +171,9 @@ This is also called on Host_Error, so it shouldn't cause any errors */ void CL_Disconnect (void) { + if (cls.state == ca_dedicated) + return; + // stop sounds (especially looping!) S_StopAllSounds (true); @@ -191,6 +198,7 @@ void CL_Disconnect (void) NET_SendUnreliableMessage (cls.netcon, &cls.message); SZ_Clear (&cls.message); NET_Close (cls.netcon); + cls.state = ca_disconnected; // prevent this code from executing again during Host_ShutdownServer // if running a local server, shut it down if (sv.active) Host_ShutdownServer(false); @@ -236,6 +244,8 @@ void CL_EstablishConnection (char *host) cls.demonum = -1; // not in the demo loop now cls.state = ca_connected; cls.signon = 0; // need all the signon messages before playing + + CL_ClearState (); } /* @@ -262,11 +272,11 @@ static void CL_PrintEntities_f (void) Con_Printf ("EMPTY\n"); continue; } - strncpy(name, ent->render.model->name, 30); - name[30] = 0; - for (j = strlen(name);j < 30;j++) + strncpy(name, ent->render.model->name, 25); + name[25] = 0; + for (j = strlen(name);j < 25;j++) name[j] = ' '; - Con_Printf ("%s:%04i (%5i %5i %5i) [%3i %3i %3i]\n", name, ent->render.frame, (int) ent->render.origin[0], (int) ent->render.origin[1], (int) ent->render.origin[2], (int) ent->render.angles[0] % 360, (int) ent->render.angles[1] % 360, (int) ent->render.angles[2] % 360); + Con_Printf ("%s:%04i (%5i %5i %5i) [%3i %3i %3i] %4.2f %5.3f\n", name, ent->render.frame, (int) ent->render.origin[0], (int) ent->render.origin[1], (int) ent->render.origin[2], (int) ent->render.angles[0] % 360, (int) ent->render.angles[1] % 360, (int) ent->render.angles[2] % 360, ent->render.scale, ent->render.alpha); } } @@ -281,53 +291,33 @@ should be put at. */ static float CL_LerpPoint (void) { - float f, frac; + float f; - f = cl.mtime[0] - cl.mtime[1]; + // dropped packet, or start of demo + if (cl.mtime[1] < cl.mtime[0] - 0.1) + cl.mtime[1] = cl.mtime[0] - 0.1; + + cl.time = bound(cl.mtime[1], cl.time, cl.mtime[0]); // LordHavoc: lerp in listen games as the server is being capped below the client (usually) + f = cl.mtime[0] - cl.mtime[1]; if (!f || cl_nolerp.integer || cls.timedemo || (sv.active && svs.maxclients == 1)) { cl.time = cl.mtime[0]; return 1; } - if (f > 0.1) - { // dropped packet, or start of demo - cl.mtime[1] = cl.mtime[0] - 0.1; - f = 0.1; - } - frac = (cl.time - cl.mtime[1]) / f; -// Con_Printf ("frac: %f\n",frac); - if (frac < 0) - { - if (frac < -0.01) - { - cl.time = cl.mtime[1]; -// Con_Printf ("low frac\n"); - } - frac = 0; - } - else if (frac > 1) - { - if (frac > 1.01) - { - cl.time = cl.mtime[0]; -// Con_Printf ("high frac\n"); - } - frac = 1; - } - - return frac; + f = (cl.time - cl.mtime[1]) / f; + return bound(0, f, 1); } static void CL_RelinkStaticEntities(void) { int i; - for (i = 0;i < cl.num_statics && cl_numvisedicts < MAX_VISEDICTS;i++) + for (i = 0;i < cl.num_statics && r_refdef.numentities < MAX_VISEDICTS;i++) { Mod_CheckLoaded(cl_static_entities[i].render.model); - cl_visedicts[cl_numvisedicts++] = &cl_static_entities[i]; + r_refdef.entities[r_refdef.numentities++] = &cl_static_entities[i].render; } } @@ -349,8 +339,6 @@ static void CL_RelinkNetworkEntities() else bobjoffset = 0; - CL_RelinkStaticEntities(); - // start on the entity after the world for (i = 1, ent = cl_entities + 1;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++) { @@ -429,8 +417,8 @@ static void CL_RelinkNetworkEntities() // if the delta is large, assume a teleport and don't lerp VectorSubtract(ent->state_current.origin, ent->state_previous.origin, delta); - // LordHavoc: increased tolerance from 100 to 200 - if ((sv.active && svs.maxclients == 1 && !(ent->state_current.flags & RENDER_STEP)) || cls.timedemo || DotProduct(delta, delta) > 200*200 || cl_nolerp.integer) + // LordHavoc: increased tolerance from 100 to 200, and now to 1000 + if ((sv.active && svs.maxclients == 1 && !(ent->state_current.flags & RENDER_STEP)) || cls.timedemo || DotProduct(delta, delta) > 1000*1000 || cl_nolerp.integer) lerp = 1; else { @@ -460,15 +448,12 @@ static void CL_RelinkNetworkEntities() VectorCopy (neworg, ent->persistent.trail_origin); // persistent.modelindex will be updated by CL_LerpUpdate - if (ent->state_current.modelindex != ent->persistent.modelindex || !ent->state_previous.active) + if (ent->state_current.modelindex != ent->persistent.modelindex) VectorCopy(neworg, oldorg); VectorCopy (neworg, ent->render.origin); ent->render.flags = ent->state_current.flags; ent->render.effects = effects = ent->state_current.effects; - ent->render.model = cl.model_precache[ent->state_current.modelindex]; - Mod_CheckLoaded(ent->render.model); - ent->render.frame = ent->state_current.frame; if (cl.scores == NULL || !ent->state_current.colormap) ent->render.colormap = -1; // no special coloring else @@ -476,11 +461,9 @@ static void CL_RelinkNetworkEntities() ent->render.skinnum = ent->state_current.skin; ent->render.alpha = ent->state_current.alpha * (1.0f / 255.0f); // FIXME: interpolate? ent->render.scale = ent->state_current.scale * (1.0f / 16.0f); // FIXME: interpolate? - glowsize = ent->state_current.glowsize * 4.0f; // FIXME: interpolate? - glowcolor = ent->state_current.glowcolor; // update interpolation info - CL_LerpUpdate(ent, ent->state_current.frame, ent->state_current.modelindex); + CL_LerpUpdate(ent); // handle effects now... dlightradius = 0; @@ -494,18 +477,7 @@ static void CL_RelinkNetworkEntities() if (effects & EF_BRIGHTFIELD) CL_EntityParticles (ent); if (effects & EF_MUZZLEFLASH) - { - vec3_t v, v2; - - AngleVectors (ent->render.angles, v, NULL, NULL); - - v2[0] = v[0] * 18 + neworg[0]; - v2[1] = v[1] * 18 + neworg[1]; - v2[2] = v[2] * 18 + neworg[2] + 16; - TraceLine(neworg, v2, v, NULL, 0); - - CL_AllocDlight (NULL, v, 100, 1, 1, 1, 0, 0.1); - } + ent->persistent.muzzleflash = 100.0f; if (effects & EF_DIMLIGHT) { dlightcolor[0] += 200.0f; @@ -537,21 +509,29 @@ static void CL_RelinkNetworkEntities() { vec3_t mins, maxs; int temp; + /* if (ent->render.angles[0] || ent->render.angles[2]) { - VectorAdd(neworg, ent->render.model->rotatedmins, mins); - VectorAdd(neworg, ent->render.model->rotatedmaxs, maxs); + VectorMA(neworg, 0.25f, ent->render.model->rotatedmins, mins); + VectorMA(neworg, 0.25f, ent->render.model->rotatedmaxs, maxs); } else if (ent->render.angles[1]) { - VectorAdd(neworg, ent->render.model->yawmins, mins); - VectorAdd(neworg, ent->render.model->yawmaxs, maxs); + VectorMA(neworg, 0.25f, ent->render.model->yawmins, mins); + VectorMA(neworg, 0.25f, ent->render.model->yawmaxs, maxs); } else { - VectorAdd(neworg, ent->render.model->normalmins, mins); - VectorAdd(neworg, ent->render.model->normalmaxs, maxs); + VectorMA(neworg, 0.25f, ent->render.model->normalmins, mins); + VectorMA(neworg, 0.25f, ent->render.model->normalmaxs, maxs); } + */ + mins[0] = neworg[0] - 16.0f; + mins[1] = neworg[1] - 16.0f; + mins[2] = neworg[2] - 16.0f; + maxs[0] = neworg[0] + 16.0f; + maxs[1] = neworg[1] + 16.0f; + maxs[2] = neworg[2] + 16.0f; // how many flames to make temp = (int) (cl.time * 300) - (int) (cl.oldtime * 300); CL_FlameCube(mins, maxs, temp); @@ -561,6 +541,59 @@ static void CL_RelinkNetworkEntities() dlightcolor[1] += d * 0.7f; dlightcolor[2] += d * 0.3f; } + if (effects & EF_STARDUST) + { + if (ent->render.model) + { + vec3_t mins, maxs; + int temp; + /* + if (ent->render.angles[0] || ent->render.angles[2]) + { + VectorMA(neworg, 0.25f, ent->render.model->rotatedmins, mins); + VectorMA(neworg, 0.25f, ent->render.model->rotatedmaxs, maxs); + } + else if (ent->render.angles[1]) + { + VectorMA(neworg, 0.25f, ent->render.model->yawmins, mins); + VectorMA(neworg, 0.25f, ent->render.model->yawmaxs, maxs); + } + else + { + VectorMA(neworg, 0.25f, ent->render.model->normalmins, mins); + VectorMA(neworg, 0.25f, ent->render.model->normalmaxs, maxs); + } + */ + mins[0] = neworg[0] - 16.0f; + mins[1] = neworg[1] - 16.0f; + mins[2] = neworg[2] - 16.0f; + maxs[0] = neworg[0] + 16.0f; + maxs[1] = neworg[1] + 16.0f; + maxs[2] = neworg[2] + 16.0f; + // how many particles to make + temp = (int) (cl.time * 200) - (int) (cl.oldtime * 200); + CL_Stardust(mins, maxs, temp); + } + d = 100; + dlightcolor[0] += d * 1.0f; + dlightcolor[1] += d * 0.7f; + dlightcolor[2] += d * 0.3f; + } + } + + if (ent->persistent.muzzleflash > 0) + { + vec3_t v, v2; + + AngleVectors (ent->render.angles, v, NULL, NULL); + + v2[0] = v[0] * 18 + neworg[0]; + v2[1] = v[1] * 18 + neworg[1]; + v2[2] = v[2] * 18 + neworg[2] + 16; + CL_TraceLine(neworg, v2, v, NULL, 0, true); + + CL_AllocDlight (NULL, v, ent->persistent.muzzleflash, 1, 1, 1, 0, 0); + ent->persistent.muzzleflash -= cl.frametime * 1000; } // LordHavoc: if the model has no flags, don't check each @@ -601,12 +634,15 @@ static void CL_RelinkNetworkEntities() } } // LordHavoc: customizable glow + glowsize = ent->state_current.glowsize; // FIXME: interpolate? + glowcolor = ent->state_current.glowcolor; if (glowsize) { - byte *tempcolor = (byte *)&d_8to24table[glowcolor]; - dlightcolor[0] += glowsize * tempcolor[0] * (1.0f / 255.0f); - dlightcolor[1] += glowsize * tempcolor[1] * (1.0f / 255.0f); - dlightcolor[2] += glowsize * tempcolor[2] * (1.0f / 255.0f); + qbyte *tempcolor = (qbyte *)&d_8to24table[glowcolor]; + // * 4 for the expansion from 0-255 to 0-1023 range, + // / 255 to scale down byte colors + glowsize *= (4.0f / 255.0f); + VectorMA(dlightcolor, glowsize, tempcolor, dlightcolor); } // LordHavoc: customizable trail if (ent->render.flags & RENDER_GLOWTRAIL) @@ -615,13 +651,11 @@ static void CL_RelinkNetworkEntities() if (dlightcolor[0] || dlightcolor[1] || dlightcolor[2]) { vec3_t vec; - dlightradius = VectorLength(dlightcolor); - d = 1.0f / dlightradius; VectorCopy(neworg, vec); // hack to make glowing player light shine on their gun if (i == cl.viewentity && !chase_active.integer) vec[2] += 30; - CL_AllocDlight (&ent->render, vec, dlightradius, dlightcolor[0] * d, dlightcolor[1] * d, dlightcolor[2] * d, 0, 0); + CL_AllocDlight (/*&ent->render*/ NULL, vec, 1, dlightcolor[0], dlightcolor[1], dlightcolor[2], 0, 0); } if (chase_active.integer) @@ -639,18 +673,26 @@ static void CL_RelinkNetworkEntities() continue; if (effects & EF_NODRAW) continue; - if (cl_numvisedicts < MAX_VISEDICTS) - cl_visedicts[cl_numvisedicts++] = ent; + if (r_refdef.numentities < MAX_VISEDICTS) + r_refdef.entities[r_refdef.numentities++] = &ent->render; } } -static void CL_LerpPlayerVelocity (void) +void CL_LerpPlayer(float frac) { int i; - float frac, d; + float d; - // fraction from previous network update to current - frac = CL_LerpPoint (); + if (cl.entitydatabase.numframes) + { + cl.viewentorigin[0] = cl.viewentoriginold[0] + frac * (cl.viewentoriginnew[0] - cl.viewentoriginold[0]); + cl.viewentorigin[1] = cl.viewentoriginold[1] + frac * (cl.viewentoriginnew[1] - cl.viewentoriginold[1]); + cl.viewentorigin[2] = cl.viewentoriginold[2] + frac * (cl.viewentoriginnew[2] - cl.viewentoriginold[2]); + } + else + VectorCopy (cl_entities[cl.viewentity].render.origin, cl.viewentorigin); + + cl.viewzoom = cl.viewzoomold + frac * (cl.viewzoomnew - cl.viewzoomold); for (i = 0;i < 3;i++) cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); @@ -747,13 +789,20 @@ static void CL_RelinkEffects() void CL_RelinkEntities (void) { - cl_numvisedicts = 0; + float frac; - CL_LerpPlayerVelocity(); + // fraction from previous network update to current + frac = CL_LerpPoint (); + + CL_DecayLights (); + CL_RelinkStaticEntities(); CL_RelinkNetworkEntities(); + CL_TraceLine_ScanForBModels(); CL_RelinkEffects(); CL_MoveParticles(); - CL_UpdateDecals(); + CL_UpdateTEnts(); + + CL_LerpPlayer(frac); } @@ -792,8 +841,14 @@ int CL_ReadFromServer (void) if (netshown) Con_Printf ("\n"); - CL_RelinkEntities (); - CL_UpdateTEnts (); + r_refdef.numentities = 0; + if (cls.state == ca_connected && cl.worldmodel) + { + CL_RelinkEntities (); + + // run cgame code (which can add more entities) + CL_CGVM_Frame(); + } // // bring the links up to date @@ -818,12 +873,31 @@ void CL_SendCmd (void) // get basic movement from keyboard CL_BaseMove (&cmd); + IN_PreMove(); // OS independent code + // allow mice or other external controllers to add to the move IN_Move (&cmd); + IN_PostMove(); // OS independent code + // send the unreliable message CL_SendMove (&cmd); } +#ifndef NOROUTINGFIX + else + { + // LordHavoc: fix for NAT routing of netquake: + // bounce back a clc_nop message to the newly allocated server port, + // to establish a routing connection for incoming frames, + // the server waits for this before sending anything + if (realtime > cl.sendnoptime) + { + Con_DPrintf("sending clc_nop to get server's attention\n"); + cl.sendnoptime = realtime + 3; + MSG_WriteByte(&cls.message, clc_nop); + } + } +#endif if (cls.demoplayback) { @@ -915,6 +989,12 @@ CL_Init */ void CL_Init (void) { + cl_scores_mempool = Mem_AllocPool("client player info"); + + cl_refdef_mempool = Mem_AllocPool("refdef"); + memset(&r_refdef, 0, sizeof(r_refdef)); + r_refdef.entities = Mem_Alloc(cl_refdef_mempool, sizeof(entity_render_t *) * MAX_VISEDICTS); + SZ_Alloc (&cls.message, 1024, "cls.message"); CL_InitInput (); @@ -965,11 +1045,10 @@ void CL_Init (void) if (gamemode == GAME_NEHAHRA) Cmd_AddCommand ("pmodel", CL_PModel_f); - cl_scores_mempool = Mem_AllocPool("client player info"); - Cvar_RegisterVariable(&cl_draweffects); CL_Parse_Init(); CL_Particles_Init(); - CL_Decals_Init(); + CL_Screen_Init(); + CL_CGVM_Init(); }