]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_main.c
capturevideo: prefill incomplete header fields a bit more defensively: 0xFFFFFFFF...
[xonotic/darkplaces.git] / cl_main.c
index ef26dc6f076bd6ab5b693ef3a9f719a84a30b0ea..33bd31d9fdf7e0155d1dac3ebf95b536a8fda248 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -89,21 +89,20 @@ cvar_t cl_locs_show = {0, "locs_show", "0", "shows defined locations for editing
 client_static_t        cls;
 client_state_t cl;
 
-#define MAX_PARTICLES                  32768   // default max # of particles at one time
-#define MAX_DECALS                             32768   // default max # of decals at one time
-#define ABSOLUTE_MIN_PARTICLES 512             // no fewer than this no matter what's on the command line
-
 /*
 =====================
 CL_ClearState
 
 =====================
 */
+void CL_VM_ShutDown (void);
 void CL_ClearState(void)
 {
        int i;
        entity_t *ent;
 
+       CL_VM_ShutDown();
+
 // wipe the entire cl structure
        Mem_EmptyPool(cls.levelmempool);
        memset (&cl, 0, sizeof(cl));
@@ -134,19 +133,10 @@ void CL_ClearState(void)
        cl.max_dlights = MAX_DLIGHTS;
        cl.max_lightstyle = MAX_LIGHTSTYLES;
        cl.max_brushmodel_entities = MAX_EDICTS;
-       cl.max_particles = MAX_PARTICLES;
-       cl.max_decals = MAX_DECALS;
+       cl.max_particles = 8192; // grows dynamically
+       cl.max_decals = 2048; // grows dynamically
        cl.max_showlmps = 0;
 
-// COMMANDLINEOPTION: Client: -particles <number> changes maximum number of particles at once, default 32768
-       i = COM_CheckParm ("-particles");
-       if (i && i < com_argc - 1)
-       {
-               cl.max_particles = (int)(atoi(com_argv[i+1]));
-               if (cl.max_particles < ABSOLUTE_MIN_PARTICLES)
-                       cl.max_particles = ABSOLUTE_MIN_PARTICLES;
-       }
-
        cl.num_dlights = 0;
        cl.num_effects = 0;
        cl.num_beams = 0;
@@ -219,7 +209,7 @@ void CL_SetInfo(const char *key, const char *value, qboolean send, qboolean allo
        if (!allowmodel && (!strcasecmp(key, "pmodel") || !strcasecmp(key, "emodel")))
                fail = true;
        for (i = 0;key[i];i++)
-               if (key[i] <= ' ' || key[i] == '\"')
+               if (ISWHITESPACE(key[i]) || key[i] == '\"')
                        fail = true;
        for (i = 0;value[i];i++)
                if (value[i] == '\r' || value[i] == '\n' || value[i] == '\"')
@@ -294,7 +284,6 @@ void CL_ExpandEntities(int num)
        }
 }
 
-void CL_VM_ShutDown (void);
 /*
 =====================
 CL_Disconnect
@@ -315,6 +304,8 @@ void CL_Disconnect(void)
 
        Con_DPrintf("CL_Disconnect\n");
 
+    Cvar_SetValueQuick(&csqc_progcrc, -1);
+       Cvar_SetValueQuick(&csqc_progsize, -1);
        CL_VM_ShutDown();
 // stop sounds (especially looping!)
        S_StopAllSounds ();
@@ -501,7 +492,7 @@ static void CL_UpdateRenderEntity_Lighting(entity_render_t *ent)
        vec3_t tempdiffusenormal;
 
        // fetch the lighting from the worldmodel data
-       VectorSet(ent->modellight_ambient, r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f), r_ambient.value * (2.0f / 128.0f));
+       VectorSet(ent->modellight_ambient, r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f), r_refdef.scene.ambient * (2.0f / 128.0f));
        VectorClear(ent->modellight_diffuse);
        VectorClear(tempdiffusenormal);
        if ((ent->flags & RENDER_LIGHT) && cl.worldmodel && cl.worldmodel->brush.LightPoint)
@@ -526,7 +517,7 @@ void CL_UpdateRenderEntity(entity_render_t *ent)
 {
        vec3_t org;
        vec_t scale;
-       model_t *model = ent->model;
+       dp_model_t *model = ent->model;
        // update the inverse matrix for the renderer
        Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
        // update the animation blend state
@@ -607,7 +598,7 @@ void CL_ClearTempEntities (void)
        r_refdef.scene.numtempentities = 0;
 }
 
-entity_render_t *CL_NewTempEntity(void)
+entity_render_t *CL_NewTempEntity(double shadertime)
 {
        entity_render_t *render;
 
@@ -619,6 +610,7 @@ entity_render_t *CL_NewTempEntity(void)
        memset (render, 0, sizeof(*render));
        r_refdef.scene.entities[r_refdef.scene.numentities++] = render;
 
+       render->shadertime = shadertime;
        render->alpha = 1;
        VectorSet(render->colormod, 1, 1, 1);
        return render;
@@ -759,7 +751,9 @@ void CL_RelinkLightFlashes(void)
                        {
                                tempmatrix = dl->matrix;
                                Matrix4x4_Scale(&tempmatrix, dl->radius, 1);
-                               R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &tempmatrix, dl->color, dl->style, dl->cubemapname, dl->shadow, dl->corona, dl->coronasizescale, dl->ambientscale, dl->diffusescale, dl->specularscale, dl->flags);
+                               // we need the corona fading to be persistent
+                               R_RTLight_Update(&dl->rtlight, false, &tempmatrix, dl->color, dl->style, dl->cubemapname, dl->shadow, dl->corona, dl->coronasizescale, dl->ambientscale, dl->diffusescale, dl->specularscale, dl->flags);
+                               r_refdef.scene.lights[r_refdef.scene.numlights++] = &dl->rtlight;
                        }
                }
        }
@@ -829,7 +823,7 @@ void CL_AddQWCTFFlagModel(entity_t *player, int skin)
        }
        // end of code taken from QuakeWorld
 
-       flagrender = CL_NewTempEntity();
+       flagrender = CL_NewTempEntity(player->render.shadertime);
        if (!flagrender)
                return;
 
@@ -877,7 +871,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        int j, k, l, frame;
        float origin[3], angles[3], delta[3], lerp, d;
        entity_t *t;
-       model_t *model;
+       dp_model_t *model;
        //entity_persistent_t *p = &e->persistent;
        //entity_render_t *r = &e->render;
        // skip inactive entities and world
@@ -890,7 +884,10 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        e->render.flags = e->state_current.flags;
        e->render.effects = e->state_current.effects;
        VectorScale(e->state_current.colormod, (1.0f / 32.0f), e->render.colormod);
-       e->render.entitynumber = e - cl.entities;
+       if(e >= cl.entities && e < cl.entities + cl.num_entities)
+               e->render.entitynumber = e - cl.entities;
+       else
+               e->render.entitynumber = 0;
        if (e->state_current.flags & RENDER_COLORMAPPED)
                CL_SetEntityColormapColors(&e->render, e->state_current.colormap);
        else if (e->state_current.colormap > 0 && e->state_current.colormap <= cl.maxclients && cl.scores != NULL)
@@ -959,11 +956,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
                interpolate = false;
        if (e == cl.entities + cl.playerentity && cl.movement_predicted && (!cl.fixangle[1] || !cl.fixangle[0]))
        {
-               lerp = (cl.time - cl.movement_time[2]) / (cl.movement_time[0] - cl.movement_time[1]);
-               lerp = bound(0, lerp, 1);
-               if (!interpolate)
-                       lerp = 1;
-               VectorLerp(cl.movement_oldorigin, lerp, cl.movement_origin, origin);
+               VectorCopy(cl.movement_origin, origin);
                VectorSet(angles, 0, cl.viewangles[1], 0);
        }
        else if (interpolate && e->persistent.lerpdeltatime > 0 && (lerp = (cl.time - e->persistent.lerpstarttime) / e->persistent.lerpdeltatime) < 1)
@@ -1075,6 +1068,8 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
                e->render.flags |= RENDER_SHADOW;
        if (e->render.flags & RENDER_VIEWMODEL)
                e->render.flags |= RENDER_NOSELFSHADOW;
+       if (e->render.effects & EF_NOSELFSHADOW)
+               e->render.flags |= RENDER_NOSELFSHADOW;
 
        // make the other useful stuff
        CL_UpdateRenderEntity(&e->render);
@@ -1369,7 +1364,8 @@ void CL_LinkNetworkEntity(entity_t *e)
                Matrix4x4_SetOrigin(&tempmatrix, trace.endpos[0], trace.endpos[1], trace.endpos[2]);
                Matrix4x4_Scale(&tempmatrix, 150, 1);
                VectorSet(color, e->persistent.muzzleflash * 4.0f, e->persistent.muzzleflash * 4.0f, e->persistent.muzzleflash * 4.0f);
-               R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &tempmatrix, color, -1, NULL, true, 0, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+               R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &tempmatrix, color, -1, NULL, true, 0, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++];
        }
        // LordHavoc: if the model has no flags, don't check each
        if (e->render.model && e->render.effects && !(e->render.flags & RENDER_VIEWMODEL))
@@ -1400,17 +1396,6 @@ void CL_LinkNetworkEntity(entity_t *e)
                dlightradius = max(dlightradius, e->state_current.glowsize * 4);
                VectorMA(dlightcolor, (1.0f / 255.0f), palette_rgb[e->state_current.glowcolor], dlightcolor);
        }
-       // make the glow dlight
-       if (dlightradius > 0 && (dlightcolor[0] || dlightcolor[1] || dlightcolor[2]) && !(e->render.flags & RENDER_VIEWMODEL) && r_refdef.scene.numlights < MAX_DLIGHTS)
-       {
-               matrix4x4_t dlightmatrix;
-               Matrix4x4_Normalize(&dlightmatrix, &e->render.matrix);
-               // hack to make glowing player light shine on their gun
-               //if (e->state_current.number == cl.viewentity/* && !chase_active.integer*/)
-               //      Matrix4x4_AdjustOrigin(&dlightmatrix, 0, 0, 30);
-               Matrix4x4_Scale(&dlightmatrix, dlightradius, 1);
-               R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &dlightmatrix, dlightcolor, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
-       }
        // custom rtlight
        if ((e->state_current.lightpflags & PFLAGS_FULLDYNAMIC) && r_refdef.scene.numlights < MAX_DLIGHTS)
        {
@@ -1425,7 +1410,20 @@ void CL_LinkNetworkEntity(entity_t *e)
                // FIXME: add ambient/diffuse/specular scales as an extension ontop of TENEBRAE_GFX_DLIGHTS?
                Matrix4x4_Normalize(&dlightmatrix, &e->render.matrix);
                Matrix4x4_Scale(&dlightmatrix, light[3], 1);
-               R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &dlightmatrix, light, e->state_current.lightstyle, e->state_current.skin > 0 ? va("cubemaps/%i", e->state_current.skin) : NULL, !(e->state_current.lightpflags & PFLAGS_NOSHADOW), (e->state_current.lightpflags & PFLAGS_CORONA) != 0, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+               R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &dlightmatrix, light, e->state_current.lightstyle, e->state_current.skin > 0 ? va("cubemaps/%i", e->state_current.skin) : NULL, !(e->state_current.lightpflags & PFLAGS_NOSHADOW), (e->state_current.lightpflags & PFLAGS_CORONA) != 0, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++];
+       }
+       // make the glow dlight
+       else if (dlightradius > 0 && (dlightcolor[0] || dlightcolor[1] || dlightcolor[2]) && !(e->render.flags & RENDER_VIEWMODEL) && r_refdef.scene.numlights < MAX_DLIGHTS)
+       {
+               matrix4x4_t dlightmatrix;
+               Matrix4x4_Normalize(&dlightmatrix, &e->render.matrix);
+               // hack to make glowing player light shine on their gun
+               //if (e->state_current.number == cl.viewentity/* && !chase_active.integer*/)
+               //      Matrix4x4_AdjustOrigin(&dlightmatrix, 0, 0, 30);
+               Matrix4x4_Scale(&dlightmatrix, dlightradius, 1);
+               R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &dlightmatrix, dlightcolor, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++];
        }
        // do trail light
        if (e->render.flags & RENDER_GLOWTRAIL)
