]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_main.c
randomized loadingscreen pic (cvar: scr_loadingscreen_count, when 2 or above, randomi...
[xonotic/darkplaces.git] / cl_main.c
index 1e3eed5a5e8afe0c4e60110bbff0a412dbc93e49..66964ea40117fd0d42ee6ce31123a2aa7dc026f2 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -38,6 +38,8 @@ cvar_t csqc_progsize = {CVAR_READONLY, "csqc_progsize","-1","file size of csprog
 
 cvar_t cl_shownet = {0, "cl_shownet","0","1 = print packet size, 2 = print packet message list"};
 cvar_t cl_nolerp = {0, "cl_nolerp", "0","network update smoothing"};
+cvar_t cl_lerpanim_maxdelta_server = {0, "cl_lerpanim_maxdelta_server", "0.1","maximum frame delta for smoothing between server-controlled animation frames (when 0, one network frame)"};
+cvar_t cl_lerpanim_maxdelta_framegroups = {0, "cl_lerpanim_maxdelta_framegroups", "0.1","maximum frame delta for smoothing between framegroups (when 0, one network frame)"};
 
 cvar_t cl_itembobheight = {0, "cl_itembobheight", "0","how much items bob up and down (try 8)"};
 cvar_t cl_itembobspeed = {0, "cl_itembobspeed", "0.5","how frequently items bob up and down"};
@@ -72,7 +74,7 @@ cvar_t cl_beams_quakepositionhack = {CVAR_SAVE, "cl_beams_quakepositionhack", "1
 cvar_t cl_beams_instantaimhack = {CVAR_SAVE, "cl_beams_instantaimhack", "0", "makes your lightning gun aiming update instantly"};
 cvar_t cl_beams_lightatend = {CVAR_SAVE, "cl_beams_lightatend", "0", "make a light at the end of the beam"};
 
-cvar_t cl_deathfade = {CVAR_SAVE, "cl_deathfade", "0", "fade screen to dark red when dead, value = how fast the fade is"};
+cvar_t cl_deathfade = {CVAR_SAVE, "cl_deathfade", "0", "fade screen to dark red when dead, value represents how fast the fade is (higher is faster)"};
 
 cvar_t cl_noplayershadow = {CVAR_SAVE, "cl_noplayershadow", "0","hide player shadow"};
 
@@ -82,6 +84,7 @@ cvar_t cl_dlights_decaybrightness = {CVAR_SAVE, "cl_dlights_decaybrightness", "1
 cvar_t qport = {0, "qport", "0", "identification key for playing on qw servers (allows you to maintain a connection to a quakeworld server even if your port changes)"};
 
 cvar_t cl_prydoncursor = {0, "cl_prydoncursor", "0", "enables a mouse pointer which is able to click on entities in the world, useful for point and click mods, see PRYDON_CLIENTCURSOR extension in dpextensions.qc"};
+cvar_t cl_prydoncursor_notrace = {0, "cl_prydoncursor_notrace", "0", "disables traceline used in prydon cursor reporting to the game, saving some cpu time"};
 
 cvar_t cl_deathnoviewmodel = {0, "cl_deathnoviewmodel", "1", "hides gun model when dead"};
 
@@ -131,15 +134,15 @@ void CL_ClearState(void)
 
        // tweak these if the game runs out
        cl.max_csqcrenderentities = 0;
-       cl.max_entities = 256;
-       cl.max_static_entities = 256;
-       cl.max_effects = 256;
-       cl.max_beams = 256;
+       cl.max_entities = MAX_ENITIES_INITIAL;
+       cl.max_static_entities = MAX_STATICENTITIES;
+       cl.max_effects = MAX_EFFECTS;
+       cl.max_beams = MAX_BEAMS;
        cl.max_dlights = MAX_DLIGHTS;
        cl.max_lightstyle = MAX_LIGHTSTYLES;
        cl.max_brushmodel_entities = MAX_EDICTS;
-       cl.max_particles = 8192; // grows dynamically
-       cl.max_decals = 2048; // grows dynamically
+       cl.max_particles = MAX_PARTICLES_INITIAL; // grows dynamically
+       cl.max_decals = MAX_DECALS_INITIAL; // grows dynamically
        cl.max_showlmps = 0;
 
        cl.num_dlights = 0;
@@ -481,17 +484,19 @@ List information on all models in the client modelindex
 */
 static void CL_ModelIndexList_f(void)
 {
-       int i = 1;
+       int i;
+       dp_model_t *model;
 
        // Print Header
        Con_Printf("%3s: %-30s %-8s %-8s\n", "ID", "Name", "Type", "Triangles");
 
-       while(cl.model_precache[i] && i != MAX_MODELS)
-       { // Valid Model
-               if(cl.model_precache[i]->loaded || i == 1)
-                       Con_Printf("%3i: %-30s %-8s %-10i\n", i, cl.model_precache[i]->name, cl.model_precache[i]->modeldatatypestring, cl.model_precache[i]->surfmesh.num_triangles);
+       for (i = -MAX_MODELS;i < MAX_MODELS;i++)
+       {
+               model = CL_GetModelByIndex(i);
+               if(model->loaded || i == 1)
+                       Con_Printf("%3i: %-30s %-8s %-10i\n", i, model->name, model->modeldatatypestring, model->surfmesh.num_triangles);
                else
-                       Con_Printf("%3i: %-30s %-30s\n", i, cl.model_precache[i]->name, "--no local model found--");
+                       Con_Printf("%3i: %-30s %-30s\n", i, model->name, "--no local model found--");
                i++;
        }
 }
@@ -529,7 +534,7 @@ void CL_UpdateRenderEntity(entity_render_t *ent)
        // update the inverse matrix for the renderer
        Matrix4x4_Invert_Simple(&ent->inversematrix, &ent->matrix);
        // update the animation blend state
-       R_LerpAnimation(ent);
+       VM_FrameBlendFromFrameGroupBlend(ent->frameblend, ent->framegroupblend, ent->model);
        // we need the matrix origin to center the box
        Matrix4x4_OriginFromMatrix(&ent->matrix, org);
        // update entity->render.scale because the renderer needs it
@@ -854,7 +859,7 @@ void CL_AddQWCTFFlagModel(entity_t *player, int skin)
        if (!flagrender)
                return;
 
-       flagrender->model = cl.model_precache[cl.qw_modelindex_flag];
+       flagrender->model = CL_GetModelByIndex(cl.qw_modelindex_flag);
        flagrender->skinnum = skin;
        flagrender->alpha = 1;
        VectorSet(flagrender->colormod, 1, 1, 1);
@@ -943,7 +948,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
                // FIXME: use a model function to get tag info (need to handle skeletal)
                if (e->state_current.tagentity && e->state_current.tagindex >= 1 && t->render.model)
                {
-                       if(!CL_BlendTagMatrix(&t->render, e->state_current.tagindex - 1, &blendmatrix)) // i.e. no error
+                       if(!Mod_Alias_GetTagMatrix(t->render.model, t->render.frameblend, t->render.skeleton, e->state_current.tagindex - 1, &blendmatrix)) // i.e. no error
                        {
                                // concat the tag matrices onto the entity matrix
                                Matrix4x4_Concat(&tempmatrix, &t->render.matrix, &blendmatrix);
@@ -1011,10 +1016,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
 
        // model setup and some modelflags
        frame = e->state_current.frame;
-       if (e->state_current.modelindex < MAX_MODELS)
-               e->render.model = cl.model_precache[e->state_current.modelindex];
-       else
-               e->render.model = NULL;
+       e->render.model = CL_GetModelByIndex(e->state_current.modelindex);
        if (e->render.model)
        {
                if (e->render.skinnum >= e->render.model->numskins)
@@ -1057,7 +1059,13 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
                        // make sure frame lerp won't last longer than 100ms
                        // (this mainly helps with models that use framegroups and
                        // switch between them infrequently)
-                       e->render.framegroupblend[0].lerp = (cl.time - e->render.framegroupblend[0].start) / min(e->render.framegroupblend[0].start - e->render.framegroupblend[1].start, 0.1);
+                       float maxdelta = cl_lerpanim_maxdelta_server.value;
+                       if(e->render.model)
+                       if(e->render.model->animscenes)
+                       if(e->render.model->animscenes[e->render.framegroupblend[0].frame].framecount > 1 || e->render.model->animscenes[e->render.framegroupblend[1].frame].framecount > 1)
+                               maxdelta = cl_lerpanim_maxdelta_framegroups.value;
+                       maxdelta = max(maxdelta, cl.mtime[0] - cl.mtime[1]);
+                       e->render.framegroupblend[0].lerp = (cl.time - e->render.framegroupblend[0].start) / min(e->render.framegroupblend[0].start - e->render.framegroupblend[1].start, maxdelta);
                        e->render.framegroupblend[0].lerp = bound(0, e->render.framegroupblend[0].lerp, 1);
                        e->render.framegroupblend[1].lerp = 1 - e->render.framegroupblend[0].lerp;
                }
@@ -1420,7 +1428,7 @@ void CL_LinkNetworkEntity(entity_t *e)
                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.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++];
+               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];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))
@@ -1466,7 +1474,7 @@ void CL_LinkNetworkEntity(entity_t *e)
                Matrix4x4_Normalize(&dlightmatrix, &e->render.matrix);
                Matrix4x4_Scale(&dlightmatrix, light[3], 1);
                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++];
+               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];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)
@@ -1478,7 +1486,7 @@ void CL_LinkNetworkEntity(entity_t *e)
                //      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++];
