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
|
|
|
|
2009-03-03 13:43:32 +00:00
|
|
|
#include "header/client.h"
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
extern struct model_s *cl_mod_powerscreen;
|
|
|
|
int vidref_val;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
struct model_s *S_RegisterSexedModel (entity_state_t *ent, char *base) {
|
2009-02-28 14:41:18 +00:00
|
|
|
int n;
|
|
|
|
char *p;
|
2010-06-17 06:24:27 +00:00
|
|
|
struct model_s *md2;
|
2009-02-28 14:41:18 +00:00
|
|
|
char model[MAX_QPATH];
|
|
|
|
char buffer[MAX_QPATH];
|
|
|
|
|
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
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
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)
|
|
|
|
*p = 0;
|
|
|
|
}
|
|
|
|
}
|
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])
|
|
|
|
strcpy(model, "male");
|
|
|
|
|
|
|
|
Com_sprintf (buffer, sizeof(buffer), "players/%s/%s", model, base+1);
|
2010-06-17 06:24:27 +00:00
|
|
|
md2 = re.RegisterModel(buffer);
|
|
|
|
|
|
|
|
if (!md2) {
|
|
|
|
/* not found, try default weapon model */
|
2009-02-28 14:41:18 +00:00
|
|
|
Com_sprintf (buffer, sizeof(buffer), "players/%s/weapon.md2", model);
|
2010-06-17 06:24:27 +00:00
|
|
|
md2 = re.RegisterModel(buffer);
|
|
|
|
|
|
|
|
if (!md2) {
|
|
|
|
/* no, revert to the male model */
|
2009-02-28 14:41:18 +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);
|
|
|
|
|
|
|
|
if (!md2) {
|
|
|
|
/* last try, default male weapon.md2 */
|
2009-02-28 14:41:18 +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
|
|
|
}
|
|
|
|
|
|
|
|
extern int Developer_searchpath (int who);
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
void CL_AddPacketEntities (frame_t *frame) {
|
2009-02-28 17:39:51 +00:00
|
|
|
entity_t ent = {0};
|
2009-02-28 14:41:18 +00:00
|
|
|
entity_state_t *s1;
|
|
|
|
float autorotate;
|
|
|
|
int i;
|
|
|
|
int pnum;
|
|
|
|
centity_t *cent;
|
|
|
|
int autoanim;
|
|
|
|
clientinfo_t *ci;
|
|
|
|
unsigned int effects, renderfx;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* bonus items rotate at a fixed rate */
|
2009-02-28 17:39:51 +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 */
|
2009-02-28 14:41:18 +00:00
|
|
|
autoanim = 2*cl.time/1000;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
for (pnum = 0 ; pnum<frame->num_entities ; pnum++) {
|
2009-02-28 14:41:18 +00:00
|
|
|
s1 = &cl_parse_entities[(frame->parse_entities+pnum)&(MAX_PARSE_ENTITIES-1)];
|
|
|
|
|
|
|
|
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)
|
|
|
|
ent.frame = autoanim & 1;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else if (effects & EF_ANIM23)
|
|
|
|
ent.frame = 2 + (autoanim & 1);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else if (effects & EF_ANIM_ALL)
|
|
|
|
ent.frame = autoanim;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else if (effects & EF_ANIM_ALLFAST)
|
|
|
|
ent.frame = cl.time / 100;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
|
|
|
ent.frame = s1->frame;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* quad and pent can do different things on client */
|
|
|
|
if (effects & EF_PENT) {
|
2009-02-28 14:41:18 +00:00
|
|
|
effects &= ~EF_PENT;
|
|
|
|
effects |= EF_COLOR_SHELL;
|
|
|
|
renderfx |= RF_SHELL_RED;
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +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
|
|
|
|
|
|
|
if (effects & EF_DOUBLE) {
|
2009-02-28 14:41:18 +00:00
|
|
|
effects &= ~EF_DOUBLE;
|
|
|
|
effects |= EF_COLOR_SHELL;
|
|
|
|
renderfx |= RF_SHELL_DOUBLE;
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +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
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
if (renderfx & (RF_FRAMELERP|RF_BEAM)) {
|
|
|
|
/* step origin discretely, because the frames
|
|
|
|
* do the animation properly */
|
2009-02-28 14:41:18 +00:00
|
|
|
VectorCopy (cent->current.origin, ent.origin);
|
|
|
|
VectorCopy (cent->current.old_origin, ent.oldorigin);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/* interpolate origin */
|
|
|
|
for (i=0 ; i<3 ; i++) {
|
|
|
|
ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac *
|
|
|
|
(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 */
|
|
|
|
if ( renderfx & RF_BEAM ) {
|
|
|
|
/* 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-06-02 09:55:12 +00:00
|
|
|
ent.skinnum = (s1->skinnum >> ((randk() % 4)*8)) & 0xff;
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = NULL;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/* set skin */
|
|
|
|
if (s1->modelindex == 255) {
|
|
|
|
/* 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
|
|
|
|
|
|
|
if (!ent.skin || !ent.model) {
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.skin = cl.baseclientinfo.skin;
|
|
|
|
ent.model = cl.baseclientinfo.model;
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
if (renderfx & RF_USE_DISGUISE) {
|
|
|
|
if (ent.skin != NULL) {
|
|
|
|
if(!strncmp((char *)ent.skin, "players/male", 12)) {
|
2010-02-20 07:48:37 +00:00
|
|
|
ent.skin = re.RegisterSkin ("players/male/disguise.pcx");
|
|
|
|
ent.model = re.RegisterModel ("players/male/tris.md2");
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if(!strncmp((char *)ent.skin, "players/female", 14)) {
|
2010-02-20 07:48:37 +00:00
|
|
|
ent.skin = re.RegisterSkin ("players/female/disguise.pcx");
|
|
|
|
ent.model = re.RegisterModel ("players/female/tris.md2");
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if(!strncmp((char *)ent.skin, "players/cyborg", 14)) {
|
2010-02-20 07:48:37 +00:00
|
|
|
ent.skin = re.RegisterSkin ("players/cyborg/disguise.pcx");
|
|
|
|
ent.model = re.RegisterModel ("players/cyborg/tris.md2");
|
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
}
|
2010-06-17 06:24:27 +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))
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.70f;
|
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))
|
2010-06-17 06:24:27 +00:00
|
|
|
ent.flags = 0; /* renderfx go on color shell entity */
|
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
|
|
|
ent.flags = renderfx;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* calculate angles */
|
|
|
|
if (effects & EF_ROTATE) {
|
|
|
|
/* 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;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_SPINNINGLIGHTS) {
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.angles[0] = 0;
|
|
|
|
ent.angles[1] = anglemod(cl.time/2) + s1->angles[1];
|
|
|
|
ent.angles[2] = 180;
|
|
|
|
{
|
|
|
|
vec3_t forward;
|
|
|
|
vec3_t start;
|
|
|
|
|
|
|
|
AngleVectors (ent.angles, forward, NULL, NULL);
|
|
|
|
VectorMA (ent.origin, 64, forward, start);
|
|
|
|
V_AddLight (start, 100, 1, 0, 0);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/* interpolate angles */
|
2009-02-28 14:41:18 +00:00
|
|
|
float a1, a2;
|
|
|
|
|
2010-06-17 06:24:27 +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];
|
|
|
|
ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
if (s1->number == cl.playernum+1) {
|
|
|
|
ent.flags |= RF_VIEWERMODEL;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
if (effects & EF_FLAG1)
|
2009-03-01 11:40:49 +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)
|
2009-03-01 11:40:49 +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)
|
|
|
|
V_AddLight (ent.origin, 225, 1.0f, 1.0f, 0.0f);
|
|
|
|
|
|
|
|
else if (effects & EF_TRACKERTRAIL)
|
|
|
|
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)
|
|
|
|
continue;
|
|
|
|
|
2010-06-17 06:24:27 +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
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +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
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +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)
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.6f;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
2009-02-28 17:39:51 +00:00
|
|
|
ent.alpha = 0.3f;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* add to refresh list */
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddEntity (&ent);
|
|
|
|
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* color shells generate a seperate entity for the main model */
|
|
|
|
if (effects & EF_COLOR_SHELL) {
|
|
|
|
/* all of the solo colors are fine. we need to catch any of
|
|
|
|
* 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) {
|
|
|
|
/* ditch the half damage shell if any of red, blue, or double are on */
|
2009-02-28 17:39:51 +00:00
|
|
|
if (renderfx & (RF_SHELL_RED|RF_SHELL_BLUE|RF_SHELL_DOUBLE))
|
|
|
|
renderfx &= ~RF_SHELL_HALF_DAM;
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
2009-02-28 17:39:51 +00:00
|
|
|
}
|
2009-02-28 14:41:18 +00:00
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
if (renderfx & RF_SHELL_DOUBLE) {
|
|
|
|
if(Developer_searchpath(2) == 2) {
|
|
|
|
/* lose the yellow shell if we have a red, blue, or green shell */
|
2009-02-28 17:39:51 +00:00
|
|
|
if (renderfx & (RF_SHELL_RED|RF_SHELL_BLUE|RF_SHELL_GREEN))
|
|
|
|
renderfx &= ~RF_SHELL_DOUBLE;
|
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)
|
|
|
|
renderfx |= RF_SHELL_BLUE;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
/* if we have a blue shell (and not a red shell), turn it to cyan by adding green */
|
2009-02-28 17:39:51 +00:00
|
|
|
else if (renderfx & RF_SHELL_BLUE) {
|
2010-06-17 06:24:27 +00:00
|
|
|
/* 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)
|
|
|
|
renderfx &= ~RF_SHELL_BLUE;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 17:39:51 +00:00
|
|
|
else
|
|
|
|
renderfx |= RF_SHELL_GREEN;
|
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;
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddEntity (&ent);
|
|
|
|
}
|
|
|
|
|
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 */
|
|
|
|
if (s1->modelindex2) {
|
|
|
|
if (s1->modelindex2 == 255) {
|
|
|
|
/* 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 */
|
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!cl_vwep->value || i > MAX_CLIENTWEAPONMODELS - 1)
|
|
|
|
i = 0;
|
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
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!ent.model) {
|
|
|
|
if (i != 0)
|
|
|
|
ent.model = ci->weaponmodel[0];
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!ent.model)
|
|
|
|
ent.model = cl.baseclientinfo.weaponmodel[0];
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl.model_draw[s1->modelindex2];
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* check for the defender sphere shell and make it translucent */
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
V_AddEntity (&ent);
|
|
|
|
|
|
|
|
ent.flags = 0;
|
|
|
|
ent.alpha = 0;
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
if (s1->modelindex3) {
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl.model_draw[s1->modelindex3];
|
|
|
|
V_AddEntity (&ent);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
if (s1->modelindex4) {
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.model = cl.model_draw[s1->modelindex4];
|
|
|
|
V_AddEntity (&ent);
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +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;
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddEntity (&ent);
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* add automatic particle trails */
|
|
|
|
if ( (effects&~EF_ROTATE) ) {
|
|
|
|
if (effects & EF_ROCKET) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_RocketTrail (cent->lerp_origin, ent.origin, cent);
|
2009-02-28 17:39:51 +00:00
|
|
|
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.
|
|
|
|
* EF_BLASTER | EF_TRACKER is a special case for
|
|
|
|
* EF_BLASTER2 */
|
|
|
|
else if (effects & EF_BLASTER) {
|
|
|
|
if (effects & EF_TRACKER) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_BlasterTrail2 (cent->lerp_origin, ent.origin);
|
2010-06-17 06:24:27 +00:00
|
|
|
V_AddLight (ent.origin, 200, 0, 1, 0);
|
|
|
|
|
|
|
|
} else {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_BlasterTrail (cent->lerp_origin, ent.origin);
|
|
|
|
V_AddLight (ent.origin, 200, 1, 1, 0);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_HYPERBLASTER) {
|
|
|
|
if (effects & EF_TRACKER)
|
|
|
|
V_AddLight (ent.origin, 200, 0, 1, 0);
|
|
|
|
|
|
|
|
else
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddLight (ent.origin, 200, 1, 1, 0);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} 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) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_FlyEffect (cent, ent.origin);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_BFG) {
|
2009-02-28 14:41:18 +00:00
|
|
|
static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75};
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
if (effects & EF_ANIM_ALLFAST) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_BfgParticles (&ent);
|
|
|
|
i = 200;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else {
|
2009-02-28 14:41:18 +00:00
|
|
|
i = bfg_lightramp[s1->frame];
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddLight (ent.origin, i, 0, 1, 0);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_TRAP) {
|
2009-02-28 14:41:18 +00:00
|
|
|
ent.origin[2] += 32;
|
|
|
|
CL_TrapParticles (&ent);
|
2012-06-02 09:55:12 +00:00
|
|
|
i = (randk()%100) + 100;
|
2009-03-01 11:40:49 +00:00
|
|
|
V_AddLight (ent.origin, i, 1, 0.8f, 0.1f);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_FLAG1) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_FlagTrail (cent->lerp_origin, ent.origin, 242);
|
2009-02-28 17:39:51 +00:00
|
|
|
V_AddLight (ent.origin, 225, 1, 0.1f, 0.1f);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_FLAG2) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_FlagTrail (cent->lerp_origin, ent.origin, 115);
|
2009-02-28 17:39:51 +00:00
|
|
|
V_AddLight (ent.origin, 225, 0.1f, 0.1f, 1);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_TAGTRAIL) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_TagTrail (cent->lerp_origin, ent.origin, 220);
|
|
|
|
V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_TRACKERTRAIL) {
|
|
|
|
if (effects & EF_TRACKER) {
|
2009-02-28 14:41:18 +00:00
|
|
|
float intensity;
|
|
|
|
|
2009-02-28 17:39:51 +00:00
|
|
|
intensity = 50 + (500 * ((float)sin(cl.time/500.0f) + 1.0f));
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +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
|
2009-03-01 11:40:49 +00:00
|
|
|
V_AddLight (ent.origin, -1.0f * intensity, 1.0f, 1.0f, 1.0f);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_Tracker_Shell (cent->lerp_origin);
|
|
|
|
V_AddLight (ent.origin, 155, -1.0, -1.0, -1.0);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_TRACKER) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_TrackerTrail (cent->lerp_origin, ent.origin, 0);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if(vidref_val == VIDREF_GL)
|
|
|
|
V_AddLight (ent.origin, 200, -1, -1, -1);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
|
|
|
V_AddLight (ent.origin, -200, 1, 1, 1);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_IONRIPPER) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_IonripperTrail (cent->lerp_origin, ent.origin);
|
|
|
|
V_AddLight (ent.origin, 100, 1, 0.5, 0.5);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_BLUEHYPERBLASTER) {
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddLight (ent.origin, 200, 0, 0, 1);
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (effects & EF_PLASMA) {
|
|
|
|
if (effects & EF_ANIM_ALLFAST) {
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_BlasterTrail (cent->lerp_origin, ent.origin);
|
|
|
|
}
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddLight (ent.origin, 130, 1, 0.5, 0.5);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VectorCopy (ent.origin, cent->lerp_origin);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops) {
|
|
|
|
entity_t gun = {0}; /* view model */
|
2009-02-28 14:41:18 +00:00
|
|
|
int i;
|
|
|
|
|
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)
|
|
|
|
return;
|
|
|
|
|
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)
|
2009-10-04 12:32:44 +00:00
|
|
|
if (cl_gun->value < 2)
|
|
|
|
return;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
if (gun_model)
|
2010-06-17 06:24:27 +00:00
|
|
|
gun.model = gun_model;
|
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
|
|
|
gun.model = cl.model_draw[ps->gunindex];
|
2010-06-17 06:24:27 +00:00
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
if (!gun.model)
|
|
|
|
return;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* set up gun position */
|
|
|
|
for (i=0 ; i<3 ; i++) {
|
2009-02-28 14:41:18 +00:00
|
|
|
gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i]
|
2010-06-17 06:24:27 +00:00
|
|
|
+ cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
|
2009-02-28 14:41:18 +00:00
|
|
|
gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i],
|
2010-06-17 06:24:27 +00:00
|
|
|
ps->gunangles[i], cl.lerpfrac);
|
2009-02-28 14:41:18 +00:00
|
|
|
}
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
if (gun_frame) {
|
|
|
|
gun.frame = gun_frame;
|
|
|
|
gun.oldframe = gun_frame;
|
|
|
|
|
|
|
|
} 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)
|
2010-06-17 06:24:27 +00:00
|
|
|
gun.oldframe = 0; /* just changed weapons, don't lerp from old */
|
|
|
|
|
2009-02-28 14:41:18 +00:00
|
|
|
else
|
|
|
|
gun.oldframe = ops->gunframe;
|
|
|
|
}
|
|
|
|
|
|
|
|
gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
|
2009-02-28 17:39:51 +00:00
|
|
|
gun.backlerp = 1.0f - cl.lerpfrac;
|
2010-06-17 06:24:27 +00:00
|
|
|
VectorCopy (gun.origin, gun.oldorigin); /* don't lerp at all */
|
2009-02-28 14:41:18 +00:00
|
|
|
V_AddEntity (&gun);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-17 06:24:27 +00:00
|
|
|
* Sets cl.refdef view values
|
|
|
|
*/
|
|
|
|
void CL_CalcViewValues (void) {
|
2009-02-28 14:41:18 +00:00
|
|
|
int i;
|
|
|
|
float lerp, backlerp;
|
|
|
|
frame_t *oldframe;
|
|
|
|
player_state_t *ps, *ops;
|
|
|
|
|
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
|
|
|
|
2009-02-28 14:41:18 +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 */
|
|
|
|
|
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 */
|
2009-02-28 14:41:18 +00:00
|
|
|
if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8
|
2010-06-17 06:24:27 +00:00
|
|
|
|| 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 */
|
|
|
|
if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION)) {
|
|
|
|
/* use predicted values */
|
2009-02-28 14:41:18 +00:00
|
|
|
unsigned delta;
|
|
|
|
|
2009-02-28 17:39:51 +00:00
|
|
|
backlerp = 1.0f - lerp;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
for (i=0 ; i<3 ; i++) {
|
|
|
|
cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i]
|
|
|
|
+ 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)
|
|
|
|
cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/* just use interpolated values */
|
2009-02-28 14:41:18 +00:00
|
|
|
for (i=0 ; i<3 ; i++)
|
2010-06-17 06:24:27 +00:00
|
|
|
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 */
|
|
|
|
if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD ) {
|
|
|
|
/* use predicted values */
|
2009-02-28 14:41:18 +00:00
|
|
|
for (i=0 ; i<3 ; i++)
|
|
|
|
cl.refdef.viewangles[i] = cl.predicted_angles[i];
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
/* just use interpolated values */
|
2009-02-28 14:41:18 +00:00
|
|
|
for (i=0 ; i<3 ; i++)
|
|
|
|
cl.refdef.viewangles[i] = LerpAngle (ops->viewangles[i], ps->viewangles[i], lerp);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0 ; i<3 ; i++)
|
|
|
|
cl.refdef.viewangles[i] += LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp);
|
|
|
|
|
|
|
|
AngleVectors (cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up);
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* interpolate field of view */
|
2009-02-28 14:41:18 +00:00
|
|
|
cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov);
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* don't interpolate blend color */
|
2009-02-28 14:41:18 +00:00
|
|
|
for (i=0 ; i<4 ; i++)
|
|
|
|
cl.refdef.blend[i] = ps->blend[i];
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
/* add the weapon */
|
2009-02-28 14:41:18 +00:00
|
|
|
CL_AddViewWeapon (ps, ops);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-17 06:24:27 +00:00
|
|
|
* Emits all entities, particles, and lights to the refresh
|
|
|
|
*/
|
|
|
|
void CL_AddEntities (void) {
|
2009-02-28 14:41:18 +00:00
|
|
|
if (cls.state != ca_active)
|
|
|
|
return;
|
|
|
|
|
2010-06-17 06:24:27 +00:00
|
|
|
if (cl.time > cl.frame.servertime) {
|
2009-02-28 14:41:18 +00:00
|
|
|
if (cl_showclamp->value)
|
|
|
|
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;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else if (cl.time < cl.frame.servertime - 100) {
|
2009-02-28 14:41:18 +00:00
|
|
|
if (cl_showclamp->value)
|
|
|
|
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;
|
2010-06-17 06:24:27 +00:00
|
|
|
|
|
|
|
} else
|
2009-02-28 17:39:51 +00:00
|
|
|
cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01f;
|
2009-02-28 14:41:18 +00:00
|
|
|
|
|
|
|
if (cl_timedemo->value)
|
|
|
|
cl.lerpfrac = 1.0;
|
|
|
|
|
|
|
|
CL_CalcViewValues ();
|
|
|
|
CL_AddPacketEntities (&cl.frame);
|
|
|
|
CL_AddTEnts ();
|
|
|
|
CL_AddParticles ();
|
|
|
|
CL_AddDLights ();
|
|
|
|
CL_AddLightStyles ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2010-06-17 06:24:27 +00:00
|
|
|
* Called to get the sound spatialization origin
|
|
|
|
*/
|
|
|
|
void CL_GetEntitySoundOrigin (int ent, vec3_t org) {
|
2009-02-28 14:41:18 +00:00
|
|
|
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];
|
|
|
|
VectorCopy (old->lerp_origin, org);
|
|
|
|
}
|