2009-02-28 14:41:18 +00:00
|
|
|
/*
|
2010-06-17 06:24:27 +00:00
|
|
|
* Copyright (C) 1997-2001 Id Software, Inc.
|
|
|
|
*
|
2010-07-13 18:19:42 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or (at
|
|
|
|
* your option) any later version.
|
2010-06-17 06:24:27 +00:00
|
|
|
*
|
2010-07-13 18:19:42 +00:00
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
2010-06-17 06:24:27 +00:00
|
|
|
*
|
|
|
|
* See the GNU General Public License for more details.
|
|
|
|
*
|
2010-07-13 18:19:42 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
|
|
* 02111-1307, USA.
|
2010-06-17 06:24:27 +00:00
|
|
|
*
|
2010-06-18 15:14:54 +00:00
|
|
|
* =======================================================================
|
|
|
|
*
|
|
|
|
* This file implements all static entities at client site.
|
|
|
|
*
|
|
|
|
* =======================================================================
|
2010-06-17 06:24:27 +00:00
|
|
|
*/
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-10-28 09:20:46 +00:00
|
|
|
#include <math.h>
|
2009-03-03 13:43:32 +00:00
|
|
|
#include "header/client.h"
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
extern struct model_s *cl_mod_powerscreen;
|
|
|
|
int vidref_val;
|
|
|
|
|
|
|
|
struct model_s *
|
|
|
|
S_RegisterSexedModel(entity_state_t *ent, char *base)
|
|
|
|
{
|
|
|
|
int n;
|
|
|
|
char *p;
|
|
|
|
struct model_s *md2;
|
|
|
|
char model[MAX_QPATH];
|
|
|
|
char buffer[MAX_QPATH];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* determine what model the client is using */
|
2009-02-28 14:41:18 +00:00
|
|
|
model[0] = 0;
|
|
|
|
n = CS_PLAYERSKINS + ent->number - 1;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (cl.configstrings[n][0])
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
p = strchr(cl.configstrings[n], '\\');
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (p)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
p += 1;
|
|
|
|
strcpy(model, p);
|
|
|
|
p = strchr(model, '/');
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (p)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
*p = 0;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
/* if we can't figure it out, they're male */
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!model[0])
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
strcpy(model, "male");
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
Com_sprintf(buffer, sizeof(buffer), "players/%s/%s", model, base + 1);
|
2010-06-17 06:24:27 +00:00
|
|
|
md2 = re.RegisterModel(buffer);
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (!md2)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* not found, try default weapon model */
|
2012-07-22 13:34:45 +00:00
|
|
|
Com_sprintf(buffer, sizeof(buffer), "players/%s/weapon.md2", model);
|
2010-06-17 06:24:27 +00:00
|
|
|
md2 = re.RegisterModel(buffer);
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (!md2)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* no, revert to the male model */
|
2012-07-22 13:34:45 +00:00
|
|
|
Com_sprintf(buffer, sizeof(buffer), "players/%s/%s",
|
|
|
|
"male", base + 1);
|
2010-06-17 06:24:27 +00:00
|
|
|
md2 = re.RegisterModel(buffer);
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (!md2)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* last try, default male weapon.md2 */
|
2012-07-22 13:34:45 +00:00
|
|
|
Com_sprintf(buffer, sizeof(buffer), "players/male/weapon.md2");
|
2010-06-17 06:24:27 +00:00
|
|
|
md2 = re.RegisterModel(buffer);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
return md2;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
extern int Developer_searchpath(int who);
|
|
|
|
|
|
|
|
void
|
|
|
|
CL_AddPacketEntities(frame_t *frame)
|
|
|
|
{
|
|
|
|
entity_t ent = {0};
|
|
|
|
entity_state_t *s1;
|
|
|
|
float autorotate;
|
|
|
|
int i;
|
|
|
|
int pnum;
|
|
|
|
centity_t *cent;
|
|
|
|
int autoanim;
|
|
|
|
clientinfo_t *ci;
|
|
|
|
unsigned int effects, renderfx;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* bonus items rotate at a fixed rate */
|
2012-07-22 13:34:45 +00:00
|
|
|
autorotate = anglemod(cl.time * 0.1f);
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* brush models can auto animate their frames */
|
2012-07-22 13:34:45 +00:00
|
|
|
autoanim = 2 * cl.time / 1000;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
for (pnum = 0; pnum < frame->num_entities; pnum++)
|
|
|
|
{
|
|
|
|
s1 = &cl_parse_entities[(frame->parse_entities +
|
|
|
|
pnum) & (MAX_PARSE_ENTITIES - 1)];
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
cent = &cl_entities[s1->number];
|
|
|
|
|
|
|
|
effects = s1->effects;
|
|
|
|
renderfx = s1->renderfx;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* set frame */
|
2009-02-28 14:41:18 +00:00
|
|
|
if (effects & EF_ANIM01)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.frame = autoanim & 1;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else if (effects & EF_ANIM23)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.frame = 2 + (autoanim & 1);
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else if (effects & EF_ANIM_ALL)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.frame = autoanim;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else if (effects & EF_ANIM_ALLFAST)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.frame = cl.time / 100;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.frame = s1->frame;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* quad and pent can do different things on client */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_PENT)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
effects &= ~EF_PENT;
|
|
|
|
effects |= EF_COLOR_SHELL;
|
|
|
|
renderfx |= RF_SHELL_RED;
|
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_QUAD)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
effects &= ~EF_QUAD;
|
|
|
|
effects |= EF_COLOR_SHELL;
|
|
|
|
renderfx |= RF_SHELL_BLUE;
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_DOUBLE)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
effects &= ~EF_DOUBLE;
|
|
|
|
effects |= EF_COLOR_SHELL;
|
|
|
|
renderfx |= RF_SHELL_DOUBLE;
|
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_HALF_DAMAGE)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
effects &= ~EF_HALF_DAMAGE;
|
|
|
|
effects |= EF_COLOR_SHELL;
|
|
|
|
renderfx |= RF_SHELL_HALF_DAM;
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.oldframe = cent->prev.frame;
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.backlerp = 1.0f - cl.lerpfrac;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (renderfx & (RF_FRAMELERP | RF_BEAM))
|
|
|
|
{
|
|
|
|
/* step origin discretely, because the
|
|
|
|
frames do the animation properly */
|
|
|
|
VectorCopy(cent->current.origin, ent.origin);
|
|
|
|
VectorCopy(cent->current.old_origin, ent.oldorigin);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* interpolate origin */
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac *
|
2012-07-22 13:34:45 +00:00
|
|
|
(cent->current.origin[i] - cent->prev.origin[i]);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* tweak the color of beams */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (renderfx & RF_BEAM)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* the four beam colors are encoded in 32 bits of skinnum (hack) */
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.30f;
|
2012-07-22 13:34:45 +00:00
|
|
|
ent.skinnum = (s1->skinnum >> ((randk() % 4) * 8)) & 0xff;
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = NULL;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* set skin */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (s1->modelindex == 255)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* use custom player skin */
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.skinnum = 0;
|
|
|
|
ci = &cl.clientinfo[s1->skinnum & 0xff];
|
|
|
|
ent.skin = ci->skin;
|
|
|
|
ent.model = ci->model;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (!ent.skin || !ent.model)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.skin = cl.baseclientinfo.skin;
|
|
|
|
ent.model = cl.baseclientinfo.model;
|
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (renderfx & RF_USE_DISGUISE)
|
|
|
|
{
|
|
|
|
if (ent.skin != NULL)
|
|
|
|
{
|
|
|
|
if (!strncmp((char *)ent.skin, "players/male", 12))
|
|
|
|
{
|
|
|
|
ent.skin = re.RegisterSkin("players/male/disguise.pcx");
|
|
|
|
ent.model = re.RegisterModel("players/male/tris.md2");
|
|
|
|
}
|
|
|
|
else if (!strncmp((char *)ent.skin, "players/female", 14))
|
|
|
|
{
|
|
|
|
ent.skin = re.RegisterSkin("players/female/disguise.pcx");
|
|
|
|
ent.model = re.RegisterModel("players/female/tris.md2");
|
|
|
|
}
|
|
|
|
else if (!strncmp((char *)ent.skin, "players/cyborg", 14))
|
|
|
|
{
|
|
|
|
ent.skin = re.RegisterSkin("players/cyborg/disguise.pcx");
|
|
|
|
ent.model = re.RegisterModel("players/cyborg/tris.md2");
|
2010-02-20 07:48:37 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.skinnum = s1->skinnum;
|
|
|
|
ent.skin = NULL;
|
|
|
|
ent.model = cl.model_draw[s1->modelindex];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* only used for black hole model right now */
|
|
|
|
if (renderfx & RF_TRANSLUCENT && !(renderfx & RF_BEAM))
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.70f;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* render effects (fullbright, translucent, etc) */
|
2009-02-28 14:41:18 +00:00
|
|
|
if ((effects & EF_COLOR_SHELL))
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
ent.flags = 0; /* renderfx go on color shell entity */
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.flags = renderfx;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* calculate angles */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_ROTATE)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* some bonus items auto-rotate */
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.angles[0] = 0;
|
|
|
|
ent.angles[1] = autorotate;
|
|
|
|
ent.angles[2] = 0;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else if (effects & EF_SPINNINGLIGHTS)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.angles[0] = 0;
|
2012-07-22 13:34:45 +00:00
|
|
|
ent.angles[1] = anglemod(cl.time / 2) + s1->angles[1];
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.angles[2] = 180;
|
|
|
|
{
|
|
|
|
vec3_t forward;
|
|
|
|
vec3_t start;
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
AngleVectors(ent.angles, forward, NULL, NULL);
|
|
|
|
VectorMA(ent.origin, 64, forward, start);
|
|
|
|
V_AddLight(start, 100, 1, 0, 0);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* interpolate angles */
|
2012-07-22 13:34:45 +00:00
|
|
|
float a1, a2;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
a1 = cent->current.angles[i];
|
|
|
|
a2 = cent->prev.angles[i];
|
2012-07-22 13:34:45 +00:00
|
|
|
ent.angles[i] = LerpAngle(a2, a1, cl.lerpfrac);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (s1->number == cl.playernum + 1)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
ent.flags |= RF_VIEWERMODEL;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
if (effects & EF_FLAG1)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 225, 1.0f, 0.1f, 0.1f);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else if (effects & EF_FLAG2)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 225, 0.1f, 0.1f, 1.0f);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
else if (effects & EF_TAGTRAIL)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 225, 1.0f, 1.0f, 0.0f);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
else if (effects & EF_TRACKERTRAIL)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 225, -1.0f, -1.0f, -1.0f);
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* if set to invisible, skip */
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!s1->modelindex)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
continue;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_BFG)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.flags |= RF_TRANSLUCENT;
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.30f;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_PLASMA)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.flags |= RF_TRANSLUCENT;
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.6f;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_SPHERETRANS)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.flags |= RF_TRANSLUCENT;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (effects & EF_TRACKERTRAIL)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.6f;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.3f;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* add to refresh list */
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddEntity(&ent);
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* color shells generate a seperate entity for the main model */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_COLOR_SHELL)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* all of the solo colors are fine. we need to catch any of
|
2012-07-22 13:34:45 +00:00
|
|
|
the combinations that look bad (double & half) and turn
|
|
|
|
them into the appropriate color, and make double/quad
|
|
|
|
something special */
|
|
|
|
if (renderfx & RF_SHELL_HALF_DAM)
|
|
|
|
{
|
|
|
|
if (Developer_searchpath(2) == 2)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* ditch the half damage shell if any of red, blue, or double are on */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (renderfx & (RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE))
|
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
renderfx &= ~RF_SHELL_HALF_DAM;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2009-02-28 17:39:51 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (renderfx & RF_SHELL_DOUBLE)
|
|
|
|
{
|
|
|
|
if (Developer_searchpath(2) == 2)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* lose the yellow shell if we have a red, blue, or green shell */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (renderfx & (RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_GREEN))
|
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
renderfx &= ~RF_SHELL_DOUBLE;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
/* if we have a red shell, turn it to purple by adding blue */
|
2009-02-28 17:39:51 +00:00
|
|
|
if (renderfx & RF_SHELL_RED)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
renderfx |= RF_SHELL_BLUE;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
/* if we have a blue shell (and not a red shell),
|
|
|
|
turn it to cyan by adding green */
|
|
|
|
else if (renderfx & RF_SHELL_BLUE)
|
|
|
|
{
|
|
|
|
/* go to green if it's on already,
|
|
|
|
otherwise do cyan (flash green) */
|
2009-02-28 17:39:51 +00:00
|
|
|
if (renderfx & RF_SHELL_GREEN)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
renderfx &= ~RF_SHELL_BLUE;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 17:39:51 +00:00
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
renderfx |= RF_SHELL_GREEN;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-28 17:39:51 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.flags = renderfx | RF_TRANSLUCENT;
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.30f;
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddEntity(&ent);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
ent.skin = NULL; /* never use a custom skin on others */
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.skinnum = 0;
|
|
|
|
ent.flags = 0;
|
|
|
|
ent.alpha = 0;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* duplicate for linked models */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (s1->modelindex2)
|
|
|
|
{
|
|
|
|
if (s1->modelindex2 == 255)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* custom weapon */
|
2009-02-28 14:41:18 +00:00
|
|
|
ci = &cl.clientinfo[s1->skinnum & 0xff];
|
2010-06-17 06:24:27 +00:00
|
|
|
i = (s1->skinnum >> 8); /* 0 is default weapon model */
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (!cl_vwep->value || (i > MAX_CLIENTWEAPONMODELS - 1))
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
i = 0;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = ci->weaponmodel[i];
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (!ent.model)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
if (i != 0)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = ci->weaponmodel[0];
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!ent.model)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl.baseclientinfo.weaponmodel[0];
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl.model_draw[s1->modelindex2];
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* check for the defender sphere shell and make it translucent */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (!Q_strcasecmp(cl.configstrings[CS_MODELS + (s1->modelindex2)],
|
|
|
|
"models/items/shell/tris.md2"))
|
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.32f;
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.flags = RF_TRANSLUCENT;
|
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddEntity(&ent);
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
ent.flags = 0;
|
|
|
|
ent.alpha = 0;
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (s1->modelindex3)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl.model_draw[s1->modelindex3];
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddEntity(&ent);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (s1->modelindex4)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl.model_draw[s1->modelindex4];
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddEntity(&ent);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_POWERSCREEN)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl_mod_powerscreen;
|
|
|
|
ent.oldframe = 0;
|
|
|
|
ent.frame = 0;
|
|
|
|
ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN);
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.30f;
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddEntity(&ent);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* add automatic particle trails */
|
2012-07-22 13:34:45 +00:00
|
|
|
if ((effects & ~EF_ROTATE))
|
|
|
|
{
|
|
|
|
if (effects & EF_ROCKET)
|
|
|
|
{
|
|
|
|
CL_RocketTrail(cent->lerp_origin, ent.origin, cent);
|
|
|
|
V_AddLight(ent.origin, 200, 1, 0.25f, 0);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
/* Do not reorder EF_BLASTER and EF_HYPERBLASTER.
|
2012-07-22 13:34:45 +00:00
|
|
|
EF_BLASTER | EF_TRACKER is a special case for
|
|
|
|
EF_BLASTER2 */
|
|
|
|
else if (effects & EF_BLASTER)
|
|
|
|
{
|
|
|
|
if (effects & EF_TRACKER)
|
|
|
|
{
|
|
|
|
CL_BlasterTrail2(cent->lerp_origin, ent.origin);
|
|
|
|
V_AddLight(ent.origin, 200, 0, 1, 0);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2012-07-22 13:34:45 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
CL_BlasterTrail(cent->lerp_origin, ent.origin);
|
|
|
|
V_AddLight(ent.origin, 200, 1, 1, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (effects & EF_HYPERBLASTER)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
if (effects & EF_TRACKER)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 200, 0, 1, 0);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 200, 1, 1, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (effects & EF_GIB)
|
|
|
|
{
|
|
|
|
CL_DiminishingTrail(cent->lerp_origin, ent.origin,
|
|
|
|
cent, effects);
|
|
|
|
}
|
|
|
|
else if (effects & EF_GRENADE)
|
|
|
|
{
|
|
|
|
CL_DiminishingTrail(cent->lerp_origin, ent.origin,
|
|
|
|
cent, effects);
|
|
|
|
}
|
|
|
|
else if (effects & EF_FLIES)
|
|
|
|
{
|
|
|
|
CL_FlyEffect(cent, ent.origin);
|
|
|
|
}
|
|
|
|
else if (effects & EF_BFG)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75};
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (effects & EF_ANIM_ALLFAST)
|
|
|
|
{
|
|
|
|
CL_BfgParticles(&ent);
|
2009-02-28 14:41:18 +00:00
|
|
|
i = 200;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
i = bfg_lightramp[s1->frame];
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddLight(ent.origin, i, 0, 1, 0);
|
|
|
|
}
|
|
|
|
else if (effects & EF_TRAP)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.origin[2] += 32;
|
2012-07-22 13:34:45 +00:00
|
|
|
CL_TrapParticles(&ent);
|
|
|
|
i = (randk() % 100) + 100;
|
|
|
|
V_AddLight(ent.origin, i, 1, 0.8f, 0.1f);
|
|
|
|
}
|
|
|
|
else if (effects & EF_FLAG1)
|
|
|
|
{
|
|
|
|
CL_FlagTrail(cent->lerp_origin, ent.origin, 242);
|
|
|
|
V_AddLight(ent.origin, 225, 1, 0.1f, 0.1f);
|
|
|
|
}
|
|
|
|
else if (effects & EF_FLAG2)
|
|
|
|
{
|
|
|
|
CL_FlagTrail(cent->lerp_origin, ent.origin, 115);
|
|
|
|
V_AddLight(ent.origin, 225, 0.1f, 0.1f, 1);
|
|
|
|
}
|
|
|
|
else if (effects & EF_TAGTRAIL)
|
|
|
|
{
|
|
|
|
CL_TagTrail(cent->lerp_origin, ent.origin, 220);
|
|
|
|
V_AddLight(ent.origin, 225, 1.0, 1.0, 0.0);
|
|
|
|
}
|
|
|
|
else if (effects & EF_TRACKERTRAIL)
|
|
|
|
{
|
|
|
|
if (effects & EF_TRACKER)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
float intensity;
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
intensity = 50 + (500 * ((float)sin(cl.time / 500.0f) + 1.0f));
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (vidref_val == VIDREF_GL)
|
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, intensity, -1.0, -1.0, -1.0);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, -1.0f * intensity,
|
|
|
|
1.0f, 1.0f, 1.0f);
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
CL_Tracker_Shell(cent->lerp_origin);
|
|
|
|
V_AddLight(ent.origin, 155, -1.0, -1.0, -1.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (effects & EF_TRACKER)
|
|
|
|
{
|
|
|
|
CL_TrackerTrail(cent->lerp_origin, ent.origin, 0);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (vidref_val == VIDREF_GL)
|
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 200, -1, -1, -1);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, -200, 1, 1, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (effects & EF_IONRIPPER)
|
|
|
|
{
|
|
|
|
CL_IonripperTrail(cent->lerp_origin, ent.origin);
|
|
|
|
V_AddLight(ent.origin, 100, 1, 0.5, 0.5);
|
|
|
|
}
|
|
|
|
else if (effects & EF_BLUEHYPERBLASTER)
|
|
|
|
{
|
|
|
|
V_AddLight(ent.origin, 200, 0, 0, 1);
|
|
|
|
}
|
|
|
|
else if (effects & EF_PLASMA)
|
|
|
|
{
|
|
|
|
if (effects & EF_ANIM_ALLFAST)
|
|
|
|
{
|
|
|
|
CL_BlasterTrail(cent->lerp_origin, ent.origin);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
V_AddLight(ent.origin, 130, 1, 0.5, 0.5);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
VectorCopy(ent.origin, cent->lerp_origin);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
void
|
|
|
|
CL_AddViewWeapon(player_state_t *ps, player_state_t *ops)
|
|
|
|
{
|
|
|
|
entity_t gun = {0}; /* view model */
|
|
|
|
int i;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* allow the gun to be completely removed */
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!cl_gun->value)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* don't draw gun if in wide angle view and drawing not forced */
|
2009-02-28 14:41:18 +00:00
|
|
|
if (ps->fov > 90)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-10-04 12:32:44 +00:00
|
|
|
if (cl_gun->value < 2)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-10-04 12:32:44 +00:00
|
|
|
return;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
if (gun_model)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
gun.model = gun_model;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
gun.model = cl.model_draw[ps->gunindex];
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!gun.model)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* set up gun position */
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i]
|
2012-07-22 13:34:45 +00:00
|
|
|
+ cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
|
|
|
|
gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle(ops->gunangles[i],
|
|
|
|
ps->gunangles[i], cl.lerpfrac);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (gun_frame)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
gun.frame = gun_frame;
|
|
|
|
gun.oldframe = gun_frame;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
gun.frame = ps->gunframe;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (gun.frame == 0)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
gun.oldframe = 0; /* just changed weapons, don't lerp from old */
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
gun.oldframe = ops->gunframe;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
|
2009-02-28 17:39:51 +00:00
|
|
|
gun.backlerp = 1.0f - cl.lerpfrac;
|
2012-07-22 13:34:45 +00:00
|
|
|
VectorCopy(gun.origin, gun.oldorigin); /* don't lerp at all */
|
|
|
|
V_AddEntity(&gun);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2012-10-28 09:20:46 +00:00
|
|
|
/*
|
|
|
|
* Adapts a 4:3 aspect FOV to the current aspect (Hor+)
|
|
|
|
*/
|
|
|
|
static inline float
|
|
|
|
AdaptFov(float fov, float w, float h)
|
|
|
|
{
|
|
|
|
static const float pi = M_PI; /* float instead of double */
|
|
|
|
|
|
|
|
if (w <= 0 || h <= 0)
|
|
|
|
return fov;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Formula:
|
|
|
|
*
|
|
|
|
* fov = 2.0 * atan(width / height * 3.0 / 4.0 * tan(fov43 / 2.0))
|
|
|
|
*
|
|
|
|
* The code below is equivalent but precalculates a few values and
|
|
|
|
* converts between degrees and radians when needed.
|
|
|
|
*/
|
|
|
|
return (atanf(tanf(fov / 360.0f * pi) * (w / h * 0.75f)) / pi * 360.0f);
|
|
|
|
}
|
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
/*
|
2010-06-17 06:24:27 +00:00
|
|
|
* Sets cl.refdef view values
|
|
|
|
*/
|
2012-07-22 13:34:45 +00:00
|
|
|
void
|
|
|
|
CL_CalcViewValues(void)
|
|
|
|
{
|
|
|
|
int i;
|
2012-10-28 09:20:46 +00:00
|
|
|
float lerp, backlerp, ifov;
|
2012-07-22 13:34:45 +00:00
|
|
|
frame_t *oldframe;
|
|
|
|
player_state_t *ps, *ops;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* find the previous frame to interpolate from */
|
2009-02-28 14:41:18 +00:00
|
|
|
ps = &cl.frame.playerstate;
|
|
|
|
i = (cl.frame.serverframe - 1) & UPDATE_MASK;
|
|
|
|
oldframe = &cl.frames[i];
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if ((oldframe->serverframe != cl.frame.serverframe - 1) || !oldframe->valid)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
oldframe = &cl.frame; /* previous frame was dropped or invalid */
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
ops = &oldframe->playerstate;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* see if the player entity was teleported this frame */
|
2012-07-22 13:34:45 +00:00
|
|
|
if ((fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256 * 8) ||
|
|
|
|
(abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256 * 8) ||
|
|
|
|
(abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256 * 8))
|
|
|
|
{
|
|
|
|
ops = ps; /* don't interpolate */
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
lerp = cl.lerpfrac;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* calculate the origin */
|
2012-07-22 13:34:45 +00:00
|
|
|
if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* use predicted values */
|
2012-07-22 13:34:45 +00:00
|
|
|
unsigned delta;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2009-02-28 17:39:51 +00:00
|
|
|
backlerp = 1.0f - lerp;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i]
|
2012-07-22 13:34:45 +00:00
|
|
|
+ cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i])
|
|
|
|
- backlerp * cl.prediction_error[i];
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* smooth out stair climbing */
|
2009-02-28 14:41:18 +00:00
|
|
|
delta = cls.realtime - cl.predicted_step_time;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (delta < 100)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* just use interpolated values */
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
cl.refdef.vieworg[i] = ops->pmove.origin[i] * 0.125 +
|
|
|
|
ops->viewoffset[i] + lerp * (ps->pmove.origin[i] * 0.125 +
|
|
|
|
ps->viewoffset[i] - (ops->pmove.origin[i] * 0.125 +
|
|
|
|
ops->viewoffset[i]));
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* if not running a demo or on a locked frame, add the local angle movement */
|
2012-07-22 13:34:45 +00:00
|
|
|
if (cl.frame.playerstate.pmove.pm_type < PM_DEAD)
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* use predicted values */
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
cl.refdef.viewangles[i] = cl.predicted_angles[i];
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2010-06-17 06:24:27 +00:00
|
|
|
/* just use interpolated values */
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
cl.refdef.viewangles[i] = LerpAngle(ops->viewangles[i],
|
|
|
|
ps->viewangles[i], lerp);
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 3; i++)
|
|
|
|
{
|
|
|
|
cl.refdef.viewangles[i] += LerpAngle(ops->kick_angles[i],
|
|
|
|
ps->kick_angles[i], lerp);
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
AngleVectors(cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up);
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* interpolate field of view */
|
2012-10-28 09:20:46 +00:00
|
|
|
ifov = ops->fov + lerp * (ps->fov - ops->fov);
|
|
|
|
if (horplus->value)
|
|
|
|
{
|
|
|
|
cl.refdef.fov_x = AdaptFov(ifov, cl.refdef.width, cl.refdef.height);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cl.refdef.fov_x = ifov;
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* don't interpolate blend color */
|
2012-07-22 13:34:45 +00:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
cl.refdef.blend[i] = ps->blend[i];
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* add the weapon */
|
2012-07-22 13:34:45 +00:00
|
|
|
CL_AddViewWeapon(ps, ops);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-17 06:24:27 +00:00
|
|
|
* Emits all entities, particles, and lights to the refresh
|
|
|
|
*/
|
2012-07-22 13:34:45 +00:00
|
|
|
void
|
|
|
|
CL_AddEntities(void)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
if (cls.state != ca_active)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
return;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
if (cl.time > cl.frame.servertime)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
if (cl_showclamp->value)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
Com_Printf("high clamp %i\n", cl.time - cl.frame.servertime);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
cl.time = cl.frame.servertime;
|
|
|
|
cl.lerpfrac = 1.0;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else if (cl.time < cl.frame.servertime - 100)
|
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
if (cl_showclamp->value)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
|
|
|
Com_Printf("low clamp %i\n", cl.frame.servertime - 100 - cl.time);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
cl.time = cl.frame.servertime - 100;
|
|
|
|
cl.lerpfrac = 0;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-02-28 17:39:51 +00:00
|
|
|
cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01f;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
if (cl_timedemo->value)
|
2012-07-22 13:34:45 +00:00
|
|
|
{
|
2009-02-28 14:41:18 +00:00
|
|
|
cl.lerpfrac = 1.0;
|
2012-07-22 13:34:45 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2012-07-22 13:34:45 +00:00
|
|
|
CL_CalcViewValues();
|
|
|
|
CL_AddPacketEntities(&cl.frame);
|
|
|
|
CL_AddTEnts();
|
|
|
|
CL_AddParticles();
|
|
|
|
CL_AddDLights();
|
|
|
|
CL_AddLightStyles();
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-17 06:24:27 +00:00
|
|
|
* Called to get the sound spatialization origin
|
|
|
|
*/
|
2012-07-22 13:34:45 +00:00
|
|
|
void
|
|
|
|
CL_GetEntitySoundOrigin(int ent, vec3_t org)
|
|
|
|
{
|
|
|
|
centity_t *old;
|
|
|
|
|
|
|
|
if ((ent < 0) || (ent >= MAX_EDICTS))
|
|
|
|
{
|
|
|
|
Com_Error(ERR_DROP, "CL_GetEntitySoundOrigin: bad ent");
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
old = &cl_entities[ent];
|
2012-07-22 13:34:45 +00:00
|
|
|
VectorCopy(old->lerp_origin, org);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2012-07-22 13:34:45 +00:00
|
|
|
|