From: havoc Date: Thu, 25 May 2006 04:12:05 +0000 (+0000) Subject: replaced cl_beams_relative cvar with cl_beams_quakepositionhack and cl_beams_instanta... X-Git-Tag: xonotic-v0.1.0preview~3987 X-Git-Url: https://git.xonotic.org/?a=commitdiff_plain;h=cf2e012dfd3473a603ea187e87124cf6b6d29d7e;p=xonotic%2Fdarkplaces.git replaced cl_beams_relative cvar with cl_beams_quakepositionhack and cl_beams_instantaimhack and rewrote the relevant code, it now works like quake (except with instant aiming in the case of the instantaimhack) and applies only to your player git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@6380 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_main.c b/cl_main.c index 05570d7c..d2058952 100644 --- a/cl_main.c +++ b/cl_main.c @@ -64,8 +64,9 @@ cvar_t cl_stainmaps = {CVAR_SAVE, "cl_stainmaps", "1","stains lightmaps, much fa cvar_t cl_stainmaps_clearonload = {CVAR_SAVE, "cl_stainmaps_clearonload", "1","clear stainmaps on map restart"}; cvar_t cl_beams_polygons = {CVAR_SAVE, "cl_beams_polygons", "1","use beam polygons instead of models"}; -cvar_t cl_beams_relative = {CVAR_SAVE, "cl_beams_relative", "1","beams are relative to owner (smooth sweeps)"}; -cvar_t cl_beams_lightatend = {CVAR_SAVE, "cl_beams_lightatend", "0","make a light at the end of the beam"}; +cvar_t cl_beams_quakepositionhack = {CVAR_SAVE, "cl_beams_quakepositionhack", "1", "makes your lightning gun appear to fire from your waist (as in Quake and QuakeWorld)"}; +cvar_t cl_beams_instantaimhack = {CVAR_SAVE, "cl_beams_instantaimhack", "1", "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_noplayershadow = {CVAR_SAVE, "cl_noplayershadow", "0","hide player shadow"}; @@ -1381,11 +1382,44 @@ static void CL_RelinkEffects(void) } } +void CL_Beam_CalculatePositions(const beam_t *b, vec3_t start, vec3_t end) +{ + VectorCopy(b->start, start); + VectorCopy(b->end, end); + + // if coming from the player, update the start position + if (b->entity == cl.viewentity) + { + if (cl_beams_quakepositionhack.integer && !chase_active.integer) + { + // LordHavoc: this is a stupid hack from Quake that makes your + // lightning appear to come from your waist and cover less of your + // view + // in Quake this hack was applied to all players (causing the + // infamous crotch-lightning), but in darkplaces and QuakeWorld it + // only applies to your own lightning, and only in first person + Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, start); + } + if (cl_beams_instantaimhack.integer) + { + vec3_t dir, localend; + vec_t len; + // LordHavoc: this updates the beam direction to match your + // viewangles + VectorSubtract(end, start, dir); + len = VectorLength(dir); + VectorNormalize(dir); + VectorSet(localend, len, 0, 0); + Matrix4x4_Transform(&r_view.matrix, localend, end); + } + } +} + void CL_RelinkBeams(void) { int i; beam_t *b; - vec3_t dist, org; + vec3_t dist, org, start, end; float d; entity_t *ent; float yaw, pitch; @@ -1402,24 +1436,14 @@ void CL_RelinkBeams(void) continue; } - // if coming from the player, update the start position - //if (b->entity == cl.viewentity) - // Matrix4x4_OriginFromMatrix(&cl.entities[cl.viewentity].render.matrix, b->start); - if (cl_beams_relative.integer >= 1 && b->entity && (b->entity == cl.viewentity || cl_beams_relative.integer >= 2) && cl.entities[b->entity].state_current.active && b->relativestartvalid) - { - entity_render_t *r = &cl.entities[b->entity].render; - //Matrix4x4_OriginFromMatrix(&r->matrix, origin); - //Matrix4x4_CreateFromQuakeEntity(&matrix, r->origin[0], r->origin[1], r->origin[2] + 16, r->angles[0], r->angles[1], r->angles[2], 1); - Matrix4x4_Transform(&r->matrix, b->relativestart, b->start); - Matrix4x4_Transform(&r->matrix, b->relativeend, b->end); - } + CL_Beam_CalculatePositions(b, start, end); if (b->lightning) { if (cl_beams_lightatend.integer) { // FIXME: create a matrix from the beam start/end orientation - Matrix4x4_CreateTranslate(&tempmatrix, b->end[0], b->end[1], b->end[2]); + Matrix4x4_CreateTranslate(&tempmatrix, end[0], end[1], end[2]); CL_AllocDlight (NULL, &tempmatrix, 200, 0.3, 0.7, 1, 0, 0, 0, -1, true, 1, 0.25, 1, 0, 0, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); } if (cl_beams_polygons.integer) @@ -1427,8 +1451,8 @@ void CL_RelinkBeams(void) } // calculate pitch and yaw - VectorSubtract (b->end, b->start, dist); - + // (this is similar to the QuakeC builtin function vectoangles) + VectorSubtract(end, start, dist); if (dist[1] == 0 && dist[0] == 0) { yaw = 0; @@ -1450,7 +1474,7 @@ void CL_RelinkBeams(void) } // add new entities for the lightning - VectorCopy (b->start, org); + VectorCopy (start, org); d = VectorNormalizeLength(dist); while (d > 0) { @@ -1742,7 +1766,8 @@ void CL_Init (void) Cvar_RegisterVariable(&cl_stainmaps); Cvar_RegisterVariable(&cl_stainmaps_clearonload); Cvar_RegisterVariable(&cl_beams_polygons); - Cvar_RegisterVariable(&cl_beams_relative); + Cvar_RegisterVariable(&cl_beams_quakepositionhack); + Cvar_RegisterVariable(&cl_beams_instantaimhack); Cvar_RegisterVariable(&cl_beams_lightatend); Cvar_RegisterVariable(&cl_noplayershadow); diff --git a/cl_parse.c b/cl_parse.c index c62bfe98..ae542bae 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -1501,19 +1501,14 @@ void CL_ParseEffect2 (void) CL_Effect(org, modelindex, startframe, framecount, framerate); } -void CL_ParseBeam (model_t *m, int lightning) +void CL_NewBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning) { - int i, ent; - vec3_t start, end; + int i; beam_t *b = NULL; - ent = (unsigned short) MSG_ReadShort (); - MSG_ReadVector(start, cls.protocol); - MSG_ReadVector(end, cls.protocol); - if (ent >= MAX_EDICTS) { - Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent); + Con_Printf("CL_NewBeam: invalid entity number %i\n", ent); ent = 0; } @@ -1529,7 +1524,7 @@ void CL_ParseBeam (model_t *m, int lightning) // if the entity was not found then just replace an unused beam if (i == cl.max_beams) for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++) - if (!b->model || b->endtime < cl.time) + if (!b->model) break; if (i < cl.max_beams) { @@ -1537,36 +1532,32 @@ void CL_ParseBeam (model_t *m, int lightning) b->entity = ent; b->lightning = lightning; b->model = m; - b->endtime = cl.time + 0.2; + b->endtime = cl.mtime[0] + 0.2; VectorCopy (start, b->start); VectorCopy (end, b->end); - b->relativestartvalid = 0; - if (ent && cl.entities[ent].state_current.active) - { - entity_state_t *p; - matrix4x4_t matrix, imatrix; - if (ent == cl.viewentity && cl.movement) - p = &cl.entities[b->entity].state_previous; - else - p = &cl.entities[b->entity].state_current; - // not really valid yet, we need to get the orientation now - // (ParseBeam flagged this because it is received before - // entities are received, by now they have been received) - // note: because players create lightning in their think - // function (which occurs before movement), they actually - // have some lag in it's location, so compare to the - // previous player state, not the latest - Matrix4x4_CreateFromQuakeEntity(&matrix, p->origin[0], p->origin[1], p->origin[2], -p->angles[0], p->angles[1], p->angles[2], 1); - Matrix4x4_Invert_Simple(&imatrix, &matrix); - Matrix4x4_Transform(&imatrix, b->start, b->relativestart); - Matrix4x4_Transform(&imatrix, b->end, b->relativeend); - b->relativestartvalid = 1; - } } else Con_Print("beam list overflow!\n"); } +void CL_ParseBeam (model_t *m, int lightning) +{ + int ent; + vec3_t start, end; + + ent = (unsigned short) MSG_ReadShort (); + MSG_ReadVector(start, cls.protocol); + MSG_ReadVector(end, cls.protocol); + + if (ent >= MAX_EDICTS) + { + Con_Printf("CL_ParseBeam: invalid entity number %i\n", ent); + ent = 0; + } + + CL_NewBeam(ent, start, end, m, lightning); +} + void CL_ParseTempEntity(void) { int type; diff --git a/client.h b/client.h index f9b16e39..cfa3f3dc 100644 --- a/client.h +++ b/client.h @@ -55,12 +55,6 @@ typedef struct beam_s struct model_s *model; float endtime; vec3_t start, end; - // if this beam is owned by an entity, this is the beam start relative to - // that entity's matrix for per frame start updates - vec3_t relativestart; - vec3_t relativeend; - // indicates whether relativestart is valid - int relativestartvalid; } beam_t; @@ -963,10 +957,6 @@ void CL_Disconnect_f (void); void CL_BoundingBoxForEntity(entity_render_t *ent); -extern cvar_t cl_beams_polygons; -extern cvar_t cl_beams_relative; -extern cvar_t cl_beams_lightatend; - // // cl_input // @@ -988,7 +978,9 @@ void CL_ValidateState(entity_state_t *s); void CL_MoveLerpEntityStates(entity_t *ent); void CL_LerpUpdate(entity_t *e); void CL_ParseTEnt (void); +void CL_NewBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning); void CL_RelinkBeams (void); +void CL_Beam_CalculatePositions (const beam_t *b, vec3_t start, vec3_t end); void CL_ClearTempEntities (void); entity_t *CL_NewTempEntity (void); diff --git a/clvm_cmds.c b/clvm_cmds.c index 011de9b3..a1a7d6e2 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -1032,45 +1032,6 @@ void VM_CL_particleeffectnum (void) PRVM_G_FLOAT(OFS_RETURN) = i; } -void CSQC_ParseBeam (int ent, vec3_t start, vec3_t end, model_t *m, int lightning) -{ - int i; - beam_t *b; - - // override any beam with the same entity - for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++) - { - if (b->entity == ent && ent) - { - //b->entity = ent; - b->lightning = lightning; - b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0; - b->model = m; - b->endtime = cl.time + 0.2; - VectorCopy (start, b->start); - VectorCopy (end, b->end); - return; - } - } - - // find a free beam - for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++) - { - if (!b->model || b->endtime < cl.time) - { - b->entity = ent; - b->lightning = lightning; - b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0; - b->model = m; - b->endtime = cl.time + 0.2; - VectorCopy (start, b->start); - VectorCopy (end, b->end); - return; - } - } - Con_Print("beam list overflow!\n"); -} - // #336 void(entity ent, float effectnum, vector start, vector end[, float color]) trailparticles (EXT_CSQC) void VM_CL_trailparticles (void) { @@ -1656,74 +1617,32 @@ void VM_CL_te_explosion2 (void) } -static void VM_CL_NewBeam (int ent, float *start, float *end, model_t *m, qboolean lightning) -{ - beam_t *b; - int i; - - if (ent >= cl.max_csqcentities) - CL_ExpandCSQCEntities(ent); - - // override any beam with the same entity - for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++) - { - if (b->entity == ent && ent) - { - //b->entity = ent; - b->lightning = lightning; - b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0; - b->model = m; - b->endtime = cl.time + 0.2; - VectorCopy (start, b->start); - VectorCopy (end, b->end); - return; - } - } - - // find a free beam - for (i = 0, b = cl.beams;i < cl.max_beams;i++, b++) - { - if (!b->model || b->endtime < cl.time) - { - b->entity = ent; - b->lightning = lightning; - b->relativestartvalid = (ent && cl.csqcentities[ent].state_current.active) ? 2 : 0; - b->model = m; - b->endtime = cl.time + 0.2; - VectorCopy (start, b->start); - VectorCopy (end, b->end); - return; - } - } - Con_Print("beam list overflow!\n"); -} - // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) void VM_CL_te_lightning1 (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_lightning1); - VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt, true); } // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) void VM_CL_te_lightning2 (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_lightning2); - VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt2, true); } // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) void VM_CL_te_lightning3 (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_lightning3); - VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_bolt3, false); } // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) void VM_CL_te_beam (void) { VM_SAFEPARMCOUNT(3, VM_CL_te_beam); - VM_CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false); + CL_NewBeam(PRVM_G_EDICTNUM(OFS_PARM0), PRVM_G_VECTOR(OFS_PARM1), PRVM_G_VECTOR(OFS_PARM2), cl.model_beam, false); } // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) diff --git a/menu.c b/menu.c index 25e2ab55..226b299a 100644 --- a/menu.c +++ b/menu.c @@ -1794,7 +1794,7 @@ static void M_Options_Key (int k, char ascii) } } -#define OPTIONS_EFFECTS_ITEMS 35 +#define OPTIONS_EFFECTS_ITEMS 36 static int options_effects_cursor; @@ -1811,8 +1811,9 @@ extern cvar_t cl_stainmaps_clearonload; extern cvar_t r_explosionclip; extern cvar_t r_coronas; extern cvar_t gl_flashblend; -extern cvar_t cl_beams_polygon; -extern cvar_t cl_beams_relative; +extern cvar_t cl_beams_polygons; +extern cvar_t cl_beams_quakepositionhack; +extern cvar_t cl_beams_instantaimhack; extern cvar_t cl_beams_lightatend; extern cvar_t r_lightningbeam_thickness; extern cvar_t r_lightningbeam_scroll; @@ -1846,7 +1847,8 @@ static void M_Menu_Options_Effects_AdjustSliders (int dir) else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_particles_blood_alpha, bound(0.2, cl_particles_blood_alpha.value + dir * 0.1, 1)); else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_particles_blood_bloodhack, !cl_particles_blood_bloodhack.integer); else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_polygons, !cl_beams_polygons.integer); - else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_relative, !cl_beams_relative.integer); + else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_instantaimhack, !cl_beams_instantaimhack.integer); + else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_quakepositionhack, !cl_beams_quakepositionhack.integer); else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&cl_beams_lightatend, !cl_beams_lightatend.integer); else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&r_lightningbeam_thickness, bound(1, r_lightningbeam_thickness.integer + dir, 10)); else if (options_effects_cursor == optnum++) Cvar_SetValueQuick (&r_lightningbeam_scroll, bound(0, r_lightningbeam_scroll.integer + dir, 10)); @@ -1898,8 +1900,9 @@ static void M_Options_Effects_Draw (void) M_Options_PrintCheckbox(" Blood", true, cl_particles_blood.integer); M_Options_PrintSlider( " Blood Opacity", true, cl_particles_blood_alpha.value, 0.2, 1); M_Options_PrintCheckbox("Force New Blood Effect", true, cl_particles_blood_bloodhack.integer); - M_Options_PrintCheckbox(" Lightning Polygons", true, cl_beams_polygons.integer); - M_Options_PrintCheckbox("Lightning Smooth Sweep", true, cl_beams_relative.integer); + M_Options_PrintCheckbox(" Polygon Lightning", true, cl_beams_polygons.integer); + M_Options_PrintCheckbox("Smooth Sweep Lightning", true, cl_beams_instantaimhack.integer); + M_Options_PrintCheckbox(" Waist-level Lightning", true, cl_beams_quakepositionhack.integer); M_Options_PrintCheckbox(" Lightning End Light", true, cl_beams_lightatend.integer); M_Options_PrintSlider( " Lightning Thickness", cl_beams_polygons.integer, r_lightningbeam_thickness.integer, 1, 10); M_Options_PrintSlider( " Lightning Scroll", cl_beams_polygons.integer, r_lightningbeam_scroll.integer, 0, 10); diff --git a/r_lightning.c b/r_lightning.c index 68f6b8f5..eabf768f 100644 --- a/r_lightning.c +++ b/r_lightning.c @@ -269,12 +269,14 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++) { const beam_t *b = cl.beams + surfacelist[surfacelistindex]; - vec3_t beamdir, right, up, offset; + vec3_t beamdir, right, up, offset, start, end; float length, t1, t2; + + CL_Beam_CalculatePositions(b, start, end); // calculate beam direction (beamdir) vector and beam length // get difference vector - VectorSubtract(b->end, b->start, beamdir); + VectorSubtract(end, start, beamdir); // find length of difference vector length = sqrt(DotProduct(beamdir, beamdir)); // calculate scale to make beamdir a unit vector (normalized) @@ -284,7 +286,7 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r // calculate up vector such that it points toward viewer, and rotates around the beamdir // get direction from start of beam to viewer - VectorSubtract(r_view.origin, b->start, up); + VectorSubtract(r_view.origin, start, up); // remove the portion of the vector that moves along the beam // (this leaves only a vector pointing directly away from the beam) t1 = -DotProduct(up, beamdir); @@ -296,7 +298,7 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r VectorNormalize(up); // calculate T coordinate scrolling (start and end texcoord along the beam) - t1 = r_refdef.time * -r_lightningbeam_scroll.value;// + beamrepeatscale * DotProduct(b->start, beamdir); + t1 = r_refdef.time * -r_lightningbeam_scroll.value;// + beamrepeatscale * DotProduct(start, beamdir); t1 = t1 - (int) t1; t2 = t1 + beamrepeatscale * length; @@ -313,15 +315,15 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r // polygon 1, verts 0-3 VectorScale(right, r_lightningbeam_thickness.value, offset); - R_CalcLightningBeamPolygonVertex3f(vertex3f + 0, b->start, b->end, offset); + R_CalcLightningBeamPolygonVertex3f(vertex3f + 0, start, end, offset); // polygon 2, verts 4-7 VectorAdd(right, up, offset); VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset); - R_CalcLightningBeamPolygonVertex3f(vertex3f + 12, b->start, b->end, offset); + R_CalcLightningBeamPolygonVertex3f(vertex3f + 12, start, end, offset); // polygon 3, verts 8-11 VectorSubtract(right, up, offset); VectorScale(offset, r_lightningbeam_thickness.value * 0.70710681f, offset); - R_CalcLightningBeamPolygonVertex3f(vertex3f + 24, b->start, b->end, offset); + R_CalcLightningBeamPolygonVertex3f(vertex3f + 24, start, end, offset); R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 0, t1, t2); R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 8, t1 + 0.33, t2 + 0.33); R_CalcLightningBeamPolygonTexCoord2f(texcoord2f + 16, t1 + 0.66, t2 + 0.66); @@ -338,11 +340,11 @@ void R_DrawLightningBeam_TransparentCallback(const entity_render_t *ent, const r } } +extern cvar_t cl_beams_polygons; void R_DrawLightningBeams(void) { int i; beam_t *b; - vec3_t org; if (!cl_beams_polygons.integer) return; @@ -350,10 +352,17 @@ void R_DrawLightningBeams(void) beamrepeatscale = 1.0f / r_lightningbeam_repeatdistance.value; for (i = 0, b = cl.beams;i < cl.num_beams;i++, b++) { - if (b->model && b->endtime >= r_refdef.time && b->lightning) + if (b->model && b->lightning) { - VectorAdd(b->start, b->end, org); - VectorScale(org, 0.5f, org); + vec3_t org, start, end, dir; + vec_t dist; + CL_Beam_CalculatePositions(b, start, end); + // calculate the nearest point on the line (beam) for depth sorting + VectorSubtract(end, start, dir); + dist = (DotProduct(r_view.origin, dir) - DotProduct(start, dir)) / (DotProduct(end, dir) - DotProduct(start, dir)); + dist = bound(0, dist, 1); + VectorLerp(start, dist, end, org); + // now we have the nearest point on the line, so sort with it R_MeshQueue_AddTransparent(org, R_DrawLightningBeam_TransparentCallback, NULL, i, NULL); } } diff --git a/todo b/todo index e692b29e..63b4e54d 100644 --- a/todo +++ b/todo @@ -56,6 +56,7 @@ 0 bug darkplaces server: the lava+func_trains room of r1m5 is leaving items floating in the air - r1m5 is Towers of Wrath, in episode of Dissolution of Eternity, aka rogue (maichal) 0 bug darkplaces video: generate 1024 color gamma ramps for glx on Quadro, right now hardware gamma is being disabled on these cards because they use 1024 color ramps, not 256 (div0) 0 bug darkplaces wgl client: during video mode setup, sometimes another application's window becomes permanently top most, not darkplaces' fullscreen window, why? (tZork) +0 bug darkplaces wgl client: hardware gamma is being retried every frame for unknown reasons, this is SEVERELY impacting framerates on win2k/xp (Jago) 0 bug darkplaces windows sound: freezing on exit sometimes when freeing sound buffer during sound shutdown (Black) 0 bug dpmod: allow selection of weapons with secondary ammo but no primary ammo, and switch away if trying to fire primary ammo you don't have (romi) 0 bug dpmod: chthon stops attacking in coop if shot enough @@ -79,8 +80,10 @@ 0 change darkplaces client: disable all possible 'cheat' things unless -developer is given on commandline, this includes r_show*, r_test, gl_lightmaps, r_fullbright 0 change darkplaces client: get image sizes from .lmp files if present 0 change darkplaces client: hardcode sbar image sizes so they can be replaced with higher quality images +0 change darkplaces client: modify cl_particles_quake to make all the engine dlights be white and look as much like quake as possible (Jago) 0 change darkplaces client: particles shouldn't be using contents checks to decide whether to die, they should use movement traces 0 change darkplaces client: restrict wateralpha and such cvars according to what is permitted in qw serverinfo? +0 change darkplaces client: turn off coronas on dlights (Jago) 0 change darkplaces extensions: edit FRIK_FILE documentation to mention that fgets uses its own separate buffer, so only one fgets can be done at a time without uzing strzone, but that darkplaces uses standard tempstrings for fgets (it doesn't - change it!) and mention DP_QC_MULTIPLETEMPSTRINGS (FrikaC) 0 change darkplaces extensions: edit FRIK_FILE documentation to mention that strcat uses its own separate buffer, and that a = strcat(a, b);a = strcat(a, c); works correctly despite this, also mention that in DP strcat uses standard tempstrings, and mention DP_QC_MULTIPLETEMPSTRINGS (FrikaC) 0 change darkplaces general: make r_speeds 2 show timings for other subsystems such as client, sound, server, network (Carni) @@ -336,6 +339,7 @@ 2 feature darkplaces loader: add support for fuhquake naming of map textures (textures/start/quake.tga style) 2 feature darkplaces menu: add some basic graphics/effects options profiles so that people can choose profiles like "Classic", "Modern", "Excessive", "Realistic", or any other profiles that make sense, may also need to reorganize the graphics/effects options menus to be a bit less confusing (Tron) 2 feature darkplaces menu: implement menu_clearkeyconfig and menu_keyconfig and the corresponding menu (diGGer) +2 feature darkplaces menu: new game custom level/mod menu, which allows you to choose a mod and browse through maps and choose starting skill, by default it would have the current mod selected and start selected (Jago) 2 feature darkplaces model: add model_exportobj console command to allow exporting a specified model as .obj (Randy) 2 feature darkplaces physics: DP_SV_QCPHYSICS extension, calls SV_PhysicsQC function, which replaces the entire SV_Physics C function, calling all thinks and physics and everything (Urre) 2 feature darkplaces protocol: .float bulge; field which makes an entity larger by moving vertices along their normals, well known as the fatboy mutator in Unreal Tournament (Wazat)