@@ -1536,7 +1534,7 @@ static void CL_RelinkEffects(void)
 
                        // if we're drawing effects, get a new temp entity
                        // (NewTempEntity adds it to the render entities list for us)
-                       if (r_draweffects.integer && (entrender = CL_NewTempEntity()))
+                       if (r_draweffects.integer && (entrender = CL_NewTempEntity(e->starttime)))
                        {
                                // interpolation stuff
                                entrender->frame1 = intframe;
@@ -1626,7 +1624,8 @@ void CL_RelinkBeams(void)
                                vec3_t dlightcolor;
                                VectorSet(dlightcolor, 0.3, 0.7, 1);
                                Matrix4x4_CreateFromQuakeEntity(&tempmatrix, end[0], end[1], end[2], 0, 0, 0, 200);
-                               R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &tempmatrix, dlightcolor, -1, NULL, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+                               R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &tempmatrix, dlightcolor, -1, NULL, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
+                               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++];
                        }
                        if (cl_beams_polygons.integer)
                                continue;
@@ -1660,7 +1659,7 @@ void CL_RelinkBeams(void)
                d = VectorNormalizeLength(dist);
                while (d > 0)
                {
-                       entrender = CL_NewTempEntity ();
+                       entrender = CL_NewTempEntity (0);
                        if (!entrender)
                                return;
                        //VectorCopy (org, ent->render.origin);
@@ -1692,7 +1691,7 @@ static void CL_RelinkQWNails(void)
 
                // if we're drawing effects, get a new temp entity
                // (NewTempEntity adds it to the render entities list for us)
-               if (!(entrender = CL_NewTempEntity()))
+               if (!(entrender = CL_NewTempEntity(0)))
                        continue;
 
                // normal stuff
@@ -1766,6 +1765,7 @@ void CL_UpdateWorld(void)
        r_refdef.scene.numentities = 0;
        r_refdef.scene.numlights = 0;
        r_refdef.view.matrix = identitymatrix;
+       r_refdef.view.quality = 1;
 
        cl.num_brushmodel_entities = 0;
 
@@ -1801,10 +1801,7 @@ void CL_UpdateWorld(void)
                CL_RelinkLightFlashes();
                CSQC_RelinkAllEntities(ENTMASK_ENGINE | ENTMASK_ENGINEVIEWMODELS);
 
-               // move decals, particles, and any other effects
-               CL_MoveDecals();
-               CL_MoveParticles();
-               R_MoveExplosions();
+               // decals, particles, and explosions will be updated during rneder
        }
 
        r_refdef.scene.time = cl.time;
