]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - cl_main.c
fix C++ compile errors
[xonotic/darkplaces.git] / cl_main.c
index 7d0a5f288f9e02f02e3d25e05b83d11cb244d3a6..420203b4f4e0c641d2fe54887432550e4c1a46d1 100644 (file)
--- a/cl_main.c
+++ b/cl_main.c
@@ -38,6 +38,7 @@ 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_lerpexcess = {0, "cl_lerpexcess", "0","maximum allowed lerp excess (hides, not fixes, some packet loss)"};
 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)"};
 
@@ -122,7 +123,7 @@ void CL_ClearState(void)
        cl.sensitivityscale = 1.0f;
 
        // enable rendering of the world and such
-       cl.csqc_vidvars.drawworld = r_drawworld.integer;
+       cl.csqc_vidvars.drawworld = r_drawworld.integer != 0;
        cl.csqc_vidvars.drawenginesbar = true;
        cl.csqc_vidvars.drawcrosshair = true;
 
@@ -171,7 +172,7 @@ void CL_ClearState(void)
                cl.entities[i].state_current = defaultstate;
        }
 
-       if (gamemode == GAME_NEXUIZ)
+       if (gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
        {
                VectorSet(cl.playerstandmins, -16, -16, -24);
                VectorSet(cl.playerstandmaxs, 16, 16, 45);
@@ -297,6 +298,7 @@ void CL_ExpandEntities(int num)
 
 void CL_ExpandCSQCRenderEntities(int num)
 {
+       int i;
        int oldmaxcsqcrenderentities;
        entity_render_t *oldcsqcrenderentities;
        if (num >= cl.max_csqcrenderentities)
@@ -310,6 +312,9 @@ void CL_ExpandCSQCRenderEntities(int num)
                if (oldcsqcrenderentities)
                {
                        memcpy(cl.csqcrenderentities, oldcsqcrenderentities, oldmaxcsqcrenderentities * sizeof(entity_render_t));
+                       for (i = 0;i < r_refdef.scene.numentities;i++)
+                               if(r_refdef.scene.entities[i] >= oldcsqcrenderentities && r_refdef.scene.entities[i] < (oldcsqcrenderentities + oldmaxcsqcrenderentities))
+                                       r_refdef.scene.entities[i] = cl.csqcrenderentities + (r_refdef.scene.entities[i] - oldcsqcrenderentities);
                        Mem_Free(oldcsqcrenderentities);
                }
        }
@@ -407,11 +412,15 @@ CL_EstablishConnection
 Host should be either "local" or a net address
 =====================
 */
-void CL_EstablishConnection(const char *host)
+void CL_EstablishConnection(const char *host, int firstarg)
 {
        if (cls.state == ca_dedicated)
                return;
 
+       // don't connect to a server if we're benchmarking a demo
+       if (COM_CheckParm("-benchmark"))
+               return;
+
        // clear menu's connect error message
        M_Update_Return_Reason("");
        cls.demonum = -1;
@@ -434,7 +443,24 @@ void CL_EstablishConnection(const char *host)
                cls.connect_trying = true;
                cls.connect_remainingtries = 3;
                cls.connect_nextsendtime = 0;
+
+               // only NOW, set connect_userinfo
+               if(firstarg >= 0)
+               {
+                       int i;
+                       *cls.connect_userinfo = 0;
+                       for(i = firstarg; i+2 <= Cmd_Argc(); i += 2)
+                               InfoString_SetValue(cls.connect_userinfo, sizeof(cls.connect_userinfo), Cmd_Argv(i), Cmd_Argv(i+1));
+               }
+               else if(firstarg < -1)
+               {
+                       // -1: keep as is (reconnect)
+                       // -2: clear
+                       *cls.connect_userinfo = 0;
+               }
+
                M_Update_Return_Reason("Trying to connect...");
+
                // run several network frames to jump into the game quickly
                //if (sv.active)
                //{
@@ -603,12 +629,20 @@ static float CL_LerpPoint(void)
        }
 
        f = (cl.time - cl.mtime[1]) / (cl.mtime[0] - cl.mtime[1]);
-       return bound(0, f, 1);
+       return bound(0, f, 1 + cl_lerpexcess.value);
 }
 
 void CL_ClearTempEntities (void)
 {
        r_refdef.scene.numtempentities = 0;
+       // grow tempentities buffer on request
+       if (r_refdef.scene.expandtempentities)
+       {
+               Con_Printf("CL_NewTempEntity: grow maxtempentities from %i to %i\n", r_refdef.scene.maxtempentities, r_refdef.scene.maxtempentities * 2);
+               r_refdef.scene.maxtempentities *= 2;
+               r_refdef.scene.tempentities = (entity_render_t *)Mem_Realloc(cls.permanentmempool, r_refdef.scene.tempentities, sizeof(entity_render_t) * r_refdef.scene.maxtempentities);
+               r_refdef.scene.expandtempentities = false;
+       }
 }
 
 entity_render_t *CL_NewTempEntity(double shadertime)
@@ -618,7 +652,10 @@ entity_render_t *CL_NewTempEntity(double shadertime)
        if (r_refdef.scene.numentities >= r_refdef.scene.maxentities)
                return NULL;
        if (r_refdef.scene.numtempentities >= r_refdef.scene.maxtempentities)
+       {
+               r_refdef.scene.expandtempentities = true; // will be reallocated next frame since current frame may have pointers set already
                return NULL;
+       }
        render = &r_refdef.scene.tempentities[r_refdef.scene.numtempentities++];
        memset (render, 0, sizeof(*render));
        r_refdef.scene.entities[r_refdef.scene.numentities++] = render;
@@ -871,7 +908,8 @@ void CL_AddQWCTFFlagModel(entity_t *player, int skin)
        CL_UpdateRenderEntity(flagrender);
 }
 