+               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++;
        }
        // do trail light
        if (e->render.flags & RENDER_GLOWTRAIL)
@@ -1486,10 +1494,6 @@ void CL_LinkNetworkEntity(entity_t *e)
        if (trailtype)
                CL_ParticleTrail(trailtype, 0, origin, origin, vec3_origin, vec3_origin, NULL, e->state_current.glowcolor, true, false);
 
-       // don't show viewmodels in certain situations
-       if (e->render.flags & RENDER_VIEWMODEL)
-               if (!r_drawviewmodel.integer || chase_active.integer || r_refdef.envmap)
-                       return;
        // don't show entities with no modelindex (note: this still shows
        // entities which have a modelindex that resolved to a NULL model)
        if (e->render.model && !(e->render.effects & EF_NODRAW) && r_refdef.scene.numentities < r_refdef.scene.maxentities)
@@ -1523,7 +1527,7 @@ static void CL_RelinkStaticEntities(void)
                e->render.flags = 0;
                // if the model was not loaded when the static entity was created we
                // need to re-fetch the model pointer
-               e->render.model = cl.model_precache[e->state_baseline.modelindex];
+               e->render.model = CL_GetModelByIndex(e->state_baseline.modelindex);
                // either fullbright or lit
                if(!r_fullbright.integer)
                {
@@ -1537,7 +1541,7 @@ static void CL_RelinkStaticEntities(void)
                        e->render.flags |= RENDER_SHADOW;
                VectorSet(e->render.colormod, 1, 1, 1);
                VectorSet(e->render.glowmod, 1, 1, 1);
-               R_LerpAnimation(&e->render);
+               VM_FrameBlendFromFrameGroupBlend(e->render.frameblend, e->render.framegroupblend, e->render.model);
                e->render.allowdecals = true;
                CL_UpdateRenderEntity(&e->render);
                r_refdef.scene.entities[r_refdef.scene.numentities++] = &e->render;
@@ -1618,10 +1622,7 @@ static void CL_RelinkEffects(void)
                                }
 
                                // normal stuff