@@ -1869,6 +1866,7 @@ static void CL_TimeRefresh_f (void)
        for (i = 0;i < 128;i++)
        {
                Matrix4x4_CreateFromQuakeEntity(&r_refdef.view.matrix, r_refdef.view.origin[0], r_refdef.view.origin[1], r_refdef.view.origin[2], 0, i / 128.0 * 360.0, 0, 1);
+               r_refdef.view.quality = 1;
                CL_UpdateScreen();
        }
        timedelta = Sys_DoubleTime() - timestart;
@@ -1938,7 +1936,7 @@ void CL_Locs_AddNode(vec3_t mins, vec3_t maxs, const char *name)
        if (!name)
                name = "";
        namelen = strlen(name);
-       node = Mem_Alloc(cls.levelmempool, sizeof(cl_locnode_t) + namelen + 1);
+       node = (cl_locnode_t *) Mem_Alloc(cls.levelmempool, sizeof(cl_locnode_t) + namelen + 1);
        VectorSet(node->mins, min(mins[0], maxs[0]), min(mins[1], maxs[1]), min(mins[2], maxs[2]));
        VectorSet(node->maxs, max(mins[0], maxs[0]), max(mins[1], maxs[1]), max(mins[2], maxs[2]));
        node->name = (char *)(node + 1);