-matrix4x4_t viewmodelmatrix;
+matrix4x4_t viewmodelmatrix_withbob;
+matrix4x4_t viewmodelmatrix_nobob;
 
 static const vec3_t muzzleflashorigin = {18, 0, 0};
 
@@ -905,6 +943,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        int frame;
        float origin[3], angles[3], lerp;
        entity_t *t;
+       entity_render_t *r;
        //entity_persistent_t *p = &e->persistent;
        //entity_render_t *r = &e->render;
        // skip inactive entities and world
@@ -937,22 +976,33 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
                        return;
                t = cl.entities + e->state_current.tagentity;
                // if the tag entity is inactive, skip it
-               if (!t->state_current.active)
-                       return;
-               // update the parent first
-               CL_UpdateNetworkEntity(t, recursionlimit - 1, interpolate);
+               if (t->state_current.active)
+               {
+                       // update the parent first
+                       CL_UpdateNetworkEntity(t, recursionlimit - 1, interpolate);
+                       r = &t->render;
+               }
+               else
+               {
+                       // it may still be a CSQC entity... trying to use its
+                       // info from last render frame (better than nothing)
+                       if(!cl.csqc_server2csqcentitynumber[e->state_current.tagentity])
+                               return;
+                       r = cl.csqcrenderentities + cl.csqc_server2csqcentitynumber[e->state_current.tagentity];
+                       if(!r->entitynumber)
+                               return; // neither CSQC nor legacy entity... can't attach
+               }
                // make relative to the entity
-               matrix = &t->render.matrix;
+               matrix = &r->matrix;
                // some properties of the tag entity carry over
-               e->render.flags |= t->render.flags & (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL);
+               e->render.flags |= r->flags & (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL);
                // if a valid tagindex is used, make it relative to that tag instead