-                               if(e->modelindex < MAX_MODELS)
-                                       entrender->model = cl.model_precache[e->modelindex];
-                               else
-                                       entrender->model = cl.csqc_model_precache[-(e->modelindex+1)];
+                               entrender->model = CL_GetModelByIndex(e->modelindex);
                                entrender->alpha = 1;
                                VectorSet(entrender->colormod, 1, 1, 1);
                                VectorSet(entrender->glowmod, 1, 1, 1);
@@ -1698,7 +1699,7 @@ void CL_RelinkBeams(void)
                                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.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++];
+                               r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights];r_refdef.scene.numlights++;
                        }
                        if (cl_beams_polygons.integer)
                                continue;
@@ -1768,7 +1769,7 @@ static void CL_RelinkQWNails(void)
                        continue;
 
                // normal stuff
-               entrender->model = cl.model_precache[cl.qw_modelindex_spike];
+               entrender->model = CL_GetModelByIndex(cl.qw_modelindex_spike);
                entrender->alpha = 1;
                VectorSet(entrender->colormod, 1, 1, 1);
                VectorSet(entrender->glowmod, 1, 1, 1);
@@ -1924,6 +1925,32 @@ static void CL_Fog_f (void)
                r_refdef.fog_fadedepth = atof(Cmd_Argv(9));
 }
 