@@ -2006,7 +2004,7 @@ void CL_Locs_Save_f(void)
        FS_StripExtension(cl.worldmodel->name, locfilename, sizeof(locfilename));
        strlcat(locfilename, ".loc", sizeof(locfilename));
 
-       outfile = FS_Open(locfilename, "w", false, false);
+       outfile = FS_OpenRealFile(locfilename, "w", false);
        if (!outfile)
                return;
        // if any boxes are used then this is a proquake-format loc file, which
@@ -2106,10 +2104,10 @@ void CL_Locs_Reload_f(void)
                if (text < textend)
                        text++;
                // trim trailing whitespace
-               while (lineend > linestart && lineend[-1] <= ' ')
+               while (lineend > linestart && ISWHITESPACE(lineend[-1]))
                        lineend--;
                // trim leading whitespace
-               while (linestart < lineend && *linestart <= ' ')
+               while (linestart < lineend && ISWHITESPACE(*linestart))
                        linestart++;
                // check if this is a comment
                if (linestart + 2 <= lineend && !strncmp(linestart, "//", 2))
@@ -2126,7 +2124,7 @@ void CL_Locs_Reload_f(void)
                        else
                                maxs[i - 3] = atof(linetext);
                        // now advance past the number
-                       while (linetext < lineend && *linetext > ' ' && *linetext != ',')
+                       while (linetext < lineend && !ISWHITESPACE(*linetext) && *linetext != ',')
                                linetext++;
                        // advance through whitespace
                        if (linetext < lineend)
@@ -2137,10 +2135,10 @@ void CL_Locs_Reload_f(void)
                                        limit = 6;
                                        // note: comma can be followed by whitespace
                                }
-                               if (*linetext <= ' ')
+                               if (ISWHITESPACE(*linetext))
                                {
                                        // skip whitespace
-                                       while (linetext < lineend && *linetext <= ' ')
+                                       while (linetext < lineend && ISWHITESPACE(*linetext))
                                                linetext++;
                                }
                        }
@@ -2230,7 +2228,7 @@ void CL_Init (void)
        r_refdef.scene.maxentities = MAX_EDICTS + 256 + 512;
        r_refdef.scene.entities = (entity_render_t **)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t *) * r_refdef.scene.maxentities);
 
-       r_refdef.scene.maxtempentities = 512;
+       r_refdef.scene.maxtempentities = 4096; // FIXME: make this grow
        r_refdef.scene.tempentities = (entity_render_t *)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t) * r_refdef.scene.maxtempentities);
 
        CL_InitInput ();
@@ -2322,9 +2320,7 @@ void CL_Init (void)
        CL_Screen_Init();
 
        CL_Video_Init();
-#ifdef SUPPORT_GECKO
        CL_Gecko_Init();
-#endif
 }