mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
[client] Merge nq and qw temp entity handling
This finally gets cl_tent merged away.
This commit is contained in:
parent
fbc1bd9f6e
commit
098ceed5ff
22 changed files with 482 additions and 957 deletions
|
@ -67,4 +67,7 @@ extern entstates_t qw_entstates;
|
|||
|
||||
extern vec3_t ent_colormod[256];
|
||||
|
||||
struct entity_s;
|
||||
void CL_TransformEntity (struct entity_s *ent, const vec3_t angles);
|
||||
|
||||
#endif//__client_entities_h
|
||||
|
|
119
include/client/temp_entities.h
Normal file
119
include/client/temp_entities.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
temp_entities.h
|
||||
|
||||
Temporary entity management
|
||||
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2021/3/10
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifndef __client_temp_entities_h
|
||||
#define __client_temp_entities_h
|
||||
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
typedef enum TE_Effect {
|
||||
TE_NoEffect, // for invalid nq/qw -> qf mapping
|
||||
TE_Beam, // grappling hook beam
|
||||
TE_Blood, // bullet hitting body
|
||||
TE_Explosion, // rocket explosion
|
||||
TE_Explosion2, // color mapped explosion
|
||||
TE_Explosion3, // Nehahra colored light explosion
|
||||
TE_Gunshot1, // NQ gunshot (20 particles)
|
||||
TE_Gunshot2, // QW gunshot (has particle count)
|
||||
TE_KnightSpike, // spike hitting wall
|
||||
TE_LavaSplash,
|
||||
TE_Lightning1, // lightning bolts
|
||||
TE_Lightning2, // lightning bolts
|
||||
TE_Lightning3, // lightning bolts
|
||||
TE_Lightning4, // Nehahra lightning
|
||||
TE_LightningBlood, // lightning hitting body
|
||||
TE_Spike, // spike hitting wall
|
||||
TE_SuperSpike, // super spike hitting wall
|
||||
TE_TarExplosion, // tarbaby explosion
|
||||
TE_Teleport,
|
||||
TE_WizSpike, // spike hitting wall
|
||||
} TE_Effect;
|
||||
|
||||
typedef enum TE_nqEffect {
|
||||
TE_nqSpike,
|
||||
TE_nqSuperSpike,
|
||||
TE_nqGunshot,
|
||||
TE_nqExplosion,
|
||||
TE_nqTarExplosion,
|
||||
TE_nqLightning1,
|
||||
TE_nqLightning2,
|
||||
TE_nqWizSpike,
|
||||
TE_nqKnightSpike,
|
||||
TE_nqLightning3,
|
||||
TE_nqLavaSplash,
|
||||
TE_nqTeleport,
|
||||
TE_nqExplosion2,
|
||||
TE_nqBeam,
|
||||
TE_nqExplosion3 = 16,
|
||||
TE_nqLightning4,
|
||||
} TE_nqEffect;
|
||||
|
||||
typedef enum TE_qwEffect {
|
||||
TE_qwSpike,
|
||||
TE_qwSuperSpike,
|
||||
TE_qwGunshot,
|
||||
TE_qwExplosion,
|
||||
TE_qwTarExplosion,
|
||||
TE_qwLightning1,
|
||||
TE_qwLightning2,
|
||||
TE_qwWizSpike,
|
||||
TE_qwKnightSpike,
|
||||
TE_qwLightning3,
|
||||
TE_qwLavaSplash,
|
||||
TE_qwTeleport,
|
||||
TE_qwBlood,
|
||||
TE_qwLightningBlood,
|
||||
TE_qwExplosion2 = 16,
|
||||
TE_qwBeam,
|
||||
} TE_qwEffect;
|
||||
|
||||
//FIXME find a better way to get this info from the parser
|
||||
typedef struct TEntContext_s {
|
||||
vec4f_t simorg;
|
||||
struct model_s *worldModel;
|
||||
int playerEntity;
|
||||
} TEntContext_t;
|
||||
|
||||
struct msg_s;
|
||||
struct entity_s;
|
||||
|
||||
void CL_TEnts_Init (void);
|
||||
void CL_Init_Entity (struct entity_s *ent);
|
||||
void CL_ClearTEnts (void);
|
||||
void CL_UpdateTEnts (double time, TEntContext_t *ctx);
|
||||
void CL_ParseTEnt_nq (struct msg_s *net_message, double time,
|
||||
TEntContext_t *ctx);
|
||||
void CL_ParseTEnt_qw (struct msg_s *net_message, double time,
|
||||
TEntContext_t *ctx);
|
||||
void CL_ParseParticleEffect (struct msg_s *net_message);
|
||||
void CL_ClearProjectiles (void);
|
||||
void CL_ParseProjectiles (struct msg_s *net_message, qboolean nail2,
|
||||
TEntContext_t *ctx);
|
||||
|
||||
#endif//__client_temp_entities_h
|
|
@ -3,4 +3,6 @@ noinst_LTLIBRARIES += libs/client/libQFclient.la
|
|||
libs_client_libQFclient_la_LDFLAGS= @STATIC@
|
||||
libs_client_libQFclient_la_LIBADD= libs/gamecode/libQFgamecode.la libs/util/libQFutil.la
|
||||
libs_client_libQFclient_la_SOURCES= \
|
||||
libs/client/cl_entities.c
|
||||
libs/client/cl_temp_entities.c \
|
||||
libs/client/cl_entities.c \
|
||||
$e
|
||||
|
|
|
@ -31,6 +31,10 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "QF/entity.h"
|
||||
#include "QF/render.h" //FIXME for entity_t
|
||||
#include "QF/simd/vec4f.h"
|
||||
|
||||
#include "client/entities.h"
|
||||
|
||||
/* QW has a max of 512 entities and wants 64 frames of data per entity, plus
|
||||
|
@ -340,3 +344,33 @@ vec3_t ent_colormod[256] = {
|
|||
{1, 1, 0.666667},
|
||||
{1, 1, 1}
|
||||
};
|
||||
|
||||
void
|
||||
CL_TransformEntity (entity_t *ent, const vec3_t angles)
|
||||
{
|
||||
union {
|
||||
quat_t q;
|
||||
vec4f_t v;
|
||||
} rotation;
|
||||
vec4f_t position;
|
||||
vec4f_t scale;
|
||||
|
||||
VectorCopy (ent->origin, position);
|
||||
position[3] = 1;
|
||||
VectorSet (ent->scale, ent->scale, ent->scale, scale);
|
||||
scale[3] = 1;
|
||||
if (VectorIsZero (angles)) {
|
||||
QuatSet (0, 0, 0, 1, rotation.q);
|
||||
} else {
|
||||
vec3_t ang;
|
||||
VectorCopy (angles, ang);
|
||||
if (ent->renderer.model && ent->renderer.model->type == mod_alias) {
|
||||
// stupid quake bug
|
||||
// why, oh, why, do alias models pitch in the opposite direction
|
||||
// to everything else?
|
||||
ang[PITCH] = -ang[PITCH];
|
||||
}
|
||||
AngleQuat (ang, rotation.q);
|
||||
}
|
||||
Transform_SetLocalTransform (ent->transform, scale, rotation.v, position);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
/*
|
||||
cl_tent.c
|
||||
cl_temp_entities.c
|
||||
|
||||
client side temporary entities
|
||||
Client side temporary entity management
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
Date: 2021/3/10
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
@ -27,7 +30,6 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
|
@ -35,23 +37,16 @@
|
|||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/console.h"
|
||||
#include "QF/entity.h"
|
||||
#include "QF/model.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/render.h"
|
||||
#include "QF/sound.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "QF/plugin/vid_render.h" //FIXME
|
||||
|
||||
#include "qw/include/cl_ents.h"
|
||||
#include "qw/include/cl_main.h"
|
||||
#include "qw/include/cl_parse.h"
|
||||
#include "qw/include/cl_tent.h"
|
||||
#include "qw/include/client.h"
|
||||
#include "client/entities.h"
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
typedef struct tent_s {
|
||||
struct tent_s *next;
|
||||
|
@ -94,28 +89,29 @@ static tent_t *cl_projectiles;
|
|||
static sfx_t *cl_sfx_wizhit;
|
||||
static sfx_t *cl_sfx_knighthit;
|
||||
static sfx_t *cl_sfx_tink1;
|
||||
static sfx_t *cl_sfx_ric1;
|
||||
static sfx_t *cl_sfx_ric2;
|
||||
static sfx_t *cl_sfx_ric3;
|
||||
static sfx_t *cl_sfx_r_exp3;
|
||||
static sfx_t *cl_sfx_ric[4];
|
||||
|
||||
static model_t *cl_mod_beam;
|
||||
static model_t *cl_mod_bolt;
|
||||
static model_t *cl_mod_bolt2;
|
||||
static model_t *cl_mod_bolt3;
|
||||
static model_t *cl_spr_explod;
|
||||
static model_t *cl_spike;
|
||||
|
||||
static void
|
||||
CL_TEnts_Precache (int phase)
|
||||
{
|
||||
if (!phase)
|
||||
if (!phase) {
|
||||
return;
|
||||
}
|
||||
cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
|
||||
cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
|
||||
cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
|
||||
cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
|
||||
cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
|
||||
cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
|
||||
cl_sfx_ric[3] = S_PrecacheSound ("weapons/ric1.wav");
|
||||
cl_sfx_ric[2] = S_PrecacheSound ("weapons/ric2.wav");
|
||||
cl_sfx_ric[1] = S_PrecacheSound ("weapons/ric3.wav");
|
||||
cl_sfx_ric[0] = cl_sfx_ric[1];
|
||||
cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
|
||||
|
||||
cl_mod_bolt = Mod_ForName ("progs/bolt.mdl", true);
|
||||
|
@ -123,8 +119,11 @@ CL_TEnts_Precache (int phase)
|
|||
cl_mod_bolt3 = Mod_ForName ("progs/bolt3.mdl", true);
|
||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||
cl_mod_beam = Mod_ForName ("progs/beam.mdl", false);
|
||||
if (!cl_mod_beam)
|
||||
cl_spike = Mod_ForName ("progs/spike.mdl", false);
|
||||
|
||||
if (!cl_mod_beam) {
|
||||
cl_mod_beam = cl_mod_bolt;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -214,23 +213,23 @@ free_tent_objects (tent_obj_t *tobjs)
|
|||
void
|
||||
CL_ClearTEnts (void)
|
||||
{
|
||||
tent_t *t;
|
||||
tent_obj_t *to;
|
||||
tent_t *tent;
|
||||
tent_obj_t *tobj;
|
||||
|
||||
for (to = cl_beams; to; to = to->next) {
|
||||
for (t = to->to.beam.tents; t; t = t->next) {
|
||||
t->ent.visibility.efrag = 0;
|
||||
for (tobj = cl_beams; tobj; tobj = tobj->next) {
|
||||
for (tent = tobj->to.beam.tents; tent; tent = tent->next) {
|
||||
tent->ent.visibility.efrag = 0;
|
||||
}
|
||||
free_temp_entities (to->to.beam.tents);
|
||||
free_temp_entities (tobj->to.beam.tents);
|
||||
}
|
||||
free_tent_objects (cl_beams);
|
||||
cl_beams = 0;
|
||||
|
||||
for (to = cl_explosions; to; to = to->next) {
|
||||
for (t = to->to.ex.tent; t; t = t->next) {
|
||||
t->ent.visibility.efrag = 0;
|
||||
for (tobj = cl_explosions; tobj; tobj = tobj->next) {
|
||||
for (tent = tobj->to.ex.tent; tent; tent = tent->next) {
|
||||
tent->ent.visibility.efrag = 0;
|
||||
}
|
||||
free_temp_entities (to->to.ex.tent);
|
||||
free_temp_entities (tobj->to.ex.tent);
|
||||
}
|
||||
free_tent_objects (cl_explosions);
|
||||
cl_explosions = 0;
|
||||
|
@ -252,7 +251,7 @@ beam_clear (beam_t *b)
|
|||
}
|
||||
|
||||
static inline void
|
||||
beam_setup (beam_t *b, qboolean transform)
|
||||
beam_setup (beam_t *b, qboolean transform, double time, TEntContext_t *ctx)
|
||||
{
|
||||
tent_t *tent;
|
||||
float forward, pitch, yaw, d;
|
||||
|
@ -287,8 +286,7 @@ beam_setup (beam_t *b, qboolean transform)
|
|||
ent_count = ceil (d / 30);
|
||||
d = 0;
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
BEAM_SEED_INTERVAL);
|
||||
seed = b->seed + ((int) (time * BEAM_SEED_INTERVAL) % BEAM_SEED_INTERVAL);
|
||||
|
||||
ang[ROLL] = 0;
|
||||
while (ent_count--) {
|
||||
|
@ -304,15 +302,15 @@ beam_setup (beam_t *b, qboolean transform)
|
|||
if (transform) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
ang[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&tent->ent, ang, true);
|
||||
CL_TransformEntity (&tent->ent, ang);
|
||||
}
|
||||
VectorCopy (ang, tent->ent.angles);
|
||||
r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent);
|
||||
r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CL_ParseBeam (model_t *m)
|
||||
CL_ParseBeam (qmsg_t *net_message, model_t *m, double time, TEntContext_t *ctx)
|
||||
{
|
||||
tent_obj_t *to;
|
||||
beam_t *b;
|
||||
|
@ -326,10 +324,12 @@ CL_ParseBeam (model_t *m)
|
|||
|
||||
to = 0;
|
||||
if (ent) {
|
||||
for (to = cl_beams; to; to = to->next)
|
||||
if (to->to.beam.entity == ent)
|
||||
for (to = cl_beams; to; to = to->next) {
|
||||
if (to->to.beam.entity == ent) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!to) {
|
||||
to = new_tent_object ();
|
||||
to->next = cl_beams;
|
||||
|
@ -341,93 +341,60 @@ CL_ParseBeam (model_t *m)
|
|||
|
||||
beam_clear (b);
|
||||
b->model = m;
|
||||
b->endtime = cl.time + 0.2;
|
||||
b->endtime = time + 0.2;
|
||||
b->seed = rand ();
|
||||
VectorCopy (end, b->end);
|
||||
if (b->entity != cl.viewentity) {
|
||||
if (b->entity != ctx->playerEntity) {
|
||||
// this will be done in CL_UpdateBeams
|
||||
VectorCopy (start, b->start);
|
||||
beam_setup (b, true);
|
||||
beam_setup (b, true, time, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CL_ParseTEnt (void)
|
||||
static void
|
||||
parse_tent (qmsg_t *net_message, double time, TEntContext_t *ctx,
|
||||
TE_Effect type)
|
||||
{
|
||||
byte type;
|
||||
dlight_t *dl;
|
||||
tent_obj_t *to;
|
||||
explosion_t *ex;
|
||||
int colorStart, colorLength;
|
||||
int cnt = -1;
|
||||
vec3_t pos;
|
||||
sfx_t *spike_sound[] = {
|
||||
cl_sfx_ric3, cl_sfx_ric3, cl_sfx_ric2, cl_sfx_ric1,
|
||||
};
|
||||
quat_t color;
|
||||
vec3_t position;
|
||||
int count;
|
||||
const char *name;
|
||||
|
||||
type = MSG_ReadByte (net_message);
|
||||
switch (type) {
|
||||
case TE_WIZSPIKE: // spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_WizSpikeEffect (pos);
|
||||
S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
|
||||
case TE_NoEffect:
|
||||
// invalid mapping, can't do anything
|
||||
break;
|
||||
|
||||
case TE_KNIGHTSPIKE: // spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_KnightSpikeEffect (pos);
|
||||
S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
|
||||
case TE_Beam:
|
||||
CL_ParseBeam (net_message, cl_mod_beam, time, ctx);
|
||||
break;
|
||||
|
||||
case TE_SPIKE: // spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_SpikeEffect (pos);
|
||||
{
|
||||
int i;
|
||||
sfx_t *sound;
|
||||
|
||||
i = (rand () % 20) - 16;
|
||||
if (i >= 0)
|
||||
sound = spike_sound[i];
|
||||
else
|
||||
sound = cl_sfx_tink1;
|
||||
S_StartSound (-1, 0, sound, pos, 1, 1);
|
||||
}
|
||||
case TE_Blood:
|
||||
count = MSG_ReadByte (net_message) * 20;
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_BloodPuffEffect (position, count);
|
||||
break;
|
||||
case TE_Explosion:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
|
||||
case TE_SUPERSPIKE: // super spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_SuperSpikeEffect (pos);
|
||||
{
|
||||
int i;
|
||||
sfx_t *sound;
|
||||
|
||||
i = (rand () % 20) - 16;
|
||||
if (i >= 0)
|
||||
sound = spike_sound[i];
|
||||
else
|
||||
sound = cl_sfx_tink1;
|
||||
S_StartSound (-1, 0, sound, pos, 1, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case TE_EXPLOSION: // rocket explosion
|
||||
// particles
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_ParticleExplosion (pos);
|
||||
r_funcs->particles->R_ParticleExplosion (position);
|
||||
|
||||
// light
|
||||
dl = r_funcs->R_AllocDlight (0);
|
||||
if (dl) {
|
||||
VectorCopy (pos, dl->origin);
|
||||
VectorCopy (position, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->die = time + 0.5;
|
||||
dl->decay = 300;
|
||||
QuatSet (0.86, 0.31, 0.24, 0.7, dl->color);
|
||||
//FIXME? nq: QuatSet (1.0, 0.5, 0.25, 0.7, dl->color);
|
||||
}
|
||||
|
||||
// sound
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
|
||||
|
||||
// sprite
|
||||
to = new_tent_object ();
|
||||
|
@ -436,105 +403,201 @@ CL_ParseTEnt (void)
|
|||
ex = &to->to.ex;
|
||||
ex->tent = new_temp_entity ();
|
||||
|
||||
VectorCopy (pos, ex->tent->ent.origin);
|
||||
ex->start = cl.time;
|
||||
VectorCopy (position, ex->tent->ent.origin);
|
||||
ex->start = time;
|
||||
//FIXME need better model management
|
||||
if (!cl_spr_explod->cache.data)
|
||||
if (!cl_spr_explod->cache.data) {
|
||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||
}
|
||||
ex->tent->ent.renderer.model = cl_spr_explod;
|
||||
CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true);
|
||||
CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles);
|
||||
break;
|
||||
|
||||
case TE_TAREXPLOSION: // tarbaby explosion
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_BlobExplosion (pos);
|
||||
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING1: // lightning bolts
|
||||
CL_ParseBeam (cl_mod_bolt);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING2: // lightning bolts
|
||||
CL_ParseBeam (cl_mod_bolt2);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING3: // lightning bolts
|
||||
CL_ParseBeam (cl_mod_bolt3);
|
||||
break;
|
||||
|
||||
// PGM 01/21/97
|
||||
case TE_BEAM: // grappling hook beam
|
||||
CL_ParseBeam (cl_mod_beam);
|
||||
break;
|
||||
// PGM 01/21/97
|
||||
|
||||
case TE_LAVASPLASH:
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_LavaSplash (pos);
|
||||
break;
|
||||
|
||||
case TE_TELEPORT:
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_TeleportSplash (pos);
|
||||
break;
|
||||
|
||||
case TE_EXPLOSION2: // color mapped explosion
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
case TE_Explosion2:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
colorStart = MSG_ReadByte (net_message);
|
||||
colorLength = MSG_ReadByte (net_message);
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
r_funcs->particles->R_ParticleExplosion2 (pos, colorStart,
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
|
||||
r_funcs->particles->R_ParticleExplosion2 (position, colorStart,
|
||||
colorLength);
|
||||
dl = r_funcs->R_AllocDlight (0);
|
||||
if (!dl)
|
||||
break;
|
||||
VectorCopy (pos, dl->origin);
|
||||
VectorCopy (position, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->die = time + 0.5;
|
||||
dl->decay = 300;
|
||||
colorStart = (colorStart + (rand () % colorLength)) * 3;
|
||||
VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0,
|
||||
dl->color);
|
||||
dl->color[3] = 0.7;
|
||||
break;
|
||||
|
||||
case TE_GUNSHOT: // bullet hitting wall
|
||||
cnt = MSG_ReadByte (net_message) * 20;
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_GunshotEffect (pos, cnt);
|
||||
case TE_Explosion3:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
MSG_ReadCoordV (net_message, color); // OUCH!
|
||||
color[3] = 0.7;
|
||||
r_funcs->particles->R_ParticleExplosion (position);
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
|
||||
dl = r_funcs->R_AllocDlight (0);
|
||||
if (dl) {
|
||||
VectorCopy (position, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = time + 0.5;
|
||||
dl->decay = 300;
|
||||
QuatCopy (color, dl->color);
|
||||
}
|
||||
break;
|
||||
|
||||
case TE_BLOOD: // bullet hitting body
|
||||
cnt = MSG_ReadByte (net_message) * 20;
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_BloodPuffEffect (pos, cnt);
|
||||
case TE_Gunshot1:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_GunshotEffect (position, 20);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNINGBLOOD: // lightning hitting body
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
case TE_Gunshot2:
|
||||
count = MSG_ReadByte (net_message) * 20;
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_GunshotEffect (position, count);
|
||||
break;
|
||||
case TE_KnightSpike:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_KnightSpikeEffect (position);
|
||||
S_StartSound (-1, 0, cl_sfx_knighthit, position, 1, 1);
|
||||
break;
|
||||
case TE_LavaSplash:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_LavaSplash (position);
|
||||
break;
|
||||
case TE_Lightning1:
|
||||
CL_ParseBeam (net_message, cl_mod_bolt, time, ctx);
|
||||
break;
|
||||
case TE_Lightning2:
|
||||
CL_ParseBeam (net_message, cl_mod_bolt2, time, ctx);
|
||||
break;
|
||||
case TE_Lightning3:
|
||||
CL_ParseBeam (net_message, cl_mod_bolt3, time, ctx);
|
||||
break;
|
||||
case TE_Lightning4:
|
||||
name = MSG_ReadString (net_message);
|
||||
CL_ParseBeam (net_message, Mod_ForName (name, true), time, ctx);
|
||||
break;
|
||||
case TE_LightningBlood:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
|
||||
// light
|
||||
dl = r_funcs->R_AllocDlight (0);
|
||||
if (dl) {
|
||||
VectorCopy (pos, dl->origin);
|
||||
VectorCopy (position, dl->origin);
|
||||
dl->radius = 150;
|
||||
dl->die = cl.time + 0.1;
|
||||
dl->die = time + 0.1;
|
||||
dl->decay = 200;
|
||||
QuatSet (0.25, 0.40, 0.65, 1, dl->color);
|
||||
}
|
||||
|
||||
r_funcs->particles->R_LightningBloodEffect (pos);
|
||||
r_funcs->particles->R_LightningBloodEffect (position);
|
||||
break;
|
||||
case TE_Spike:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_SpikeEffect (position);
|
||||
{
|
||||
int i;
|
||||
sfx_t *sound;
|
||||
|
||||
default:
|
||||
Sys_Error ("CL_ParseTEnt: bad type %d", type);
|
||||
i = (rand () % 20) - 16;
|
||||
if (i >= 0) {
|
||||
sound = cl_sfx_ric[i];
|
||||
} else {
|
||||
sound = cl_sfx_tink1;
|
||||
}
|
||||
S_StartSound (-1, 0, sound, position, 1, 1);
|
||||
}
|
||||
break;
|
||||
case TE_SuperSpike:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_SuperSpikeEffect (position);
|
||||
{
|
||||
int i;
|
||||
sfx_t *sound;
|
||||
|
||||
i = (rand () % 20) - 16;
|
||||
if (i >= 0) {
|
||||
sound = cl_sfx_ric[i];
|
||||
} else {
|
||||
sound = cl_sfx_tink1;
|
||||
}
|
||||
S_StartSound (-1, 0, sound, position, 1, 1);
|
||||
}
|
||||
break;
|
||||
case TE_TarExplosion:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_BlobExplosion (position);
|
||||
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, position, 1, 1);
|
||||
break;
|
||||
case TE_Teleport:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_TeleportSplash (position);
|
||||
break;
|
||||
case TE_WizSpike:
|
||||
MSG_ReadCoordV (net_message, position);
|
||||
r_funcs->particles->R_WizSpikeEffect (position);
|
||||
S_StartSound (-1, 0, cl_sfx_wizhit, position, 1, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// the effect type is a byte so a max of 256 values
|
||||
static const TE_Effect nqEffects[256] = {
|
||||
[TE_nqSpike] = TE_Spike,
|
||||
[TE_nqSuperSpike] = TE_SuperSpike,
|
||||
[TE_nqGunshot] = TE_Gunshot1,
|
||||
[TE_nqExplosion] = TE_Explosion,
|
||||
[TE_nqTarExplosion] = TE_TarExplosion,
|
||||
[TE_nqLightning1] = TE_Lightning1,
|
||||
[TE_nqLightning2] = TE_Lightning2,
|
||||
[TE_nqWizSpike] = TE_WizSpike,
|
||||
[TE_nqKnightSpike] = TE_KnightSpike,
|
||||
[TE_nqLightning3] = TE_Lightning3,
|
||||
[TE_nqLavaSplash] = TE_LavaSplash,
|
||||
[TE_nqTeleport] = TE_Teleport,
|
||||
[TE_nqExplosion2] = TE_Explosion2,
|
||||
[TE_nqBeam] = TE_Beam,
|
||||
[TE_nqExplosion3] = TE_Explosion3,
|
||||
[TE_nqLightning4] = TE_Lightning4,
|
||||
};
|
||||
|
||||
void
|
||||
CL_ParseTEnt_nq (qmsg_t *net_message, double time, TEntContext_t *ctx)
|
||||
{
|
||||
byte type = MSG_ReadByte (net_message);
|
||||
parse_tent (net_message, time, ctx, nqEffects[type]);
|
||||
}
|
||||
|
||||
// the effect type is a byte so a max of 256 values
|
||||
static const TE_Effect qwEffects[256] = {
|
||||
[TE_qwSpike] = TE_Spike,
|
||||
[TE_qwSuperSpike] = TE_SuperSpike,
|
||||
[TE_qwGunshot] = TE_Gunshot2,
|
||||
[TE_qwExplosion] = TE_Explosion,
|
||||
[TE_qwTarExplosion] = TE_TarExplosion,
|
||||
[TE_qwLightning1] = TE_Lightning1,
|
||||
[TE_qwLightning2] = TE_Lightning2,
|
||||
[TE_qwWizSpike] = TE_WizSpike,
|
||||
[TE_qwKnightSpike] = TE_KnightSpike,
|
||||
[TE_qwLightning3] = TE_Lightning3,
|
||||
[TE_qwLavaSplash] = TE_LavaSplash,
|
||||
[TE_qwTeleport] = TE_Teleport,
|
||||
[TE_qwBlood] = TE_Blood,
|
||||
[TE_qwLightningBlood] = TE_LightningBlood,
|
||||
[TE_qwExplosion2] = TE_Explosion2,
|
||||
[TE_qwBeam] = TE_Beam,
|
||||
};
|
||||
|
||||
void
|
||||
CL_ParseTEnt_qw (qmsg_t *net_message, double time, TEntContext_t *ctx)
|
||||
{
|
||||
byte type = MSG_ReadByte (net_message);
|
||||
parse_tent (net_message, time, ctx, qwEffects[type]);
|
||||
}
|
||||
|
||||
static void
|
||||
CL_UpdateBeams (void)
|
||||
CL_UpdateBeams (double time, TEntContext_t *ctx)
|
||||
{
|
||||
tent_obj_t **to;
|
||||
beam_t *b;
|
||||
|
@ -546,7 +609,7 @@ CL_UpdateBeams (void)
|
|||
b = &(*to)->to.beam;
|
||||
if (!b->endtime)
|
||||
continue;
|
||||
if (!b->model || b->endtime < cl.time) {
|
||||
if (!b->model || b->endtime < time) {
|
||||
tent_obj_t *_to;
|
||||
b->endtime = 0;
|
||||
beam_clear (b);
|
||||
|
@ -559,26 +622,26 @@ CL_UpdateBeams (void)
|
|||
to = &(*to)->next;
|
||||
|
||||
// if coming from the player, update the start position
|
||||
if (b->entity == cl.viewentity) {
|
||||
if (b->entity == ctx->playerEntity) {
|
||||
beam_clear (b);
|
||||
VectorCopy (cl.simorg, b->start);
|
||||
beam_setup (b, false);
|
||||
VectorCopy (ctx->simorg, b->start);
|
||||
beam_setup (b, false, time, ctx);
|
||||
}
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
seed = b->seed + ((int) (time * BEAM_SEED_INTERVAL) %
|
||||
BEAM_SEED_INTERVAL);
|
||||
|
||||
// add new entities for the lightning
|
||||
for (t = b->tents; t; t = t->next) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
t->ent.angles[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&t->ent, t->ent.angles, true);
|
||||
CL_TransformEntity (&t->ent, t->ent.angles);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CL_UpdateExplosions (void)
|
||||
CL_UpdateExplosions (double time, TEntContext_t *ctx)
|
||||
{
|
||||
int f;
|
||||
tent_obj_t **to;
|
||||
|
@ -588,7 +651,7 @@ CL_UpdateExplosions (void)
|
|||
for (to = &cl_explosions; *to; ) {
|
||||
ex = &(*to)->to.ex;
|
||||
ent = &ex->tent->ent;
|
||||
f = 10 * (cl.time - ex->start);
|
||||
f = 10 * (time - ex->start);
|
||||
if (f >= ent->renderer.model->numframes) {
|
||||
tent_obj_t *_to;
|
||||
r_funcs->R_RemoveEfrags (ent);
|
||||
|
@ -604,16 +667,39 @@ CL_UpdateExplosions (void)
|
|||
|
||||
ent->animation.frame = f;
|
||||
if (!ent->visibility.efrag) {
|
||||
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
|
||||
r_funcs->R_AddEfrags (&ctx->worldModel->brush, ent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CL_UpdateTEnts (void)
|
||||
CL_UpdateTEnts (double time, TEntContext_t *ctx)
|
||||
{
|
||||
CL_UpdateBeams ();
|
||||
CL_UpdateExplosions ();
|
||||
CL_UpdateBeams (time, ctx);
|
||||
CL_UpdateExplosions (time, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
CL_ParseParticleEffect
|
||||
|
||||
Parse an effect out of the server message
|
||||
*/
|
||||
void
|
||||
CL_ParseParticleEffect (qmsg_t *net_message)
|
||||
{
|
||||
int i, count, color;
|
||||
vec3_t org, dir;
|
||||
|
||||
MSG_ReadCoordV (net_message, org);
|
||||
for (i = 0; i < 3; i++)
|
||||
dir[i] = ((signed char) MSG_ReadByte (net_message)) * (15.0 / 16.0);
|
||||
count = MSG_ReadByte (net_message);
|
||||
color = MSG_ReadByte (net_message);
|
||||
|
||||
if (count == 255)
|
||||
r_funcs->particles->R_ParticleExplosion (org);
|
||||
else
|
||||
r_funcs->particles->R_RunParticleEffect (org, dir, color, count);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -633,7 +719,7 @@ CL_ClearProjectiles (void)
|
|||
Nails are passed as efficient temporary entities
|
||||
*/
|
||||
void
|
||||
CL_ParseProjectiles (qboolean nail2)
|
||||
CL_ParseProjectiles (qmsg_t *net_message, qboolean nail2, TEntContext_t *ctx)
|
||||
{
|
||||
tent_t *tent;
|
||||
tent_t *head = 0, **tail = &head;
|
||||
|
@ -658,7 +744,7 @@ CL_ParseProjectiles (qboolean nail2)
|
|||
tail = &tent->next;
|
||||
|
||||
pr = &tent->ent;
|
||||
pr->renderer.model = cl.model_precache[cl_spikeindex];
|
||||
pr->renderer.model = cl_spike;
|
||||
pr->renderer.skin = 0;
|
||||
pr->origin[0] = ((bits[0] + ((bits[1] & 15) << 8)) << 1) - 4096;
|
||||
pr->origin[1] = (((bits[1] >> 4) + (bits[2] << 4)) << 1) - 4096;
|
||||
|
@ -666,9 +752,9 @@ CL_ParseProjectiles (qboolean nail2)
|
|||
pr->angles[0] = (bits[4] >> 4) * (360.0 / 16.0);
|
||||
pr->angles[1] = bits[5] * (360.0 / 256.0);
|
||||
pr->angles[2] = 0;
|
||||
CL_TransformEntity (&tent->ent, tent->ent.angles, true);
|
||||
CL_TransformEntity (&tent->ent, tent->ent.angles);
|
||||
|
||||
r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent);
|
||||
r_funcs->R_AddEfrags (&ctx->worldModel->brush, &tent->ent);
|
||||
}
|
||||
|
||||
*tail = cl_projectiles;
|
|
@ -304,10 +304,6 @@ void CL_Input_Init (void);
|
|||
void CL_SendCmd (void);
|
||||
void CL_SendMove (usercmd_t *cmd);
|
||||
|
||||
void CL_ParseParticleEffect (void);
|
||||
void CL_ParseTEnt (void);
|
||||
void CL_UpdateTEnts (void);
|
||||
|
||||
void CL_ClearState (void);
|
||||
|
||||
int CL_ReadFromServer (void);
|
||||
|
@ -344,13 +340,7 @@ void V_SetContentsColor (int contents);
|
|||
void V_PrepBlend (void);
|
||||
|
||||
// cl_tent
|
||||
void CL_TEnts_Init (void);
|
||||
void CL_ClearTEnts (void);
|
||||
void CL_Init_Entity (struct entity_s *ent);
|
||||
void CL_ParseTEnt (void);
|
||||
void CL_SignonReply (void);
|
||||
void CL_TransformEntity (struct entity_s *ent, const vec3_t
|
||||
angles, qboolean force);
|
||||
void CL_RelinkEntities (void);
|
||||
void CL_ClearEnts (void);
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ nq_server_LIB_DEPS=$(nq_server_LIBFILES) $(nq_common_LIBFILES)
|
|||
|
||||
nq_source_libnq_client_a_SOURCES= \
|
||||
nq/source/cl_chase.c nq/source/cl_cmd.c nq/source/cl_demo.c nq/source/cl_ents.c nq/source/cl_input.c nq/source/cl_main.c \
|
||||
nq/source/cl_screen.c nq/source/cl_parse.c nq/source/cl_tent.c nq/source/cl_view.c nq/source/sbar.c
|
||||
nq/source/cl_screen.c nq/source/cl_parse.c nq/source/cl_view.c nq/source/sbar.c
|
||||
|
||||
nq_source_libnq_server_a_SOURCES= \
|
||||
nq/source/host.c nq/source/host_cmd.c nq/source/sv_cl_phys.c nq/source/sv_cvar.c nq/source/sv_main.c \
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
#include "compat.h"
|
||||
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
#include "nq/include/chase.h"
|
||||
#include "nq/include/client.h"
|
||||
#include "nq/include/host.h"
|
||||
|
@ -177,36 +179,6 @@ CL_LerpPoint (void)
|
|||
return frac;
|
||||
}
|
||||
|
||||
void
|
||||
CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force)
|
||||
{
|
||||
union {
|
||||
quat_t q;
|
||||
vec4f_t v;
|
||||
} rotation;
|
||||
vec4f_t position;
|
||||
vec4f_t scale;
|
||||
|
||||
VectorCopy (ent->origin, position);
|
||||
position[3] = 1;
|
||||
VectorSet (ent->scale, ent->scale, ent->scale, scale);
|
||||
scale[3] = 1;
|
||||
if (VectorIsZero (angles)) {
|
||||
QuatSet (0, 0, 0, 1, rotation.q);
|
||||
} else {
|
||||
vec3_t ang;
|
||||
VectorCopy (angles, ang);
|
||||
if (ent->renderer.model && ent->renderer.model->type == mod_alias) {
|
||||
// stupid quake bug
|
||||
// why, oh, why, do alias models pitch in the opposite direction
|
||||
// to everything else?
|
||||
ang[PITCH] = -ang[PITCH];
|
||||
}
|
||||
AngleQuat (ang, rotation.q);
|
||||
}
|
||||
Transform_SetLocalTransform (ent->transform, scale, rotation.v, position);
|
||||
}
|
||||
|
||||
static void
|
||||
CL_ModelEffects (entity_t *ent, int num, int glow_color)
|
||||
{
|
||||
|
@ -392,7 +364,7 @@ CL_RelinkEntities (void)
|
|||
animation->pose1 = animation->pose2 = -1;
|
||||
VectorCopy (new->origin, ent->origin);
|
||||
if (!(model_flags & EF_ROTATE))
|
||||
CL_TransformEntity (ent, new->angles, true);
|
||||
CL_TransformEntity (ent, new->angles);
|
||||
if (i != cl.viewentity || chase_active->int_val) {
|
||||
if (ent->visibility.efrag) {
|
||||
r_funcs->R_RemoveEfrags (ent);
|
||||
|
@ -410,7 +382,7 @@ CL_RelinkEntities (void)
|
|||
// assume a teleportation, not a motion
|
||||
VectorCopy (new->origin, ent->origin);
|
||||
if (!(model_flags & EF_ROTATE))
|
||||
CL_TransformEntity (ent, new->angles, true);
|
||||
CL_TransformEntity (ent, new->angles);
|
||||
animation->pose1 = animation->pose2 = -1;
|
||||
} else {
|
||||
vec3_t angles, d;
|
||||
|
@ -425,7 +397,7 @@ CL_RelinkEntities (void)
|
|||
d[j] += 360;
|
||||
}
|
||||
VectorMultAdd (old->angles, f, d, angles);
|
||||
CL_TransformEntity (ent, angles, false);
|
||||
CL_TransformEntity (ent, angles);
|
||||
}
|
||||
}
|
||||
if (i != cl.viewentity || chase_active->int_val) {
|
||||
|
@ -445,7 +417,7 @@ CL_RelinkEntities (void)
|
|||
vec3_t angles;
|
||||
VectorCopy (new->angles, angles);
|
||||
angles[YAW] = bobjrotate;
|
||||
CL_TransformEntity (ent, angles, false);
|
||||
CL_TransformEntity (ent, angles);
|
||||
}
|
||||
CL_EntityEffects (i, ent, new);
|
||||
CL_NewDlight (i, ent->origin, new->effects, new->glow_size,
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
#include "clview.h"
|
||||
#include "sbar.h"
|
||||
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
#include "nq/include/chase.h"
|
||||
#include "nq/include/cl_skin.h"
|
||||
#include "nq/include/client.h"
|
||||
|
@ -423,6 +425,10 @@ int
|
|||
CL_ReadFromServer (void)
|
||||
{
|
||||
int ret;
|
||||
TEntContext_t tentCtx = {
|
||||
{VectorExpand (cl_entities[cl.viewentity].origin), 1},
|
||||
cl.worldmodel, cl.viewentity
|
||||
};
|
||||
|
||||
cl.oldtime = cl.time;
|
||||
cl.time += host_frametime;
|
||||
|
@ -442,7 +448,7 @@ CL_ReadFromServer (void)
|
|||
Sys_Printf ("\n");
|
||||
|
||||
CL_RelinkEntities ();
|
||||
CL_UpdateTEnts ();
|
||||
CL_UpdateTEnts (cl.time, &tentCtx);
|
||||
|
||||
// bring the links up to date
|
||||
return 0;
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
|
||||
#include "QF/plugin/vid_render.h"
|
||||
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "sbar.h"
|
||||
|
||||
|
@ -591,7 +593,7 @@ CL_ParseUpdate (int bits)
|
|||
//VectorCopy (state->msg_origins[0], state->msg_origins[1]);
|
||||
//VectorCopy (state->msg_origins[0], ent->origin);
|
||||
//VectorCopy (state->msg_angles[0], state->msg_angles[1]);
|
||||
//CL_TransformEntity (ent, state->msg_angles[0], true);
|
||||
//CL_TransformEntity (ent, state->msg_angles[0]);
|
||||
//state->forcelink = true;
|
||||
cl_forcelink[num] = true;
|
||||
}
|
||||
|
@ -793,7 +795,7 @@ CL_ParseStatic (int version)
|
|||
ent->renderer.colormod[3] = ENTALPHA_DECODE (baseline.alpha);
|
||||
ent->scale = baseline.scale / 16.0;
|
||||
VectorCopy (baseline.origin, ent->origin);
|
||||
CL_TransformEntity (ent, baseline.angles, true);
|
||||
CL_TransformEntity (ent, baseline.angles);
|
||||
|
||||
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
|
||||
}
|
||||
|
@ -835,6 +837,11 @@ CL_ParseServerMessage (void)
|
|||
static dstring_t *stuffbuf;
|
||||
signon_t so;
|
||||
|
||||
TEntContext_t tentCtx = {
|
||||
{VectorExpand (cl_entities[cl.viewentity].origin), 1},
|
||||
cl.worldmodel, cl.viewentity
|
||||
};
|
||||
|
||||
// if recording demos, copy the message out
|
||||
if (cl_shownet->int_val == 1)
|
||||
Sys_Printf ("%i ", net_message->message->cursize);
|
||||
|
@ -1031,7 +1038,7 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_particle:
|
||||
CL_ParseParticleEffect ();
|
||||
CL_ParseParticleEffect (net_message);
|
||||
break;
|
||||
|
||||
case svc_damage:
|
||||
|
@ -1051,7 +1058,7 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_temp_entity:
|
||||
CL_ParseTEnt ();
|
||||
CL_ParseTEnt_nq (net_message, cl.time, &tentCtx);
|
||||
break;
|
||||
|
||||
case svc_setpause:
|
||||
|
|
|
@ -1,630 +0,0 @@
|
|||
/*
|
||||
cl_tent.c
|
||||
|
||||
client side temporary entities
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/entity.h"
|
||||
#include "QF/model.h"
|
||||
#include "QF/msg.h"
|
||||
#include "QF/sound.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "QF/plugin/vid_render.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#include "nq/include/client.h"
|
||||
|
||||
typedef struct tent_s {
|
||||
struct tent_s *next;
|
||||
entity_t ent;
|
||||
} tent_t;
|
||||
|
||||
#define TEMP_BATCH 64
|
||||
static tent_t *temp_entities = 0;
|
||||
|
||||
typedef struct {
|
||||
int entity;
|
||||
struct model_s *model;
|
||||
float endtime;
|
||||
vec3_t start, end;
|
||||
tent_t *tents;
|
||||
int seed;
|
||||
} beam_t;
|
||||
|
||||
#define BEAM_SEED_INTERVAL 72
|
||||
#define BEAM_SEED_PRIME 3191
|
||||
|
||||
typedef struct {
|
||||
float start;
|
||||
tent_t *tent;
|
||||
} explosion_t;
|
||||
|
||||
typedef struct tent_obj_s {
|
||||
struct tent_obj_s *next;
|
||||
union {
|
||||
beam_t beam;
|
||||
explosion_t ex;
|
||||
} to;
|
||||
} tent_obj_t;
|
||||
|
||||
static tent_obj_t *tent_objects;
|
||||
static tent_obj_t *cl_beams;
|
||||
static tent_obj_t *cl_explosions;
|
||||
|
||||
static sfx_t *cl_sfx_wizhit;
|
||||
static sfx_t *cl_sfx_knighthit;
|
||||
static sfx_t *cl_sfx_tink1;
|
||||
static sfx_t *cl_sfx_ric1;
|
||||
static sfx_t *cl_sfx_ric2;
|
||||
static sfx_t *cl_sfx_ric3;
|
||||
static sfx_t *cl_sfx_r_exp3;
|
||||
|
||||
static model_t *cl_mod_beam;
|
||||
static model_t *cl_mod_bolt;
|
||||
static model_t *cl_mod_bolt2;
|
||||
static model_t *cl_mod_bolt3;
|
||||
static model_t *cl_spr_explod;
|
||||
|
||||
static void
|
||||
CL_TEnts_Precache (int phase)
|
||||
{
|
||||
if (!phase)
|
||||
return;
|
||||
cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
|
||||
cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
|
||||
cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
|
||||
cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
|
||||
cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
|
||||
cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
|
||||
cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
|
||||
|
||||
cl_mod_bolt = Mod_ForName ("progs/bolt.mdl", true);
|
||||
cl_mod_bolt2 = Mod_ForName ("progs/bolt2.mdl", true);
|
||||
cl_mod_bolt3 = Mod_ForName ("progs/bolt3.mdl", true);
|
||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||
cl_mod_beam = Mod_ForName ("progs/beam.mdl", false);
|
||||
if (!cl_mod_beam)
|
||||
cl_mod_beam = cl_mod_bolt;
|
||||
}
|
||||
|
||||
void
|
||||
CL_TEnts_Init (void)
|
||||
{
|
||||
QFS_GamedirCallback (CL_TEnts_Precache);
|
||||
CL_TEnts_Precache (1);
|
||||
}
|
||||
|
||||
void
|
||||
CL_Init_Entity (entity_t *ent)
|
||||
{
|
||||
if (ent->transform) {
|
||||
Transform_Delete (ent->transform);
|
||||
}
|
||||
memset (ent, 0, sizeof (*ent));
|
||||
|
||||
ent->transform = Transform_New (0);
|
||||
ent->renderer.skin = 0;
|
||||
QuatSet (1.0, 1.0, 1.0, 1.0, ent->renderer.colormod);
|
||||
ent->scale = 1.0;
|
||||
ent->animation.pose1 = ent->animation.pose2 = -1;
|
||||
}
|
||||
|
||||
static tent_t *
|
||||
new_temp_entity (void)
|
||||
{
|
||||
tent_t *tent;
|
||||
if (!temp_entities) {
|
||||
int i;
|
||||
|
||||
temp_entities = malloc (TEMP_BATCH * sizeof (tent_t));
|
||||
for (i = 0; i < TEMP_BATCH - 1; i++) {
|
||||
temp_entities[i].next = &temp_entities[i + 1];
|
||||
temp_entities[i].ent.transform = 0;
|
||||
}
|
||||
temp_entities[i].next = 0;
|
||||
temp_entities[i].ent.transform = 0;
|
||||
}
|
||||
tent = temp_entities;
|
||||
temp_entities = tent->next;
|
||||
tent->next = 0;
|
||||
CL_Init_Entity (&tent->ent);
|
||||
return tent;
|
||||
}
|
||||
|
||||
static void
|
||||
free_temp_entities (tent_t *tents)
|
||||
{
|
||||
tent_t **t = &tents;
|
||||
|
||||
while (*t)
|
||||
t = &(*t)->next;
|
||||
*t = temp_entities;
|
||||
temp_entities = tents;
|
||||
}
|
||||
|
||||
static tent_obj_t *
|
||||
new_tent_object (void)
|
||||
{
|
||||
tent_obj_t *tobj;
|
||||
if (!tent_objects) {
|
||||
int i;
|
||||
|
||||
tent_objects = malloc (TEMP_BATCH * sizeof (tent_obj_t));
|
||||
for (i = 0; i < TEMP_BATCH - 1; i++)
|
||||
tent_objects[i].next = &tent_objects[i + 1];
|
||||
tent_objects[i].next = 0;
|
||||
}
|
||||
tobj = tent_objects;
|
||||
tent_objects = tobj->next;
|
||||
tobj->next = 0;
|
||||
return tobj;
|
||||
}
|
||||
|
||||
static void
|
||||
free_tent_objects (tent_obj_t *tobjs)
|
||||
{
|
||||
tent_obj_t **t = &tobjs;
|
||||
|
||||
while (*t)
|
||||
t = &(*t)->next;
|
||||
*t = tent_objects;
|
||||
tent_objects = tobjs;
|
||||
}
|
||||
|
||||
void
|
||||
CL_ClearTEnts (void)
|
||||
{
|
||||
tent_t *t;
|
||||
tent_obj_t *to;
|
||||
|
||||
for (to = cl_beams; to; to = to->next) {
|
||||
for (t = to->to.beam.tents; t; t = t->next)
|
||||
t->ent.visibility.efrag = 0;
|
||||
free_temp_entities (to->to.beam.tents);
|
||||
}
|
||||
free_tent_objects (cl_beams);
|
||||
cl_beams = 0;
|
||||
|
||||
for (to = cl_explosions; to; to = to->next) {
|
||||
for (t = to->to.ex.tent; t; t = t->next)
|
||||
t->ent.visibility.efrag = 0;
|
||||
free_temp_entities (to->to.ex.tent);
|
||||
}
|
||||
free_tent_objects (cl_explosions);
|
||||
cl_explosions = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
beam_clear (beam_t *b)
|
||||
{
|
||||
if (b->tents) {
|
||||
tent_t *t;
|
||||
|
||||
for (t = b->tents; t; t = t->next) {
|
||||
r_funcs->R_RemoveEfrags (&t->ent);
|
||||
t->ent.visibility.efrag = 0;
|
||||
}
|
||||
free_temp_entities (b->tents);
|
||||
b->tents = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
beam_setup (beam_t *b, qboolean transform)
|
||||
{
|
||||
tent_t *tent;
|
||||
float forward, pitch, yaw, d;
|
||||
int ent_count;
|
||||
vec3_t dist, org, ang;
|
||||
unsigned seed;
|
||||
|
||||
// calculate pitch and yaw
|
||||
VectorSubtract (b->end, b->start, dist);
|
||||
|
||||
if (dist[1] == 0 && dist[0] == 0) {
|
||||
yaw = 0;
|
||||
if (dist[2] > 0)
|
||||
pitch = 90;
|
||||
else
|
||||
pitch = 270;
|
||||
} else {
|
||||
yaw = (int) (atan2 (dist[1], dist[0]) * 180 / M_PI);
|
||||
if (yaw < 0)
|
||||
yaw += 360;
|
||||
|
||||
forward = sqrt (dist[0] * dist[0] + dist[1] * dist[1]);
|
||||
pitch = (int) (atan2 (dist[2], forward) * 180 / M_PI);
|
||||
if (pitch < 0)
|
||||
pitch += 360;
|
||||
}
|
||||
|
||||
// add new entities for the lightning
|
||||
VectorCopy (b->start, org);
|
||||
d = VectorNormalize (dist);
|
||||
VectorScale (dist, 30, dist);
|
||||
ent_count = ceil (d / 30);
|
||||
d = 0;
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
BEAM_SEED_INTERVAL);
|
||||
|
||||
ang[ROLL] = 0;
|
||||
while (ent_count--) {
|
||||
tent = new_temp_entity ();
|
||||
tent->next = b->tents;
|
||||
b->tents = tent;
|
||||
|
||||
VectorMultAdd (org, d, dist, tent->ent.origin);
|
||||
d += 1.0;
|
||||
tent->ent.renderer.model = b->model;
|
||||
ang[PITCH] = pitch;
|
||||
ang[YAW] = yaw;
|
||||
if (transform) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
ang[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&tent->ent, ang, true);
|
||||
}
|
||||
VectorCopy (ang, tent->ent.angles);
|
||||
r_funcs->R_AddEfrags (&cl.worldmodel->brush, &tent->ent);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CL_ParseBeam (model_t *m)
|
||||
{
|
||||
tent_obj_t *to;
|
||||
beam_t *b;
|
||||
int ent;
|
||||
vec3_t start, end;
|
||||
|
||||
ent = MSG_ReadShort (net_message);
|
||||
|
||||
MSG_ReadCoordV (net_message, start);
|
||||
MSG_ReadCoordV (net_message, end);
|
||||
|
||||
to = 0;
|
||||
if (ent) {
|
||||
for (to = cl_beams; to; to = to->next)
|
||||
if (to->to.beam.entity == ent)
|
||||
break;
|
||||
}
|
||||
if (!to) {
|
||||
to = new_tent_object ();
|
||||
to->next = cl_beams;
|
||||
cl_beams = to;
|
||||
to->to.beam.tents = 0;
|
||||
to->to.beam.entity = ent;
|
||||
}
|
||||
b = &to->to.beam;
|
||||
|
||||
beam_clear (b);
|
||||
b->model = m;
|
||||
b->endtime = cl.time + 0.2;
|
||||
b->seed = rand ();
|
||||
VectorCopy (end, b->end);
|
||||
if (b->entity != cl.viewentity) {
|
||||
// this will be done in CL_UpdateBeams
|
||||
VectorCopy (start, b->start);
|
||||
beam_setup (b, true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CL_ParseTEnt (void)
|
||||
{
|
||||
byte type;
|
||||
dlight_t *dl;
|
||||
tent_obj_t *to;
|
||||
explosion_t *ex;
|
||||
int colorStart, colorLength;
|
||||
quat_t col;
|
||||
vec3_t pos;
|
||||
sfx_t *spike_sound[] = {
|
||||
cl_sfx_ric3, cl_sfx_ric3, cl_sfx_ric2, cl_sfx_ric1,
|
||||
};
|
||||
|
||||
type = MSG_ReadByte (net_message);
|
||||
switch (type) {
|
||||
case TE_WIZSPIKE: // spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_WizSpikeEffect (pos);
|
||||
S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_KNIGHTSPIKE: // spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_KnightSpikeEffect (pos);
|
||||
S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_SPIKE: // spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_SpikeEffect (pos);
|
||||
{
|
||||
int i;
|
||||
sfx_t *sound;
|
||||
|
||||
i = (rand () % 20) - 16;
|
||||
if (i >= 0)
|
||||
sound = spike_sound[i];
|
||||
else
|
||||
sound = cl_sfx_tink1;
|
||||
S_StartSound (-1, 0, sound, pos, 1, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case TE_SUPERSPIKE: // super spike hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_SuperSpikeEffect (pos);
|
||||
{
|
||||
int i;
|
||||
sfx_t *sound;
|
||||
|
||||
i = (rand () % 20) - 16;
|
||||
if (i >= 0)
|
||||
sound = spike_sound[i];
|
||||
else
|
||||
sound = cl_sfx_tink1;
|
||||
S_StartSound (-1, 0, sound, pos, 1, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case TE_EXPLOSION: // rocket explosion
|
||||
// particles
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_ParticleExplosion (pos);
|
||||
|
||||
// light
|
||||
dl = r_funcs->R_AllocDlight (0);
|
||||
if (dl) {
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
QuatSet (1.0, 0.5, 0.25, 0.7, dl->color);
|
||||
}
|
||||
|
||||
// sound
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
|
||||
// sprite
|
||||
to = new_tent_object ();
|
||||
to->next = cl_explosions;
|
||||
cl_explosions = to;
|
||||
ex = &to->to.ex;
|
||||
ex->tent = new_temp_entity ();
|
||||
|
||||
VectorCopy (pos, ex->tent->ent.origin);
|
||||
ex->start = cl.time;
|
||||
//FIXME need better model management
|
||||
if (!cl_spr_explod->cache.data)
|
||||
cl_spr_explod = Mod_ForName ("progs/s_explod.spr", true);
|
||||
ex->tent->ent.renderer.model = cl_spr_explod;
|
||||
CL_TransformEntity (&ex->tent->ent, ex->tent->ent.angles, true);
|
||||
break;
|
||||
|
||||
case TE_TAREXPLOSION: // tarbaby explosion
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_BlobExplosion (pos);
|
||||
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING1: // lightning bolts
|
||||
CL_ParseBeam (cl_mod_bolt);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING2: // lightning bolts
|
||||
CL_ParseBeam (cl_mod_bolt2);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING3: // lightning bolts
|
||||
CL_ParseBeam (cl_mod_bolt3);
|
||||
break;
|
||||
|
||||
case TE_LIGHTNING4NEH: // Nehahra lightning
|
||||
CL_ParseBeam (Mod_ForName (MSG_ReadString (net_message), true));
|
||||
break;
|
||||
|
||||
// PGM 01/21/97
|
||||
case TE_BEAM: // grappling hook beam
|
||||
CL_ParseBeam (cl_mod_beam);
|
||||
break;
|
||||
// PGM 01/21/97
|
||||
|
||||
case TE_LAVASPLASH:
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_LavaSplash (pos);
|
||||
break;
|
||||
|
||||
case TE_TELEPORT:
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_TeleportSplash (pos);
|
||||
break;
|
||||
|
||||
case TE_EXPLOSION2: // color mapped explosion
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
colorStart = MSG_ReadByte (net_message);
|
||||
colorLength = MSG_ReadByte (net_message);
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
r_funcs->particles->R_ParticleExplosion2 (pos, colorStart,
|
||||
colorLength);
|
||||
dl = r_funcs->R_AllocDlight (0);
|
||||
if (!dl)
|
||||
break;
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
colorStart = (colorStart + (rand () % colorLength)) * 3;
|
||||
VectorScale (&r_data->vid->palette[colorStart], 1.0 / 255.0,
|
||||
dl->color);
|
||||
dl->color[3] = 0.7;
|
||||
break;
|
||||
|
||||
case TE_EXPLOSION3: // Nehahra colored light explosion
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
MSG_ReadCoordV (net_message, col); // OUCH!
|
||||
col[3] = 0.7;
|
||||
r_funcs->particles->R_ParticleExplosion (pos);
|
||||
S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
|
||||
dl = r_funcs->R_AllocDlight (0);
|
||||
if (dl) {
|
||||
VectorCopy (pos, dl->origin);
|
||||
dl->radius = 350;
|
||||
dl->die = cl.time + 0.5;
|
||||
dl->decay = 300;
|
||||
QuatCopy (col, dl->color);
|
||||
}
|
||||
break;
|
||||
|
||||
case TE_GUNSHOT: // bullet hitting wall
|
||||
MSG_ReadCoordV (net_message, pos);
|
||||
r_funcs->particles->R_GunshotEffect (pos, 20);
|
||||
break;
|
||||
|
||||
default:
|
||||
Sys_Error ("CL_ParseTEnt: bad type %d", type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CL_UpdateBeams (void)
|
||||
{
|
||||
tent_obj_t **to;
|
||||
beam_t *b;
|
||||
unsigned seed;
|
||||
tent_t *t;
|
||||
|
||||
// update lightning
|
||||
for (to = &cl_beams; *to; ) {
|
||||
b = &(*to)->to.beam;
|
||||
if (!b->endtime)
|
||||
continue;
|
||||
if (!b->model || b->endtime < cl.time) {
|
||||
tent_obj_t *_to;
|
||||
b->endtime = 0;
|
||||
beam_clear (b);
|
||||
_to = *to;
|
||||
*to = _to->next;
|
||||
_to->next = tent_objects;
|
||||
tent_objects = _to;
|
||||
continue;
|
||||
}
|
||||
to = &(*to)->next;
|
||||
|
||||
// if coming from the player, update the start position
|
||||
if (b->entity == cl.viewentity) {
|
||||
beam_clear (b);
|
||||
VectorCopy (cl_entities[cl.viewentity].origin, b->start);
|
||||
beam_setup (b, false);
|
||||
}
|
||||
|
||||
seed = b->seed + ((int) (cl.time * BEAM_SEED_INTERVAL) %
|
||||
BEAM_SEED_INTERVAL);
|
||||
|
||||
// add new entities for the lightning
|
||||
for (t = b->tents; t; t = t->next) {
|
||||
seed = seed * BEAM_SEED_PRIME;
|
||||
t->ent.angles[ROLL] = seed % 360;
|
||||
CL_TransformEntity (&t->ent, t->ent.angles, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
CL_UpdateExplosions (void)
|
||||
{
|
||||
int f;
|
||||
tent_obj_t **to;
|
||||
explosion_t *ex;
|
||||
entity_t *ent;
|
||||
|
||||
for (to = &cl_explosions; *to; ) {
|
||||
ex = &(*to)->to.ex;
|
||||
ent = &ex->tent->ent;
|
||||
f = 10 * (cl.time - ex->start);
|
||||
if (f >= ent->renderer.model->numframes) {
|
||||
tent_obj_t *_to;
|
||||
r_funcs->R_RemoveEfrags (ent);
|
||||
ent->visibility.efrag = 0;
|
||||
free_temp_entities (ex->tent);
|
||||
_to = *to;
|
||||
*to = _to->next;
|
||||
_to->next = tent_objects;
|
||||
tent_objects = _to;
|
||||
continue;
|
||||
}
|
||||
to = &(*to)->next;
|
||||
|
||||
ent->animation.frame = f;
|
||||
if (!ent->visibility.efrag)
|
||||
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CL_UpdateTEnts (void)
|
||||
{
|
||||
CL_UpdateBeams ();
|
||||
CL_UpdateExplosions ();
|
||||
}
|
||||
|
||||
/*
|
||||
CL_ParseParticleEffect
|
||||
|
||||
Parse an effect out of the server message
|
||||
*/
|
||||
void
|
||||
CL_ParseParticleEffect (void)
|
||||
{
|
||||
int i, count, color;
|
||||
vec3_t org, dir;
|
||||
|
||||
MSG_ReadCoordV (net_message, org);
|
||||
for (i = 0; i < 3; i++)
|
||||
dir[i] = ((signed char) MSG_ReadByte (net_message)) * (15.0 / 16.0);
|
||||
count = MSG_ReadByte (net_message);
|
||||
color = MSG_ReadByte (net_message);
|
||||
|
||||
if (count == 255)
|
||||
r_funcs->particles->R_ParticleExplosion (org);
|
||||
else
|
||||
r_funcs->particles->R_RunParticleEffect (org, dir, color, count);
|
||||
}
|
|
@ -728,7 +728,7 @@ V_CalcRefdef (void)
|
|||
if (cl.chase && chase_active->int_val)
|
||||
Chase_Update ();
|
||||
|
||||
CL_TransformEntity (view, view->angles, true);
|
||||
CL_TransformEntity (view, view->angles);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -11,7 +11,6 @@ EXTRA_DIST += \
|
|||
qw/include/cl_pred.h \
|
||||
qw/include/cl_skin.h \
|
||||
qw/include/cl_slist.h \
|
||||
qw/include/cl_tent.h \
|
||||
qw/include/client.h \
|
||||
qw/include/crudefile.h \
|
||||
qw/include/game.h \
|
||||
|
|
|
@ -34,11 +34,9 @@
|
|||
void CL_SetSolidPlayers (int playernum);
|
||||
void CL_ClearPredict (void);
|
||||
void CL_SetUpPlayerPrediction(qboolean dopred);
|
||||
void CL_TransformEntity (struct entity_s * ent, const vec3_t angles,
|
||||
qboolean force);
|
||||
void CL_ClearEnts (void);
|
||||
void CL_EmitEntities (void);
|
||||
void CL_ClearProjectiles (void);
|
||||
void CL_ParseProjectiles (qboolean nail2);
|
||||
void CL_ParsePacketEntities (qboolean delta);
|
||||
void CL_SetSolidEntities (void);
|
||||
void CL_ParsePlayerinfo (void);
|
||||
|
|
|
@ -40,7 +40,6 @@ extern int parsecountmod;
|
|||
extern double parsecounttime;
|
||||
extern int cl_playerindex;
|
||||
extern int cl_flagindex;
|
||||
extern int cl_spikeindex;
|
||||
extern int viewentity;
|
||||
extern int cl_h_playerindex;
|
||||
extern int cl_gib1index;
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
client.h
|
||||
|
||||
Client definitions
|
||||
|
||||
Copyright (C) 1996-1997 Id Software, Inc.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _CL_TENT_H
|
||||
#define _CL_TENT_H
|
||||
|
||||
void CL_TEnts_Init (void);
|
||||
void CL_ClearEnts (void);
|
||||
void CL_ClearTEnts (void);
|
||||
void CL_Init_Entity (struct entity_s *ent);
|
||||
void CL_ParseTEnt (void);
|
||||
void CL_UpdateTEnts (void);
|
||||
|
||||
#endif
|
|
@ -103,7 +103,7 @@ qw_source_libqw_client_a_SOURCES= \
|
|||
qw/source/cl_cam.c qw/source/cl_chase.c qw/source/cl_chat.c qw/source/cl_cmd.c qw/source/cl_cvar.c qw/source/cl_demo.c \
|
||||
qw/source/cl_entparse.c qw/source/cl_ents.c qw/source/cl_http.c qw/source/cl_input.c qw/source/cl_main.c qw/source/cl_ngraph.c \
|
||||
qw/source/cl_parse.c qw/source/cl_pred.c qw/source/cl_rss.c qw/source/cl_screen.c qw/source/cl_skin.c qw/source/cl_slist.c \
|
||||
qw/source/cl_tent.c qw/source/cl_view.c \
|
||||
qw/source/cl_view.c \
|
||||
qw/source/locs.c qw/source/sbar.c qw/source/teamplay.c
|
||||
|
||||
# Software-rendering clients
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "compat.h"
|
||||
#include "clview.h"
|
||||
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
#include "qw/msg_ucmd.h"
|
||||
#include "qw/pmove.h"
|
||||
#include "qw/bothdefs.h"
|
||||
|
@ -54,7 +56,6 @@
|
|||
#include "qw/include/cl_main.h"
|
||||
#include "qw/include/cl_parse.h"
|
||||
#include "qw/include/cl_pred.h"
|
||||
#include "qw/include/cl_tent.h"
|
||||
#include "qw/include/host.h"
|
||||
|
||||
static struct predicted_player {
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
#include "clview.h"
|
||||
#include "d_iface.h"
|
||||
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
#include "qw/bothdefs.h"
|
||||
#include "qw/msg_ucmd.h"
|
||||
#include "qw/pmove.h"
|
||||
|
@ -57,7 +59,6 @@
|
|||
#include "qw/include/cl_main.h"
|
||||
#include "qw/include/cl_parse.h"
|
||||
#include "qw/include/cl_pred.h"
|
||||
#include "qw/include/cl_tent.h"
|
||||
#include "qw/include/host.h"
|
||||
|
||||
entity_t cl_player_ents[MAX_CLIENTS];
|
||||
|
@ -170,36 +171,6 @@ is_gib (entity_state_t *s1)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
CL_TransformEntity (entity_t *ent, const vec3_t angles, qboolean force)
|
||||
{
|
||||
union {
|
||||
quat_t q;
|
||||
vec4f_t v;
|
||||
} rotation;
|
||||
vec4f_t position;
|
||||
vec4f_t scale;
|
||||
|
||||
VectorCopy (ent->origin, position);
|
||||
position[3] = 1;
|
||||
VectorSet (ent->scale, ent->scale, ent->scale, scale);
|
||||
scale[3] = 1;
|
||||
if (VectorIsZero (angles)) {
|
||||
QuatSet (0, 0, 0, 1, rotation.q);
|
||||
} else {
|
||||
vec3_t ang;
|
||||
VectorCopy (angles, ang);
|
||||
if (ent->renderer.model && ent->renderer.model->type == mod_alias) {
|
||||
// stupid quake bug
|
||||
// why, oh, why, do alias models pitch in the opposite direction
|
||||
// to everything else?
|
||||
ang[PITCH] = -ang[PITCH];
|
||||
}
|
||||
AngleQuat (ang, rotation.q);
|
||||
}
|
||||
Transform_SetLocalTransform (ent->transform, scale, rotation.v, position);
|
||||
}
|
||||
|
||||
static void
|
||||
CL_ModelEffects (entity_t *ent, int num, int glow_color)
|
||||
{
|
||||
|
@ -342,7 +313,7 @@ CL_LinkPacketEntities (void)
|
|||
animation->pose1 = animation->pose2 = -1;
|
||||
VectorCopy (new->origin, ent->origin);
|
||||
if (!(renderer->model->flags & EF_ROTATE))
|
||||
CL_TransformEntity (ent, new->angles, true);
|
||||
CL_TransformEntity (ent, new->angles);
|
||||
if (i != cl.viewentity || chase_active->int_val) {
|
||||
if (ent->visibility.efrag) {
|
||||
r_funcs->R_RemoveEfrags (ent);
|
||||
|
@ -360,7 +331,7 @@ CL_LinkPacketEntities (void)
|
|||
// assume a teleportation, not a motion
|
||||
VectorCopy (new->origin, ent->origin);
|
||||
if (!(renderer->model->flags & EF_ROTATE)) {
|
||||
CL_TransformEntity (ent, new->angles, true);
|
||||
CL_TransformEntity (ent, new->angles);
|
||||
}
|
||||
animation->pose1 = animation->pose2 = -1;
|
||||
} else {
|
||||
|
@ -376,7 +347,7 @@ CL_LinkPacketEntities (void)
|
|||
d[j] += 360;
|
||||
}
|
||||
VectorMultAdd (old->angles, f, d, angles);
|
||||
CL_TransformEntity (ent, angles, false);
|
||||
CL_TransformEntity (ent, angles);
|
||||
}
|
||||
}
|
||||
if (i != cl.viewentity || chase_active->int_val) {
|
||||
|
@ -400,7 +371,7 @@ CL_LinkPacketEntities (void)
|
|||
angles[PITCH] = 0;
|
||||
angles[YAW] = anglemod (100 * cl.time);
|
||||
angles[ROLL] = 0;
|
||||
CL_TransformEntity (ent, angles, false);
|
||||
CL_TransformEntity (ent, angles);
|
||||
}
|
||||
//CL_EntityEffects (i, ent, new);
|
||||
//CL_NewDlight (i, ent->origin, new->effects, 0, 0);
|
||||
|
@ -567,7 +538,7 @@ CL_LinkPlayers (void)
|
|||
ent->animation.frame = state->pls.frame;
|
||||
ent->renderer.skinnum = state->pls.skinnum;
|
||||
|
||||
CL_TransformEntity (ent, ang, false);
|
||||
CL_TransformEntity (ent, ang);
|
||||
|
||||
ent->renderer.min_light = 0;
|
||||
ent->renderer.fullbright = 0;
|
||||
|
@ -611,9 +582,13 @@ CL_EmitEntities (void)
|
|||
if (!cl.validsequence)
|
||||
return;
|
||||
|
||||
TEntContext_t tentCtx = {
|
||||
{VectorExpand (cl.simorg), 1}, cl.worldmodel, cl.viewentity
|
||||
};
|
||||
|
||||
CL_LinkPlayers ();
|
||||
CL_LinkPacketEntities ();
|
||||
CL_UpdateTEnts ();
|
||||
CL_UpdateTEnts (cl.time, &tentCtx);
|
||||
if (cl_draw_locs->int_val) {
|
||||
//FIXME custom ent rendering code would be nice
|
||||
dlight_t *dl;
|
||||
|
|
|
@ -96,6 +96,8 @@
|
|||
#include "compat.h"
|
||||
#include "sbar.h"
|
||||
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
#include "qw/bothdefs.h"
|
||||
#include "qw/pmove.h"
|
||||
|
||||
|
@ -110,7 +112,6 @@
|
|||
#include "qw/include/cl_pred.h"
|
||||
#include "qw/include/cl_skin.h"
|
||||
#include "qw/include/cl_slist.h"
|
||||
#include "qw/include/cl_tent.h"
|
||||
#include "qw/include/client.h"
|
||||
#include "qw/include/game.h"
|
||||
#include "qw/include/host.h"
|
||||
|
|
|
@ -65,6 +65,8 @@
|
|||
#include "clview.h"
|
||||
#include "sbar.h"
|
||||
|
||||
#include "client/temp_entities.h"
|
||||
|
||||
#include "qw/bothdefs.h"
|
||||
#include "qw/pmove.h"
|
||||
#include "qw/protocol.h"
|
||||
|
@ -77,7 +79,6 @@
|
|||
#include "qw/include/cl_main.h"
|
||||
#include "qw/include/cl_parse.h"
|
||||
#include "qw/include/cl_skin.h"
|
||||
#include "qw/include/cl_tent.h"
|
||||
#include "qw/include/client.h"
|
||||
#include "qw/include/host.h"
|
||||
#include "qw/include/map_cfg.h"
|
||||
|
@ -161,7 +162,7 @@ int oldparsecountmod;
|
|||
int parsecountmod;
|
||||
double parsecounttime;
|
||||
|
||||
int cl_spikeindex, cl_playerindex, cl_flagindex;
|
||||
int cl_playerindex, cl_flagindex;
|
||||
int cl_h_playerindex, cl_gib1index, cl_gib2index, cl_gib3index;
|
||||
|
||||
int packet_latency[NET_TIMINGS];
|
||||
|
@ -437,7 +438,6 @@ Sound_NextDownload (void)
|
|||
// done with sounds, request models now
|
||||
memset (cl.model_precache, 0, sizeof (cl.model_precache));
|
||||
cl_playerindex = -1;
|
||||
cl_spikeindex = -1;
|
||||
cl_flagindex = -1;
|
||||
cl_h_playerindex = -1;
|
||||
cl_gib1index = cl_gib2index = cl_gib3index = -1;
|
||||
|
@ -906,9 +906,7 @@ CL_ParseModellist (void)
|
|||
Host_Error ("Server sent too many model_precache");
|
||||
strcpy (cl.model_name[cl.nummodels], str);
|
||||
|
||||
if (!strcmp (cl.model_name[cl.nummodels], "progs/spike.mdl"))
|
||||
cl_spikeindex = cl.nummodels;
|
||||
else if (!strcmp (cl.model_name[cl.nummodels], "progs/player.mdl"))
|
||||
if (!strcmp (cl.model_name[cl.nummodels], "progs/player.mdl"))
|
||||
cl_playerindex = cl.nummodels;
|
||||
else if (!strcmp (cl.model_name[cl.nummodels], "progs/flag.mdl"))
|
||||
cl_flagindex = cl.nummodels;
|
||||
|
@ -984,7 +982,7 @@ CL_ParseStatic (void)
|
|||
ent->renderer.skinnum = es.skinnum;
|
||||
|
||||
VectorCopy (es.origin, ent->origin);
|
||||
CL_TransformEntity (ent, es.angles, true);
|
||||
CL_TransformEntity (ent, es.angles);
|
||||
|
||||
r_funcs->R_AddEfrags (&cl.worldmodel->brush, ent);
|
||||
}
|
||||
|
@ -1305,6 +1303,9 @@ CL_ParseServerMessage (void)
|
|||
int cmd = 0, i, j;
|
||||
const char *str;
|
||||
static dstring_t *stuffbuf;
|
||||
TEntContext_t tentCtx = {
|
||||
{VectorExpand (cl.simorg), 1}, cl.worldmodel, cl.viewentity
|
||||
};
|
||||
|
||||
received_framecount = host_framecount;
|
||||
cl.last_servermessage = realtime;
|
||||
|
@ -1507,7 +1508,7 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_temp_entity:
|
||||
CL_ParseTEnt ();
|
||||
CL_ParseTEnt_qw (net_message, cl.time, &tentCtx);
|
||||
break;
|
||||
|
||||
case svc_setpause:
|
||||
|
@ -1639,7 +1640,7 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_nails:
|
||||
CL_ParseProjectiles (false);
|
||||
CL_ParseProjectiles (net_message, false, &tentCtx);
|
||||
break;
|
||||
|
||||
case svc_chokecount: // some preceding packets were choked
|
||||
|
@ -1690,7 +1691,7 @@ CL_ParseServerMessage (void)
|
|||
break;
|
||||
|
||||
case svc_nails2: // FIXME from qwex
|
||||
CL_ParseProjectiles (true);
|
||||
CL_ParseProjectiles (net_message, true, &tentCtx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -731,7 +731,7 @@ V_CalcRefdef (void)
|
|||
if (cl.chase && chase_active->int_val)
|
||||
Chase_Update ();
|
||||
|
||||
CL_TransformEntity (view, view->angles, true);
|
||||
CL_TransformEntity (view, view->angles);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in a new issue