#include "image.h"
#include "csprogs.h"
#include "r_shadow.h"
+#include "libcurl.h"
// we need to declare some mouse variables here, because the menu system
// references them even when on a unix system.
cvar_t freelook = {CVAR_SAVE, "freelook", "1","mouse controls pitch instead of forward/back"};
+#ifdef AUTODEMO_BROKEN
cvar_t cl_autodemo = {0, "cl_autodemo", "0", "records every game played, using the date/time and map name to name the demo file" };
cvar_t cl_autodemo_nameformat = {0, "cl_autodemo_nameformat", "%Y-%m-%d_%H-%M", "The format of the cl_autodemo filename, followed by the map name" };
+#endif
cvar_t r_draweffects = {0, "r_draweffects", "1","renders temporary sprite effects"};
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"};
CL_Screen_NewMap();
}
+void CL_SetInfo(const char *key, const char *value, qboolean send, qboolean allowstarkey, qboolean allowmodel, qboolean quiet)
+{
+ if (strchr(key, '\"') || strchr(value, '\"') || (!allowstarkey && key[0] == '*') || (!allowmodel && (!strcasecmp(Cmd_Argv(1), "pmodel") || !strcasecmp(Cmd_Argv(1), "emodel"))))
+ {
+ if (!quiet)
+ Con_Printf("Can't setinfo \"%s\" \"%s\"\n");
+ return;
+ }
+ InfoString_SetValue(cls.userinfo, sizeof(cls.userinfo), key, value);
+ if (cls.state == ca_connected && cls.netcon)
+ {
+ if (cls.protocol == PROTOCOL_QUAKEWORLD)
+ {
+ MSG_WriteByte(&cls.netcon->message, qw_clc_stringcmd);
+ MSG_WriteString(&cls.netcon->message, va("setinfo \"%s\" \"%s\"", key, value));
+ }
+ else if (!strcasecmp(key, "name"))
+ {
+ MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+ MSG_WriteString(&cls.netcon->message, va("name \"%s\"", value));
+ }
+ else if (!strcasecmp(key, "playermodel"))
+ {
+ MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+ MSG_WriteString(&cls.netcon->message, va("playermodel \"%s\"", value));
+ }
+ else if (!strcasecmp(key, "playerskin"))
+ {
+ MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+ MSG_WriteString(&cls.netcon->message, va("playerskin \"%s\"", value));
+ }
+ else if (!strcasecmp(key, "topcolor"))
+ {
+ // don't send anything, the combined color code will be updated manually
+ }
+ else if (!strcasecmp(key, "bottomcolor"))
+ {
+ // don't send anything, the combined color code will be updated manually
+ }
+ else if (!strcasecmp(key, "rate"))
+ {
+ MSG_WriteByte(&cls.netcon->message, clc_stringcmd);
+ MSG_WriteString(&cls.netcon->message, va("rate \"%s\"", value));
+ }
+ }
+}
+
void CL_ExpandEntities(int num)
{
int i, oldmaxentities;
// stop demo loop in case this fails
CL_Disconnect();
+ // if downloads are running, cancel their finishing action
+ Curl_Clear_forthismap();
+
// make sure the client ports are open before attempting to connect
NetConn_UpdateSockets();
for (i = 0, ent = cl.entities;i < cl.num_entities;i++, ent++)
{
+ const char* modelname;
+
if (!ent->state_current.active)
continue;
if (ent->render.model)
- strlcpy (name, ent->render.model->name, 25);
+ modelname = ent->render.model->name;
else
- strcpy(name, "--no model--");
+ modelname = "--no model--";
+ strlcpy(name, modelname, 25);
for (j = (int)strlen(name);j < 25;j++)
name[j] = ' ';
Con_Printf("%3i: %s:%4i (%5i %5i %5i) [%3i %3i %3i] %4.2f %5.3f\n", i, name, ent->render.frame, (int) ent->render.matrix.m[0][3], (int) ent->render.matrix.m[1][3], (int) ent->render.matrix.m[2][3], (int) ent->render.angles[0] % 360, (int) ent->render.angles[1] % 360, (int) ent->render.angles[2] % 360, ent->render.scale, ent->render.alpha);
e->render.skinnum = e->state_current.skin;
if (e->render.flags & RENDER_VIEWMODEL && !e->state_current.tagentity)
{
- if (!r_drawviewmodel.integer || chase_active.integer || envmap)// || csqc_loaded)
+ if (!r_drawviewmodel.integer || chase_active.integer || r_refdef.envmap)// || csqc_loaded)
return;
if (!e->csqc)
{
// movement lerp
// if it's the player entity, update according to client movement
- if (e == cl.entities + cl.playerentity && cl.movement)// && !e->csqc)
+ if (e == cl.entities + cl.playerentity && cl.movement_predicted)// && !e->csqc)
{
- lerp = (cl.time - cl.mtime[1]) / (cl.mtime[0] - cl.mtime[1]);
+ lerp = (cl.time - cl.movement_time[1]) / (cl.movement_time[0] - cl.movement_time[1]);
lerp = bound(0, lerp, 1);
VectorLerp(cl.movement_oldorigin, lerp, cl.movement_origin, origin);
VectorSet(angles, 0, cl.viewangles[1], 0);
tempmatrix.m[1][3] = trace.endpos[1];
tempmatrix.m[2][3] = trace.endpos[2];
CL_AllocDlight(NULL, &tempmatrix, 100, e->persistent.muzzleflash, e->persistent.muzzleflash, e->persistent.muzzleflash, 0, 0, 0, -1, true, 0, 0.25, 0.25, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
- e->persistent.muzzleflash -= cl.frametime * 10;
+ e->persistent.muzzleflash -= (cl.time - cl.oldtime) * 10;
}
// LordHavoc: if the model has no flags, don't check each
if (e->render.model && e->render.model->flags && (!e->state_current.tagentity && !(e->render.flags & RENDER_VIEWMODEL)))
if (len > 0)
len = 1.0f / len;
VectorScale(vel, len, vel);
- len = VectorDistance(origin, e->persistent.trail_origin);
- CL_ParticleEffect(trailtype, len, e->persistent.trail_origin, origin, vel, vel, e, e->state_current.glowcolor);
+ CL_ParticleEffect(trailtype, 1, e->persistent.trail_origin, origin, vel, vel, e, e->state_current.glowcolor);
}
VectorCopy(origin, e->persistent.trail_origin);
// tenebrae's sprites are all additive mode (weird)
}
}
+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;
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 && b->entity && 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)
}
// 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;
}
// add new entities for the lightning
- VectorCopy (b->start, org);
+ VectorCopy (start, org);
d = VectorNormalizeLength(dist);
while (d > 0)
{
void CL_LerpPlayer(float frac)
{
int i;
- float d;
cl.viewzoom = cl.mviewzoom[1] + frac * (cl.mviewzoom[0] - cl.mviewzoom[1]);
for (i = 0;i < 3;i++)
cl.punchvector[i] = cl.mpunchvector[1][i] + frac * (cl.mpunchvector[0][i] - cl.mpunchvector[1][i]);
cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]);
}
-
- if (cls.demoplayback)
- {
- // interpolate the angles
- for (i = 0;i < 3;i++)
- {
- d = cl.mviewangles[0][i] - cl.mviewangles[1][i];
- if (d > 180)
- d -= 360;
- else if (d < -180)
- d += 360;
- cl.viewangles[i] = cl.mviewangles[1][i] + frac * d;
- }
- }
}
void CSQC_RelinkAllEntities (int drawmask)
{
+ cl.num_brushmodel_entities = 0;
CL_RelinkNetworkEntities(drawmask);
if(drawmask & ENTMASK_ENGINE)
{
r_refdef.time = cl.time;
r_refdef.extraupdate = !r_speeds.integer;
r_refdef.numentities = 0;
- r_refdef.viewentitymatrix = identitymatrix;
- cl.num_brushmodel_entities = 0;
+ r_view.matrix = identitymatrix;
if (cls.state == ca_connected && cls.signon == SIGNONS)
{
CL_ClientMovement_Replay();
if(!csqc_loaded) //[515]: csqc
{
+ cl.num_brushmodel_entities = 0;
CL_RelinkNetworkEntities(65535);
// move particles
// update view blend
V_CalcViewBlend();
+
+ // update the r_refdef time again because cl.time may have changed
+ r_refdef.time = cl.time;
}
return 0;
{
if (Cmd_Argc () == 1)
{
- Con_Printf("\"fog\" is \"%f %f %f %f\"\n", fog_density, fog_red, fog_green, fog_blue);
+ Con_Printf("\"fog\" is \"%f %f %f %f\"\n", r_refdef.fog_density, r_refdef.fog_red, r_refdef.fog_green, r_refdef.fog_blue);
return;
}
- fog_density = atof(Cmd_Argv(1));
- fog_red = atof(Cmd_Argv(2));
- fog_green = atof(Cmd_Argv(3));
- fog_blue = atof(Cmd_Argv(4));
+ 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));
}
/*
timestart = Sys_DoubleTime();
for (i = 0;i < 128;i++)
{
- Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], 0, i / 128.0 * 360.0, 0, 1);
+ Matrix4x4_CreateFromQuakeEntity(&r_view.matrix, r_view.origin[0], r_view.origin[1], r_view.origin[2], 0, i / 128.0 * 360.0, 0, 1);
CL_UpdateScreen();
}
timedelta = Sys_DoubleTime() - timestart;
Cmd_AddCommand ("playdemo", CL_PlayDemo_f, "watch a demo file");
Cmd_AddCommand ("timedemo", CL_TimeDemo_f, "play back a demo as fast as possible and save statistics to benchmark.log");
+#ifdef AUTODEMO_BROKEN
Cvar_RegisterVariable (&cl_autodemo);
Cvar_RegisterVariable (&cl_autodemo_nameformat);
+#endif
Cmd_AddCommand ("fog", CL_Fog_f, "set global fog parameters (density red green blue)");
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);