-               // 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 (e->state_current.tagentity && e->state_current.tagindex >= 1 && r->model)
                {
-                       if(!Mod_Alias_GetTagMatrix(t->render.model, t->render.frameblend, t->render.skeleton, e->state_current.tagindex - 1, &blendmatrix)) // i.e. no error
+                       if(!Mod_Alias_GetTagMatrix(r->model, r->frameblend, r->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);
+                               Matrix4x4_Concat(&tempmatrix, &r->matrix, &blendmatrix);
                                // use the constructed tag matrix
                                matrix = &tempmatrix;
                        }
@@ -962,9 +1012,9 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        {
                // view-relative entity (guns and such)
                if (e->render.effects & EF_NOGUNBOB)
-                       matrix = &r_refdef.view.matrix; // really attached to view
+                       matrix = &viewmodelmatrix_nobob; // really attached to view
                else
-                       matrix = &viewmodelmatrix; // attached to gun bob matrix
+                       matrix = &viewmodelmatrix_withbob; // attached to gun bob matrix
        }
        else
        {
@@ -985,7 +1035,7 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
                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)
+       else if (interpolate && e->persistent.lerpdeltatime > 0 && (lerp = (cl.time - e->persistent.lerpstarttime) / e->persistent.lerpdeltatime) < 1 + cl_lerpexcess.value)
        {
                // interpolate the origin and angles
                lerp = max(0, lerp);
@@ -1050,7 +1100,17 @@ void CL_UpdateNetworkEntity(entity_t *e, int recursionlimit, qboolean interpolat
        }
 
        // animation lerp
-       if (e->render.framegroupblend[0].frame == frame)
+       e->render.skeleton = NULL;
+       if (e->render.flags & RENDER_COMPLEXANIMATION)
+       {
+               e->render.framegroupblend[0] = e->state_current.framegroupblend[0];
+               e->render.framegroupblend[1] = e->state_current.framegroupblend[1];
+               e->render.framegroupblend[2] = e->state_current.framegroupblend[2];
+               e->render.framegroupblend[3] = e->state_current.framegroupblend[3];
+               if (e->state_current.skeletonobject.model && e->state_current.skeletonobject.relativetransforms)
+                       e->render.skeleton = &e->state_current.skeletonobject;
+       }
+       else if (e->render.framegroupblend[0].frame == frame)
        {
                // update frame lerp fraction
                e->render.framegroupblend[0].lerp = 1;
@@ -1159,15 +1219,15 @@ void CL_UpdateNetworkEntityTrail(entity_t *e)
        {
                if (e->render.effects & EF_BRIGHTFIELD)
                {
-                       if (gamemode == GAME_NEXUIZ)
+                       if (gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
                                trailtype = EFFECT_TR_NEXUIZPLASMA;
                        else
                                CL_EntityParticles(e);
                }
                if (e->render.effects & EF_FLAME)
-                       CL_ParticleTrail(EFFECT_EF_FLAME, bound(0, cl.time - cl.oldtime, 0.1), origin, origin, vec3_origin, vec3_origin, NULL, 0, false, true);
+                       CL_ParticleTrail(EFFECT_EF_FLAME, bound(0, cl.time - cl.oldtime, 0.1), origin, origin, vec3_origin, vec3_origin, NULL, 0, false, true, NULL, NULL);
                if (e->render.effects & EF_STARDUST)
-                       CL_ParticleTrail(EFFECT_EF_STARDUST, bound(0, cl.time - cl.oldtime, 0.1), origin, origin, vec3_origin, vec3_origin, NULL, 0, false, true);
+                       CL_ParticleTrail(EFFECT_EF_STARDUST, bound(0, cl.time - cl.oldtime, 0.1), origin, origin, vec3_origin, vec3_origin, NULL, 0, false, true, NULL, NULL);
        }
        if (e->render.internaleffects & (INTEF_FLAG1QW | INTEF_FLAG2QW))
        {
@@ -1201,6 +1261,8 @@ void CL_UpdateNetworkEntityTrail(entity_t *e)
        // do trails
        if (e->render.flags & RENDER_GLOWTRAIL)
                trailtype = EFFECT_TR_GLOWTRAIL;
+       if (e->state_current.traileffectnum)
+               trailtype = (effectnameindex_t)e->state_current.traileffectnum;
        // check if a trail is allowed (it is not after a teleport for example)
        if (trailtype && e->persistent.trail_allowed)
        {
@@ -1211,7 +1273,7 @@ void CL_UpdateNetworkEntityTrail(entity_t *e)
                if (len > 0)
                        len = 1.0f / len;
                VectorScale(vel, len, vel);
-               CL_ParticleTrail(trailtype, 1, e->persistent.trail_origin, origin, vel, vel, e, e->state_current.glowcolor, false, true);
+               CL_ParticleTrail(trailtype, 1, e->persistent.trail_origin, origin, vel, vel, e, e->state_current.glowcolor, false, true, NULL, NULL);
        }
        // now that the entity has survived one trail update it is allowed to
        // leave a real trail on later frames
@@ -1355,7 +1417,13 @@ void CL_LinkNetworkEntity(entity_t *e)
                        return;
                // if the tag entity is inactive, skip it
                if (!cl.entities[e->state_current.tagentity].state_current.active)
-                       return;
+               {
+                       if(!cl.csqc_server2csqcentitynumber[e->state_current.tagentity])
+                               return;
+                       if(!cl.csqcrenderentities[cl.csqc_server2csqcentitynumber[e->state_current.tagentity]].entitynumber)
+                               return;
+                       // if we get here, it's properly csqc networked and attached
+               }
        }
 
        // create entity dlights associated with this entity
@@ -1378,7 +1446,7 @@ void CL_LinkNetworkEntity(entity_t *e)
        {
                if (e->render.effects & EF_BRIGHTFIELD)
                {
-                       if (gamemode == GAME_NEXUIZ)
+                       if (gamemode == GAME_NEXUIZ || gamemode == GAME_XONOTIC)
                                trailtype = EFFECT_TR_NEXUIZPLASMA;
                }
                if (e->render.effects & EF_DIMLIGHT)
@@ -1411,9 +1479,9 @@ void CL_LinkNetworkEntity(entity_t *e)
                        dlightcolor[2] += 1.50f;
                }
                if (e->render.effects & EF_FLAME)
-                       CL_ParticleTrail(EFFECT_EF_FLAME, 0, origin, origin, vec3_origin, vec3_origin, NULL, 0, true, false);
+                       CL_ParticleTrail(EFFECT_EF_FLAME, 1, origin, origin, vec3_origin, vec3_origin, NULL, 0, true, false, NULL, NULL);
                if (e->render.effects & EF_STARDUST)
-                       CL_ParticleTrail(EFFECT_EF_STARDUST, 0, origin, origin, vec3_origin, vec3_origin, NULL, 0, true, false);
+                       CL_ParticleTrail(EFFECT_EF_STARDUST, 1, origin, origin, vec3_origin, vec3_origin, NULL, 0, true, false, NULL, NULL);
        }
        // muzzleflash fades over time, and is offset a bit
        if (e->persistent.muzzleflash > 0 && r_refdef.scene.numlights < MAX_DLIGHTS)
@@ -1423,7 +1491,7 @@ void CL_LinkNetworkEntity(entity_t *e)
                trace_t trace;
                matrix4x4_t tempmatrix;
                Matrix4x4_Transform(&e->render.matrix, muzzleflashorigin, v2);
-               trace = CL_TraceLine(origin, v2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, NULL, false);
+               trace = CL_TraceLine(origin, v2, MOVE_NOMONSTERS, NULL, SUPERCONTENTS_SOLID | SUPERCONTENTS_SKY, true, false, NULL, false, false);
                Matrix4x4_Normalize(&tempmatrix, &e->render.matrix);
                Matrix4x4_SetOrigin(&tempmatrix, trace.endpos[0], trace.endpos[1], trace.endpos[2]);
                Matrix4x4_Scale(&tempmatrix, 150, 1);
@@ -1492,8 +1560,10 @@ void CL_LinkNetworkEntity(entity_t *e)
        // do trail light
        if (e->render.flags & RENDER_GLOWTRAIL)
                trailtype = EFFECT_TR_GLOWTRAIL;
+       if (e->state_current.traileffectnum)
+               trailtype = (effectnameindex_t)e->state_current.traileffectnum;
        if (trailtype)
-               CL_ParticleTrail(trailtype, 0, origin, origin, vec3_origin, vec3_origin, NULL, e->state_current.glowcolor, true, false);
+               CL_ParticleTrail(trailtype, 1, origin, origin, vec3_origin, vec3_origin, NULL, e->state_current.glowcolor, true, false, NULL, NULL);
 
        // don't show entities with no modelindex (note: this still shows
        // entities which have a modelindex that resolved to a NULL model)
@@ -1842,7 +1912,7 @@ void CL_UpdateWorld(void)
        r_refdef.scene.numlights = 0;
        r_refdef.view.matrix = identitymatrix;
        r_refdef.view.quality = 1;
-
+               
        cl.num_brushmodel_entities = 0;
 
        if (cls.state == ca_connected && cls.signon == SIGNONS)
@@ -2322,6 +2392,7 @@ CL_Init
 */
 void CL_Init (void)
 {
+
        cls.levelmempool = Mem_AllocPool("client (per-level memory)", 0, NULL);
        cls.permanentmempool = Mem_AllocPool("client (long term memory)", 0, NULL);
 
@@ -2330,7 +2401,8 @@ 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 = MAX_TEMPENTITIES; // FIXME: make this grow
+       // max temp entities
+       r_refdef.scene.maxtempentities = MAX_TEMPENTITIES;
        r_refdef.scene.tempentities = (entity_render_t *)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t) * r_refdef.scene.maxtempentities);
 
        CL_InitInput ();
@@ -2348,6 +2420,7 @@ void CL_Init (void)
        Cvar_RegisterVariable (&cl_anglespeedkey);
        Cvar_RegisterVariable (&cl_shownet);
        Cvar_RegisterVariable (&cl_nolerp);
+       Cvar_RegisterVariable (&cl_lerpexcess);
        Cvar_RegisterVariable (&cl_lerpanim_maxdelta_server);
        Cvar_RegisterVariable (&cl_lerpanim_maxdelta_framegroups);
        Cvar_RegisterVariable (&cl_deathfade);