+/*
+======================
+CL_FogHeightTexture_f
+======================
+*/
+static void CL_Fog_HeightTexture_f (void)
+{
+       if (Cmd_Argc () < 11)
+       {
+               Con_Printf("\"fog_heighttexture\" is \"%f %f %f %f %f %f %f %f %f %s\"\n", r_refdef.fog_density, r_refdef.fog_red, r_refdef.fog_green, r_refdef.fog_blue, r_refdef.fog_alpha, r_refdef.fog_start, r_refdef.fog_end, r_refdef.fog_height, r_refdef.fog_fadedepth, r_refdef.fog_height_texturename);
+               return;
+       }
+       FOG_clear(); // so missing values get good defaults
+       r_refdef.fog_density = atof(Cmd_Argv(1));
+       r_refdef.fog_red = atof(Cmd_Argv(2));
+       r_refdef.fog_green = atof(Cmd_Argv(3));
+       r_refdef.fog_blue = atof(Cmd_Argv(4));
+       r_refdef.fog_alpha = atof(Cmd_Argv(5));
+       r_refdef.fog_start = atof(Cmd_Argv(6));
+       r_refdef.fog_end = atof(Cmd_Argv(7));
+       r_refdef.fog_height = atof(Cmd_Argv(8));
+       r_refdef.fog_fadedepth = atof(Cmd_Argv(9));
+       strlcpy(r_refdef.fog_height_texturename, Cmd_Argv(10), sizeof(r_refdef.fog_height_texturename));
+}
+
+
 /*
 ====================
 CL_TimeRefresh_f
@@ -2305,7 +2332,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 = 4096; // FIXME: make this grow
+       r_refdef.scene.maxtempentities = MAX_TEMPENTITIES; // 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 ();
@@ -2323,6 +2350,8 @@ void CL_Init (void)
        Cvar_RegisterVariable (&cl_anglespeedkey);
        Cvar_RegisterVariable (&cl_shownet);
        Cvar_RegisterVariable (&cl_nolerp);
+       Cvar_RegisterVariable (&cl_lerpanim_maxdelta_server);
+       Cvar_RegisterVariable (&cl_lerpanim_maxdelta_framegroups);
        Cvar_RegisterVariable (&cl_deathfade);
        Cvar_RegisterVariable (&lookspring);
        Cvar_RegisterVariable (&lookstrafe);
@@ -2352,7 +2381,8 @@ void CL_Init (void)
        Cvar_RegisterVariable (&cl_autodemo);
        Cvar_RegisterVariable (&cl_autodemo_nameformat);
 
-       Cmd_AddCommand ("fog", CL_Fog_f, "set global fog parameters (density red green blue [alpha [mindist maxdist]])");
+       Cmd_AddCommand ("fog", CL_Fog_f, "set global fog parameters (density red green blue [alpha [mindist [maxdist [top [fadedepth]]]]])");
+       Cmd_AddCommand ("fog_heighttexture", CL_Fog_HeightTexture_f, "set global fog parameters (density red green blue alpha mindist maxdist top depth textures/mapname/fogheight.tga)");
 
        // LordHavoc: added pausedemo
        Cmd_AddCommand ("pausedemo", CL_PauseDemo_f, "pause demo playback (can also safely pause demo recording if using QUAKE, QUAKEDP or NEHAHRAMOVIE protocol, useful for making movies)");
@@ -2376,6 +2406,7 @@ void CL_Init (void)
        Cvar_RegisterVariable(&cl_dlights_decaybrightness);
 
        Cvar_RegisterVariable(&cl_prydoncursor);
+       Cvar_RegisterVariable(&cl_prydoncursor_notrace);
 
        Cvar_RegisterVariable(&cl_deathnoviewmodel);