2835 lines
90 KiB
C
2835 lines
90 KiB
C
|
|
//**************************************************************************
|
|
//**
|
|
//** cl_effect.c
|
|
//**
|
|
//** Client side effects.
|
|
//**
|
|
//** $Header: /HexenWorld/Client/cl_effect.c 89 5/25/98 1:29p Mgummelt $
|
|
//**
|
|
//**************************************************************************
|
|
|
|
// HEADER FILES ------------------------------------------------------------
|
|
|
|
#include "quakedef.h"
|
|
|
|
// MACROS ------------------------------------------------------------------
|
|
|
|
// TYPES -------------------------------------------------------------------
|
|
|
|
#define MAX_EFFECT_ENTITIES 256
|
|
|
|
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
|
extern void CreateStream(int type, int ent, int flags, int tag, float duration, int skin, vec3_t source, vec3_t dest);
|
|
extern void CLTENT_XbowImpact(vec3_t pos, vec3_t vel, int chType, int damage, int arrowType);//so xbow effect can use tents
|
|
extern void CLTENT_SpawnDeathBubble(vec3_t pos);
|
|
entity_state_t *FindState(int EntNum);
|
|
int TempSoundChannel();
|
|
void setseed(unsigned int seed);
|
|
float seedrand(void);
|
|
|
|
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
|
|
|
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
|
|
|
|
static int NewEffectEntity(void);
|
|
static void FreeEffectEntity(int index);
|
|
|
|
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
|
|
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
|
|
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
|
|
|
static entity_t EffectEntities[MAX_EFFECT_ENTITIES];
|
|
static qboolean EntityUsed[MAX_EFFECT_ENTITIES];
|
|
static int EffectEntityCount;
|
|
|
|
// CODE --------------------------------------------------------------------
|
|
|
|
static void vectoangles(vec3_t vec, vec3_t ang)
|
|
{
|
|
float forward;
|
|
float yaw, pitch;
|
|
|
|
if (vec[1] == 0 && vec[0] == 0)
|
|
{
|
|
yaw = 0;
|
|
if (vec[2] > 0)
|
|
pitch = 90;
|
|
else
|
|
pitch = 270;
|
|
}
|
|
else
|
|
{
|
|
yaw = (int) (atan2(vec[1], vec[0]) * 180 / M_PI);
|
|
if (yaw < 0)
|
|
yaw += 360;
|
|
|
|
forward = sqrt (vec[0]*vec[0] + vec[1]*vec[1]);
|
|
pitch = (int) (atan2(vec[2], forward) * 180 / M_PI);
|
|
if (pitch < 0)
|
|
pitch += 360;
|
|
}
|
|
|
|
ang[0] = pitch;
|
|
ang[1] = yaw;
|
|
ang[2] = 0;
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// CL_InitTEnts
|
|
//
|
|
//==========================================================================
|
|
|
|
sfx_t *cl_fxsfx_bone;
|
|
sfx_t *cl_fxsfx_bonefpow;
|
|
sfx_t *cl_fxsfx_xbowshoot;
|
|
sfx_t *cl_fxsfx_xbowfshoot;
|
|
sfx_t *cl_fxsfx_explode;
|
|
sfx_t *cl_fxsfx_mmfire;
|
|
sfx_t *cl_fxsfx_eidolon;
|
|
sfx_t *cl_fxsfx_scarabwhoosh;
|
|
sfx_t *cl_fxsfx_scarabgrab;
|
|
sfx_t *cl_fxsfx_scarabhome;
|
|
sfx_t *cl_fxsfx_scarabrip;
|
|
sfx_t *cl_fxsfx_scarabbyebye;
|
|
sfx_t *cl_fxsfx_ravensplit;
|
|
sfx_t *cl_fxsfx_ravenfire;
|
|
sfx_t *cl_fxsfx_ravengo;
|
|
sfx_t *cl_fxsfx_drillashoot;
|
|
sfx_t *cl_fxsfx_drillaspin;
|
|
sfx_t *cl_fxsfx_drillameat;
|
|
|
|
|
|
sfx_t *cl_fxsfx_arr2flsh;
|
|
sfx_t *cl_fxsfx_arr2wood;
|
|
sfx_t *cl_fxsfx_met2stn;
|
|
|
|
sfx_t *cl_fxsfx_ripple;
|
|
sfx_t *cl_fxsfx_splash;
|
|
void CL_InitEffects(void)
|
|
{
|
|
cl_fxsfx_bone = S_PrecacheSound ("necro/bonefnrm.wav");
|
|
cl_fxsfx_bonefpow = S_PrecacheSound ("necro/bonefpow.wav");
|
|
cl_fxsfx_xbowshoot = S_PrecacheSound ("assassin/firebolt.wav");
|
|
cl_fxsfx_xbowfshoot = S_PrecacheSound ("assassin/firefblt.wav");
|
|
cl_fxsfx_explode = S_PrecacheSound ("weapons/explode.wav");
|
|
cl_fxsfx_mmfire = S_PrecacheSound ("necro/mmfire.wav");
|
|
cl_fxsfx_eidolon = S_PrecacheSound ("eidolon/spell.wav");
|
|
cl_fxsfx_scarabwhoosh = S_PrecacheSound ("misc/whoosh.wav");
|
|
cl_fxsfx_scarabgrab = S_PrecacheSound ("assassin/chn2flsh.wav");
|
|
cl_fxsfx_scarabhome = S_PrecacheSound ("assassin/chain.wav");
|
|
cl_fxsfx_scarabrip = S_PrecacheSound ("assassin/chntear.wav");
|
|
cl_fxsfx_scarabbyebye = S_PrecacheSound ("items/itmspawn.wav");
|
|
cl_fxsfx_ravensplit = S_PrecacheSound ("raven/split.wav");
|
|
cl_fxsfx_ravenfire = S_PrecacheSound ("raven/rfire1.wav");
|
|
cl_fxsfx_ravengo = S_PrecacheSound ("raven/ravengo.wav");
|
|
cl_fxsfx_drillashoot = S_PrecacheSound ("assassin/pincer.wav");
|
|
cl_fxsfx_drillaspin = S_PrecacheSound ("assassin/spin.wav");
|
|
cl_fxsfx_drillameat = S_PrecacheSound ("assassin/core.wav");
|
|
|
|
cl_fxsfx_arr2flsh = S_PrecacheSound ("assassin/arr2flsh.wav");
|
|
cl_fxsfx_arr2wood = S_PrecacheSound ("assassin/arr2wood.wav");
|
|
cl_fxsfx_met2stn = S_PrecacheSound ("weapons/met2stn.wav");
|
|
|
|
cl_fxsfx_ripple = S_PrecacheSound ("misc/drip.wav");
|
|
cl_fxsfx_splash = S_PrecacheSound ("raven/outwater.wav");
|
|
}
|
|
|
|
void CL_ClearEffects(void)
|
|
{
|
|
memset(cl.Effects,0,sizeof(cl.Effects));
|
|
memset(EntityUsed,0,sizeof(EntityUsed));
|
|
EffectEntityCount = 0;
|
|
}
|
|
|
|
void CL_FreeEffect(int index)
|
|
{
|
|
int i;
|
|
|
|
switch(cl.Effects[index].type)
|
|
{
|
|
case CE_RAIN:
|
|
break;
|
|
|
|
case CE_FOUNTAIN:
|
|
break;
|
|
|
|
case CE_QUAKE:
|
|
break;
|
|
|
|
case CE_TELESMK1:
|
|
FreeEffectEntity(cl.Effects[index].Smoke.entity_index2);
|
|
//no break wanted here
|
|
case CE_WHITE_SMOKE:
|
|
case CE_GREEN_SMOKE:
|
|
case CE_GREY_SMOKE:
|
|
case CE_RED_SMOKE:
|
|
case CE_SLOW_WHITE_SMOKE:
|
|
case CE_TELESMK2:
|
|
case CE_GHOST:
|
|
case CE_REDCLOUD:
|
|
case CE_ACID_MUZZFL:
|
|
case CE_FLAMESTREAM:
|
|
case CE_FLAMEWALL:
|
|
case CE_FLAMEWALL2:
|
|
case CE_ONFIRE:
|
|
case CE_RIPPLE:
|
|
FreeEffectEntity(cl.Effects[index].Smoke.entity_index);
|
|
break;
|
|
|
|
case CE_DEATHBUBBLES:
|
|
break;
|
|
// Just go through animation and then remove
|
|
case CE_SM_WHITE_FLASH:
|
|
case CE_YELLOWRED_FLASH:
|
|
case CE_BLUESPARK:
|
|
case CE_YELLOWSPARK:
|
|
case CE_SM_CIRCLE_EXP:
|
|
case CE_BG_CIRCLE_EXP:
|
|
case CE_SM_EXPLOSION:
|
|
case CE_SM_EXPLOSION2:
|
|
case CE_BG_EXPLOSION:
|
|
case CE_FLOOR_EXPLOSION:
|
|
case CE_BLUE_EXPLOSION:
|
|
case CE_REDSPARK:
|
|
case CE_GREENSPARK:
|
|
case CE_ICEHIT:
|
|
case CE_MEDUSA_HIT:
|
|
case CE_MEZZO_REFLECT:
|
|
case CE_FLOOR_EXPLOSION2:
|
|
case CE_XBOW_EXPLOSION:
|
|
case CE_NEW_EXPLOSION:
|
|
case CE_MAGIC_MISSILE_EXPLOSION:
|
|
case CE_BONE_EXPLOSION:
|
|
case CE_BLDRN_EXPL:
|
|
case CE_BRN_BOUNCE:
|
|
case CE_LSHOCK:
|
|
case CE_ACID_HIT:
|
|
case CE_ACID_SPLAT:
|
|
case CE_ACID_EXPL:
|
|
case CE_LBALL_EXPL:
|
|
case CE_FBOOM:
|
|
case CE_BOMB:
|
|
case CE_FIREWALL_SMALL:
|
|
case CE_FIREWALL_MEDIUM:
|
|
case CE_FIREWALL_LARGE:
|
|
FreeEffectEntity(cl.Effects[index].Smoke.entity_index);
|
|
break;
|
|
|
|
// Go forward then backward through animation then remove
|
|
case CE_WHITE_FLASH:
|
|
case CE_BLUE_FLASH:
|
|
case CE_SM_BLUE_FLASH:
|
|
case CE_HWSPLITFLASH:
|
|
case CE_RED_FLASH:
|
|
FreeEffectEntity(cl.Effects[index].Flash.entity_index);
|
|
break;
|
|
|
|
case CE_RIDER_DEATH:
|
|
break;
|
|
|
|
case CE_TELEPORTERPUFFS:
|
|
for (i=0;i<8;++i)
|
|
FreeEffectEntity(cl.Effects[index].Teleporter.entity_index[i]);
|
|
break;
|
|
|
|
case CE_HWSHEEPINATOR:
|
|
for (i=0;i<5;++i)
|
|
FreeEffectEntity(cl.Effects[index].Xbow.ent[i]);
|
|
break;
|
|
|
|
case CE_HWXBOWSHOOT:
|
|
for (i=0;i<cl.Effects[index].Xbow.bolts;++i)
|
|
FreeEffectEntity(cl.Effects[index].Xbow.ent[i]);
|
|
break;
|
|
|
|
case CE_TELEPORTERBODY:
|
|
FreeEffectEntity(cl.Effects[index].Teleporter.entity_index[0]);
|
|
break;
|
|
|
|
case CE_HWDRILLA:
|
|
case CE_BONESHARD:
|
|
case CE_BONESHRAPNEL:
|
|
case CE_HWBONEBALL:
|
|
case CE_HWRAVENSTAFF:
|
|
case CE_HWRAVENPOWER:
|
|
FreeEffectEntity(cl.Effects[index].Missile.entity_index);
|
|
break;
|
|
case CE_TRIPMINESTILL:
|
|
// Con_DPrintf("Ditching chain\n");
|
|
FreeEffectEntity(cl.Effects[index].Chain.ent1);
|
|
break;
|
|
case CE_SCARABCHAIN:
|
|
case CE_TRIPMINE:
|
|
FreeEffectEntity(cl.Effects[index].Chain.ent1);
|
|
break;
|
|
case CE_HWMISSILESTAR:
|
|
FreeEffectEntity(cl.Effects[index].Star.ent2);
|
|
//no break wanted here
|
|
case CE_HWEIDOLONSTAR:
|
|
FreeEffectEntity(cl.Effects[index].Star.ent1);
|
|
FreeEffectEntity(cl.Effects[index].Star.entity_index);
|
|
|
|
break;
|
|
default:
|
|
// Con_Printf("Freeing unknown effect type\n");
|
|
break;
|
|
}
|
|
|
|
memset(&cl.Effects[index],0,sizeof(struct EffectT));
|
|
}
|
|
|
|
//==========================================================================
|
|
//
|
|
// CL_ParseEffect
|
|
//
|
|
//==========================================================================
|
|
|
|
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
|
|
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
|
|
void CL_ParseEffect(void)
|
|
{
|
|
int index,i;
|
|
qboolean ImmediateFree;
|
|
entity_t *ent;
|
|
int dir;
|
|
float angleval, sinval, cosval;
|
|
float skinnum;
|
|
int play_sound;
|
|
vec3_t forward, right, up, vtemp;
|
|
vec3_t forward2, right2, up2;
|
|
vec3_t origin;
|
|
|
|
ImmediateFree = false;
|
|
|
|
index = MSG_ReadByte();
|
|
if (cl.Effects[index].type)
|
|
CL_FreeEffect(index);
|
|
|
|
memset(&cl.Effects[index],0,sizeof(struct EffectT));
|
|
|
|
cl.Effects[index].type = MSG_ReadByte();
|
|
|
|
switch(cl.Effects[index].type)
|
|
{
|
|
case CE_RAIN:
|
|
cl.Effects[index].Rain.min_org[0] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.min_org[1] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.min_org[2] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.max_org[0] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.max_org[1] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.max_org[2] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.e_size[0] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.e_size[1] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.e_size[2] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.dir[0] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.dir[1] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.dir[2] = MSG_ReadCoord();
|
|
cl.Effects[index].Rain.color = MSG_ReadShort();
|
|
cl.Effects[index].Rain.count = MSG_ReadShort();
|
|
cl.Effects[index].Rain.wait = MSG_ReadFloat();
|
|
break;
|
|
|
|
case CE_FOUNTAIN:
|
|
cl.Effects[index].Fountain.pos[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Fountain.pos[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Fountain.pos[2] = MSG_ReadCoord ();
|
|
cl.Effects[index].Fountain.angle[0] = MSG_ReadAngle ();
|
|
cl.Effects[index].Fountain.angle[1] = MSG_ReadAngle ();
|
|
cl.Effects[index].Fountain.angle[2] = MSG_ReadAngle ();
|
|
cl.Effects[index].Fountain.movedir[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Fountain.movedir[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Fountain.movedir[2] = MSG_ReadCoord ();
|
|
cl.Effects[index].Fountain.color = MSG_ReadShort ();
|
|
cl.Effects[index].Fountain.cnt = MSG_ReadByte ();
|
|
AngleVectors (cl.Effects[index].Fountain.angle,
|
|
cl.Effects[index].Fountain.vforward,
|
|
cl.Effects[index].Fountain.vright,
|
|
cl.Effects[index].Fountain.vup);
|
|
break;
|
|
|
|
case CE_QUAKE:
|
|
cl.Effects[index].Quake.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Quake.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Quake.origin[2] = MSG_ReadCoord ();
|
|
cl.Effects[index].Quake.radius = MSG_ReadFloat ();
|
|
break;
|
|
|
|
case CE_WHITE_SMOKE:
|
|
case CE_GREEN_SMOKE:
|
|
case CE_GREY_SMOKE:
|
|
case CE_RED_SMOKE:
|
|
case CE_SLOW_WHITE_SMOKE:
|
|
case CE_TELESMK1:
|
|
case CE_TELESMK2:
|
|
case CE_GHOST:
|
|
case CE_REDCLOUD:
|
|
case CE_ACID_MUZZFL:
|
|
case CE_FLAMESTREAM:
|
|
case CE_FLAMEWALL:
|
|
case CE_FLAMEWALL2:
|
|
case CE_ONFIRE:
|
|
case CE_RIPPLE:
|
|
cl.Effects[index].Smoke.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Smoke.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Smoke.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Smoke.velocity[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Smoke.velocity[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Smoke.velocity[2] = MSG_ReadFloat ();
|
|
|
|
cl.Effects[index].Smoke.framelength = MSG_ReadFloat ();
|
|
|
|
if ((cl.Effects[index].Smoke.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index];
|
|
VectorCopy(cl.Effects[index].Smoke.origin, ent->origin);
|
|
|
|
if ((cl.Effects[index].type == CE_WHITE_SMOKE) ||
|
|
(cl.Effects[index].type == CE_SLOW_WHITE_SMOKE))
|
|
ent->model = Mod_ForName("models/whtsmk1.spr", true);
|
|
else if (cl.Effects[index].type == CE_GREEN_SMOKE)
|
|
ent->model = Mod_ForName("models/grnsmk1.spr", true);
|
|
else if (cl.Effects[index].type == CE_GREY_SMOKE)
|
|
ent->model = Mod_ForName("models/grysmk1.spr", true);
|
|
else if (cl.Effects[index].type == CE_RED_SMOKE)
|
|
ent->model = Mod_ForName("models/redsmk1.spr", true);
|
|
else if (cl.Effects[index].type == CE_TELESMK1)
|
|
ent->model = Mod_ForName("models/telesmk1.spr", true);
|
|
else if (cl.Effects[index].type == CE_TELESMK2)
|
|
ent->model = Mod_ForName("models/telesmk2.spr", true);
|
|
else if (cl.Effects[index].type == CE_REDCLOUD)
|
|
ent->model = Mod_ForName("models/rcloud.spr", true);
|
|
else if (cl.Effects[index].type == CE_FLAMESTREAM)
|
|
ent->model = Mod_ForName("models/flamestr.spr", true);
|
|
else if (cl.Effects[index].type == CE_ACID_MUZZFL)
|
|
{
|
|
ent->model = Mod_ForName("models/muzzle1.spr", true);
|
|
ent->drawflags=DRF_TRANSLUCENT|MLS_ABSLIGHT;
|
|
ent->abslight=0.2;
|
|
}
|
|
else if (cl.Effects[index].type == CE_FLAMEWALL)
|
|
ent->model = Mod_ForName("models/firewal1.spr", true);
|
|
else if (cl.Effects[index].type == CE_FLAMEWALL2)
|
|
ent->model = Mod_ForName("models/firewal2.spr", true);
|
|
else if (cl.Effects[index].type == CE_ONFIRE)
|
|
{
|
|
float rdm = rand() & 3;
|
|
|
|
if (rdm < 1)
|
|
ent->model = Mod_ForName("models/firewal1.spr", true);
|
|
else if (rdm < 2)
|
|
ent->model = Mod_ForName("models/firewal2.spr", true);
|
|
else
|
|
ent->model = Mod_ForName("models/firewal3.spr", true);
|
|
|
|
ent->drawflags = DRF_TRANSLUCENT;
|
|
ent->abslight = 1;
|
|
ent->frame = cl.Effects[index].Smoke.frame;
|
|
}
|
|
else if (cl.Effects[index].type == CE_RIPPLE)
|
|
{
|
|
if(cl.Effects[index].Smoke.framelength==2)
|
|
{
|
|
R_SplashParticleEffect (cl.Effects[index].Smoke.origin, 200, 406+rand()%8, pt_slowgrav, 40);//splash
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_splash, cl.Effects[index].Smoke.origin, 1, 1);
|
|
}
|
|
else if(cl.Effects[index].Smoke.framelength==1)
|
|
R_SplashParticleEffect (cl.Effects[index].Smoke.origin, 100, 406+rand()%8, pt_slowgrav, 20);//splash
|
|
else
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_ripple, cl.Effects[index].Smoke.origin, 1, 1);
|
|
cl.Effects[index].Smoke.framelength=0.05;
|
|
ent->model = Mod_ForName("models/ripple.spr", true);
|
|
ent->drawflags = DRF_TRANSLUCENT;//|SCALE_TYPE_XYONLY|SCALE_ORIGIN_CENTER;
|
|
ent->angles[0]=90;
|
|
//ent->scale = 1;
|
|
}
|
|
else
|
|
{
|
|
ImmediateFree = true;
|
|
Con_Printf ("Bad effect type %d\n",(int)cl.Effects[index].type);
|
|
}
|
|
|
|
if (cl.Effects[index].type != CE_REDCLOUD&&cl.Effects[index].type != CE_ACID_MUZZFL&&cl.Effects[index].type != CE_FLAMEWALL&&cl.Effects[index].type != CE_RIPPLE)
|
|
ent->drawflags = DRF_TRANSLUCENT;
|
|
|
|
if (cl.Effects[index].type == CE_FLAMESTREAM)
|
|
{
|
|
ent->drawflags = DRF_TRANSLUCENT | MLS_ABSLIGHT;
|
|
ent->abslight = 1;
|
|
ent->frame = cl.Effects[index].Smoke.frame;
|
|
}
|
|
|
|
if (cl.Effects[index].type == CE_GHOST)
|
|
{
|
|
ent->model = Mod_ForName("models/ghost.spr", true);
|
|
ent->drawflags = DRF_TRANSLUCENT | MLS_ABSLIGHT;
|
|
ent->abslight = .5;
|
|
}
|
|
if (cl.Effects[index].type == CE_TELESMK1)
|
|
{
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_ravenfire, cl.Effects[index].Smoke.origin, 1, 1);
|
|
|
|
if ((cl.Effects[index].Smoke.entity_index2 = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index2];
|
|
VectorCopy(cl.Effects[index].Smoke.origin, ent->origin);
|
|
ent->model = Mod_ForName("models/telesmk1.spr", true);
|
|
ent->drawflags = DRF_TRANSLUCENT;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
ImmediateFree = true;
|
|
break;
|
|
|
|
case CE_SM_WHITE_FLASH:
|
|
case CE_YELLOWRED_FLASH:
|
|
case CE_BLUESPARK:
|
|
case CE_YELLOWSPARK:
|
|
case CE_SM_CIRCLE_EXP:
|
|
case CE_BG_CIRCLE_EXP:
|
|
case CE_SM_EXPLOSION:
|
|
case CE_SM_EXPLOSION2:
|
|
case CE_BG_EXPLOSION:
|
|
case CE_FLOOR_EXPLOSION:
|
|
case CE_BLUE_EXPLOSION:
|
|
case CE_REDSPARK:
|
|
case CE_GREENSPARK:
|
|
case CE_ICEHIT:
|
|
case CE_MEDUSA_HIT:
|
|
case CE_MEZZO_REFLECT:
|
|
case CE_FLOOR_EXPLOSION2:
|
|
case CE_XBOW_EXPLOSION:
|
|
case CE_NEW_EXPLOSION:
|
|
case CE_MAGIC_MISSILE_EXPLOSION:
|
|
case CE_BONE_EXPLOSION:
|
|
case CE_BLDRN_EXPL:
|
|
case CE_BRN_BOUNCE:
|
|
case CE_LSHOCK:
|
|
case CE_ACID_HIT:
|
|
case CE_ACID_SPLAT:
|
|
case CE_ACID_EXPL:
|
|
case CE_LBALL_EXPL:
|
|
case CE_FBOOM:
|
|
case CE_BOMB:
|
|
case CE_FIREWALL_SMALL:
|
|
case CE_FIREWALL_MEDIUM:
|
|
case CE_FIREWALL_LARGE:
|
|
|
|
cl.Effects[index].Smoke.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Smoke.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Smoke.origin[2] = MSG_ReadCoord ();
|
|
if ((cl.Effects[index].Smoke.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index];
|
|
VectorCopy(cl.Effects[index].Smoke.origin, ent->origin);
|
|
|
|
if (cl.Effects[index].type == CE_BLUESPARK)
|
|
ent->model = Mod_ForName("models/bspark.spr", true);
|
|
else if (cl.Effects[index].type == CE_YELLOWSPARK)
|
|
ent->model = Mod_ForName("models/spark.spr", true);
|
|
else if (cl.Effects[index].type == CE_SM_CIRCLE_EXP)
|
|
ent->model = Mod_ForName("models/fcircle.spr", true);
|
|
else if (cl.Effects[index].type == CE_BG_CIRCLE_EXP)
|
|
ent->model = Mod_ForName("models/xplod29.spr", true);
|
|
else if (cl.Effects[index].type == CE_SM_WHITE_FLASH)
|
|
ent->model = Mod_ForName("models/sm_white.spr", true);
|
|
else if (cl.Effects[index].type == CE_YELLOWRED_FLASH)
|
|
{
|
|
ent->model = Mod_ForName("models/yr_flsh.spr", true);
|
|
ent->drawflags = DRF_TRANSLUCENT;
|
|
}
|
|
else if (cl.Effects[index].type == CE_SM_EXPLOSION)
|
|
ent->model = Mod_ForName("models/sm_expld.spr", true);
|
|
else if (cl.Effects[index].type == CE_SM_EXPLOSION2)
|
|
{
|
|
ent->model = Mod_ForName("models/sm_expld.spr", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_explode, cl.Effects[index].Smoke.origin, 1, 1);
|
|
|
|
}
|
|
else if (cl.Effects[index].type == CE_BG_EXPLOSION)
|
|
{
|
|
ent->model = Mod_ForName("models/bg_expld.spr", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_explode, cl.Effects[index].Smoke.origin, 1, 1);
|
|
}
|
|
else if (cl.Effects[index].type == CE_FLOOR_EXPLOSION)
|
|
ent->model = Mod_ForName("models/fl_expld.spr", true);
|
|
else if (cl.Effects[index].type == CE_BLUE_EXPLOSION)
|
|
ent->model = Mod_ForName("models/xpspblue.spr", true);
|
|
else if (cl.Effects[index].type == CE_REDSPARK)
|
|
ent->model = Mod_ForName("models/rspark.spr", true);
|
|
else if (cl.Effects[index].type == CE_GREENSPARK)
|
|
ent->model = Mod_ForName("models/gspark.spr", true);
|
|
else if (cl.Effects[index].type == CE_ICEHIT)
|
|
ent->model = Mod_ForName("models/icehit.spr", true);
|
|
else if (cl.Effects[index].type == CE_MEDUSA_HIT)
|
|
ent->model = Mod_ForName("models/medhit.spr", true);
|
|
else if (cl.Effects[index].type == CE_MEZZO_REFLECT)
|
|
ent->model = Mod_ForName("models/mezzoref.spr", true);
|
|
else if (cl.Effects[index].type == CE_FLOOR_EXPLOSION2)
|
|
ent->model = Mod_ForName("models/flrexpl2.spr", true);
|
|
else if (cl.Effects[index].type == CE_XBOW_EXPLOSION)
|
|
ent->model = Mod_ForName("models/xbowexpl.spr", true);
|
|
else if (cl.Effects[index].type == CE_NEW_EXPLOSION)
|
|
ent->model = Mod_ForName("models/gen_expl.spr", true);
|
|
else if (cl.Effects[index].type == CE_MAGIC_MISSILE_EXPLOSION)
|
|
{
|
|
ent->model = Mod_ForName("models/mm_expld.spr", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_explode, cl.Effects[index].Smoke.origin, 1, 1);
|
|
}
|
|
else if (cl.Effects[index].type == CE_BONE_EXPLOSION)
|
|
ent->model = Mod_ForName("models/bonexpld.spr", true);
|
|
else if (cl.Effects[index].type == CE_BLDRN_EXPL)
|
|
ent->model = Mod_ForName("models/xplsn_1.spr", true);
|
|
else if (cl.Effects[index].type == CE_ACID_HIT)
|
|
ent->model = Mod_ForName("models/axplsn_2.spr", true);
|
|
else if (cl.Effects[index].type == CE_ACID_SPLAT)
|
|
ent->model = Mod_ForName("models/axplsn_1.spr", true);
|
|
else if (cl.Effects[index].type == CE_ACID_EXPL)
|
|
{
|
|
ent->model = Mod_ForName("models/axplsn_5.spr", true);
|
|
ent->drawflags = MLS_ABSLIGHT;
|
|
ent->abslight = 1;
|
|
}
|
|
else if (cl.Effects[index].type == CE_FBOOM)
|
|
ent->model = Mod_ForName("models/fboom.spr", true);
|
|
else if (cl.Effects[index].type == CE_BOMB)
|
|
ent->model = Mod_ForName("models/pow.spr", true);
|
|
else if (cl.Effects[index].type == CE_LBALL_EXPL)
|
|
ent->model = Mod_ForName("models/Bluexp3.spr", true);
|
|
else if (cl.Effects[index].type == CE_FIREWALL_SMALL)
|
|
ent->model = Mod_ForName("models/firewal1.spr", true);
|
|
else if (cl.Effects[index].type == CE_FIREWALL_MEDIUM)
|
|
ent->model = Mod_ForName("models/firewal5.spr", true);
|
|
else if (cl.Effects[index].type == CE_FIREWALL_LARGE)
|
|
ent->model = Mod_ForName("models/firewal4.spr", true);
|
|
else if (cl.Effects[index].type == CE_BRN_BOUNCE)
|
|
ent->model = Mod_ForName("models/spark.spr", true);
|
|
else if (cl.Effects[index].type == CE_LSHOCK)
|
|
{
|
|
ent->model = Mod_ForName("models/vorpshok.mdl", true);
|
|
ent->drawflags=MLS_TORCH;
|
|
ent->angles[2]=90;
|
|
ent->scale=255;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImmediateFree = true;
|
|
}
|
|
break;
|
|
|
|
case CE_WHITE_FLASH:
|
|
case CE_BLUE_FLASH:
|
|
case CE_SM_BLUE_FLASH:
|
|
case CE_HWSPLITFLASH:
|
|
case CE_RED_FLASH:
|
|
cl.Effects[index].Flash.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Flash.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Flash.origin[2] = MSG_ReadCoord ();
|
|
cl.Effects[index].Flash.reverse = 0;
|
|
if ((cl.Effects[index].Flash.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Flash.entity_index];
|
|
VectorCopy(cl.Effects[index].Flash.origin, ent->origin);
|
|
|
|
if (cl.Effects[index].type == CE_WHITE_FLASH)
|
|
ent->model = Mod_ForName("models/gryspt.spr", true);
|
|
else if (cl.Effects[index].type == CE_BLUE_FLASH)
|
|
ent->model = Mod_ForName("models/bluflash.spr", true);
|
|
else if (cl.Effects[index].type == CE_SM_BLUE_FLASH)
|
|
ent->model = Mod_ForName("models/sm_blue.spr", true);
|
|
else if (cl.Effects[index].type == CE_RED_FLASH)
|
|
ent->model = Mod_ForName("models/redspt.spr", true);
|
|
else if (cl.Effects[index].type == CE_HWSPLITFLASH)
|
|
{
|
|
ent->model = Mod_ForName("models/sm_blue.spr", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_ravensplit, cl.Effects[index].Flash.origin, 1, 1);
|
|
}
|
|
ent->drawflags = DRF_TRANSLUCENT;
|
|
|
|
}
|
|
else
|
|
{
|
|
ImmediateFree = true;
|
|
}
|
|
break;
|
|
|
|
case CE_RIDER_DEATH:
|
|
cl.Effects[index].RD.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].RD.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].RD.origin[2] = MSG_ReadCoord ();
|
|
break;
|
|
|
|
case CE_TELEPORTERPUFFS:
|
|
cl.Effects[index].Teleporter.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Teleporter.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Teleporter.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Teleporter.framelength = .05;
|
|
dir = 0;
|
|
for (i=0;i<8;++i)
|
|
{
|
|
if ((cl.Effects[index].Teleporter.entity_index[i] = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Teleporter.entity_index[i]];
|
|
VectorCopy(cl.Effects[index].Teleporter.origin, ent->origin);
|
|
|
|
angleval = dir * M_PI*2 / 360;
|
|
|
|
sinval = sin(angleval);
|
|
cosval = cos(angleval);
|
|
|
|
cl.Effects[index].Teleporter.velocity[i][0] = 10*cosval;
|
|
cl.Effects[index].Teleporter.velocity[i][1] = 10*sinval;
|
|
cl.Effects[index].Teleporter.velocity[i][2] = 0;
|
|
dir += 45;
|
|
|
|
ent->model = Mod_ForName("models/telesmk2.spr", true);
|
|
ent->drawflags = DRF_TRANSLUCENT;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CE_TELEPORTERBODY:
|
|
cl.Effects[index].Teleporter.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Teleporter.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Teleporter.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Teleporter.velocity[0][0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Teleporter.velocity[0][1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Teleporter.velocity[0][2] = MSG_ReadFloat ();
|
|
|
|
skinnum = MSG_ReadFloat ();
|
|
|
|
cl.Effects[index].Teleporter.framelength = .05;
|
|
dir = 0;
|
|
if ((cl.Effects[index].Teleporter.entity_index[0] = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Teleporter.entity_index[0]];
|
|
VectorCopy(cl.Effects[index].Teleporter.origin, ent->origin);
|
|
|
|
ent->model = Mod_ForName("models/teleport.mdl", true);
|
|
ent->drawflags = SCALE_TYPE_XYONLY | DRF_TRANSLUCENT;
|
|
ent->scale = 100;
|
|
ent->skinnum = skinnum;
|
|
}
|
|
break;
|
|
|
|
case CE_BONESHRAPNEL:
|
|
case CE_HWBONEBALL:
|
|
cl.Effects[index].Missile.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Missile.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Missile.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Missile.velocity[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.velocity[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.velocity[2] = MSG_ReadFloat ();
|
|
|
|
cl.Effects[index].Missile.angle[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.angle[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.angle[2] = MSG_ReadFloat ();
|
|
|
|
cl.Effects[index].Missile.avelocity[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.avelocity[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.avelocity[2] = MSG_ReadFloat ();
|
|
|
|
if ((cl.Effects[index].Missile.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
VectorCopy(cl.Effects[index].Missile.origin, ent->origin);
|
|
VectorCopy(cl.Effects[index].Missile.angle, ent->angles);
|
|
if (cl.Effects[index].type == CE_BONESHRAPNEL)
|
|
ent->model = Mod_ForName("models/boneshrd.mdl", true);
|
|
else if (cl.Effects[index].type == CE_HWBONEBALL)
|
|
{
|
|
ent->model = Mod_ForName("models/bonelump.mdl", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_bonefpow, cl.Effects[index].Missile.origin, 1, 1);
|
|
}
|
|
}
|
|
else
|
|
ImmediateFree = true;
|
|
|
|
break;
|
|
case CE_BONESHARD:
|
|
case CE_HWRAVENSTAFF:
|
|
case CE_HWRAVENPOWER:
|
|
cl.Effects[index].Missile.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Missile.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Missile.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Missile.velocity[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.velocity[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Missile.velocity[2] = MSG_ReadFloat ();
|
|
vectoangles(cl.Effects[index].Missile.velocity, cl.Effects[index].Missile.angle);
|
|
|
|
if ((cl.Effects[index].Missile.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
VectorCopy(cl.Effects[index].Missile.origin, ent->origin);
|
|
VectorCopy(cl.Effects[index].Missile.angle, ent->angles);
|
|
if (cl.Effects[index].type == CE_HWRAVENSTAFF)
|
|
{
|
|
cl.Effects[index].Missile.avelocity[2] = 1000;
|
|
ent->model = Mod_ForName("models/vindsht1.mdl", true);
|
|
}
|
|
else if (cl.Effects[index].type == CE_BONESHARD)
|
|
{
|
|
cl.Effects[index].Missile.avelocity[0] = (rand() % 1554) - 777;
|
|
ent->model = Mod_ForName("models/boneshot.mdl", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_bone, cl.Effects[index].Missile.origin, 1, 1);
|
|
}
|
|
else if (cl.Effects[index].type == CE_HWRAVENPOWER)
|
|
{
|
|
ent->model = Mod_ForName("models/ravproj.mdl", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_ravengo, cl.Effects[index].Missile.origin, 1, 1);
|
|
}
|
|
}
|
|
else
|
|
ImmediateFree = true;
|
|
break;
|
|
case CE_DEATHBUBBLES:
|
|
cl.Effects[index].Bubble.owner = MSG_ReadShort();
|
|
cl.Effects[index].Bubble.offset[0] = MSG_ReadByte();
|
|
cl.Effects[index].Bubble.offset[1] = MSG_ReadByte();
|
|
cl.Effects[index].Bubble.offset[2] = MSG_ReadByte();
|
|
cl.Effects[index].Bubble.count = MSG_ReadByte();//num of bubbles
|
|
cl.Effects[index].Bubble.time_amount = 0;
|
|
break;
|
|
case CE_HWXBOWSHOOT:
|
|
origin[0] = MSG_ReadCoord ();
|
|
origin[1] = MSG_ReadCoord ();
|
|
origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Xbow.angle[0] = MSG_ReadAngle ();
|
|
cl.Effects[index].Xbow.angle[1] = MSG_ReadAngle ();
|
|
cl.Effects[index].Xbow.angle[2] = 0;//MSG_ReadFloat ();
|
|
|
|
cl.Effects[index].Xbow.bolts = MSG_ReadByte();
|
|
cl.Effects[index].Xbow.randseed = MSG_ReadByte();
|
|
|
|
cl.Effects[index].Xbow.turnedbolts = MSG_ReadByte();
|
|
|
|
cl.Effects[index].Xbow.activebolts= MSG_ReadByte();
|
|
|
|
setseed(cl.Effects[index].Xbow.randseed);
|
|
|
|
AngleVectors (cl.Effects[index].Xbow.angle, forward, right, up);
|
|
|
|
VectorNormalize(forward);
|
|
VectorCopy(forward, cl.Effects[index].Xbow.velocity);
|
|
// VectorScale(forward, 1000, cl.Effects[index].Xbow.velocity);
|
|
|
|
if (cl.Effects[index].Xbow.bolts == 3)
|
|
{
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_xbowshoot, origin, 1, 1);
|
|
}
|
|
else if (cl.Effects[index].Xbow.bolts == 5)
|
|
{
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_xbowfshoot, origin, 1, 1);
|
|
}
|
|
|
|
for (i=0;i<cl.Effects[index].Xbow.bolts;i++)
|
|
{
|
|
cl.Effects[index].Xbow.gonetime[i] = 1 + seedrand()*2;
|
|
cl.Effects[index].Xbow.state[i] = 0;
|
|
|
|
if ((1<<i)& cl.Effects[index].Xbow.turnedbolts)
|
|
{
|
|
cl.Effects[index].Xbow.origin[i][0]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[i][1]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[i][2]=MSG_ReadCoord();
|
|
vtemp[0]=MSG_ReadAngle();
|
|
vtemp[1]=MSG_ReadAngle();
|
|
vtemp[2]=0;
|
|
AngleVectors (vtemp, forward2, right2, up2);
|
|
VectorScale(forward2, 800 + seedrand()*500, cl.Effects[index].Xbow.vel[i]);
|
|
}
|
|
else
|
|
{
|
|
VectorScale(forward, 800 + seedrand()*500, cl.Effects[index].Xbow.vel[i]);
|
|
|
|
VectorScale(right,i*100-(cl.Effects[index].Xbow.bolts-1)*50,vtemp);
|
|
|
|
//this should only be done for deathmatch:
|
|
VectorScale(vtemp,0.333,vtemp);
|
|
|
|
VectorAdd(cl.Effects[index].Xbow.vel[i],vtemp,cl.Effects[index].Xbow.vel[i]);
|
|
|
|
//start me off a bit out
|
|
VectorScale(vtemp,0.05,cl.Effects[index].Xbow.origin[i]);
|
|
VectorAdd(origin,cl.Effects[index].Xbow.origin[i],cl.Effects[index].Xbow.origin[i]);
|
|
}
|
|
|
|
if ((cl.Effects[index].Xbow.ent[i] = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[i]];
|
|
VectorCopy(cl.Effects[index].Xbow.origin[i], ent->origin);
|
|
vectoangles(cl.Effects[index].Xbow.vel[i],ent->angles);
|
|
if (cl.Effects[index].Xbow.bolts == 5)
|
|
ent->model = Mod_ForName("models/flaming.mdl", true);
|
|
else
|
|
ent->model = Mod_ForName("models/arrow.mdl", true);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case CE_HWSHEEPINATOR:
|
|
origin[0] = MSG_ReadCoord ();
|
|
origin[1] = MSG_ReadCoord ();
|
|
origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Xbow.angle[0] = MSG_ReadAngle ();
|
|
cl.Effects[index].Xbow.angle[1] = MSG_ReadAngle ();
|
|
cl.Effects[index].Xbow.angle[2] = 0;//MSG_ReadFloat ();
|
|
|
|
cl.Effects[index].Xbow.turnedbolts = MSG_ReadByte();
|
|
|
|
cl.Effects[index].Xbow.activebolts= MSG_ReadByte();
|
|
|
|
cl.Effects[index].Xbow.bolts = 5;
|
|
cl.Effects[index].Xbow.randseed = 0;
|
|
|
|
AngleVectors (cl.Effects[index].Xbow.angle, forward, right, up);
|
|
|
|
VectorNormalize(forward);
|
|
VectorCopy(forward, cl.Effects[index].Xbow.velocity);
|
|
|
|
// S_StartSound (TempSoundChannel(), 1, cl_fxsfx_xbowshoot, origin, 1, 1);
|
|
|
|
for (i=0;i<cl.Effects[index].Xbow.bolts;i++)
|
|
{
|
|
cl.Effects[index].Xbow.gonetime[i] = 0;
|
|
cl.Effects[index].Xbow.state[i] = 0;
|
|
|
|
|
|
if ((1<<i)& cl.Effects[index].Xbow.turnedbolts)
|
|
{
|
|
cl.Effects[index].Xbow.origin[i][0]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[i][1]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[i][2]=MSG_ReadCoord();
|
|
vtemp[0]=MSG_ReadAngle();
|
|
vtemp[1]=MSG_ReadAngle();
|
|
vtemp[2]=0;
|
|
AngleVectors (vtemp, forward2, right2, up2);
|
|
VectorScale(forward2, 700, cl.Effects[index].Xbow.vel[i]);
|
|
}
|
|
else
|
|
{
|
|
VectorCopy(origin,cl.Effects[index].Xbow.origin[i]);
|
|
VectorScale(forward, 700, cl.Effects[index].Xbow.vel[i]);
|
|
VectorScale(right,i*75-150,vtemp);
|
|
VectorAdd(cl.Effects[index].Xbow.vel[i],vtemp,cl.Effects[index].Xbow.vel[i]);
|
|
}
|
|
|
|
if ((cl.Effects[index].Xbow.ent[i] = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[i]];
|
|
VectorCopy(cl.Effects[index].Xbow.origin[i], ent->origin);
|
|
vectoangles(cl.Effects[index].Xbow.vel[i],ent->angles);
|
|
ent->model = Mod_ForName("models/polymrph.spr", true);
|
|
}
|
|
}
|
|
|
|
break;
|
|
case CE_HWDRILLA:
|
|
cl.Effects[index].Missile.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Missile.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Missile.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Missile.angle[0] = MSG_ReadAngle ();
|
|
cl.Effects[index].Missile.angle[1] = MSG_ReadAngle ();
|
|
cl.Effects[index].Missile.angle[2] = 0;
|
|
|
|
cl.Effects[index].Missile.speed = MSG_ReadShort();
|
|
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_drillashoot, cl.Effects[index].Missile.origin, 1, 1);
|
|
|
|
AngleVectors(cl.Effects[index].Missile.angle,cl.Effects[index].Missile.velocity,right,up);
|
|
|
|
VectorScale(cl.Effects[index].Missile.velocity,cl.Effects[index].Missile.speed,cl.Effects[index].Missile.velocity);
|
|
|
|
if ((cl.Effects[index].Missile.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
VectorCopy(cl.Effects[index].Missile.origin, ent->origin);
|
|
VectorCopy(cl.Effects[index].Missile.angle, ent->angles);
|
|
ent->model = Mod_ForName("models/scrbstp1.mdl", true);
|
|
}
|
|
else
|
|
ImmediateFree = true;
|
|
break;
|
|
case CE_SCARABCHAIN:
|
|
cl.Effects[index].Chain.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Chain.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Chain.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Chain.owner = MSG_ReadShort ();
|
|
cl.Effects[index].Chain.tag = MSG_ReadByte();
|
|
cl.Effects[index].Chain.material = cl.Effects[index].Chain.owner>>12;
|
|
cl.Effects[index].Chain.owner &= 0x0fff;
|
|
cl.Effects[index].Chain.height = 16;//MSG_ReadByte ();
|
|
|
|
cl.Effects[index].Chain.sound_time = cl.time;
|
|
|
|
cl.Effects[index].Chain.state = 0;//state 0: move slowly toward owner
|
|
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_scarabwhoosh, cl.Effects[index].Chain.origin, 1, 1);
|
|
|
|
if ((cl.Effects[index].Chain.ent1 = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Chain.ent1];
|
|
VectorCopy(cl.Effects[index].Chain.origin, ent->origin);
|
|
ent->model = Mod_ForName("models/scrbpbdy.mdl", true);
|
|
}
|
|
else
|
|
ImmediateFree = true;
|
|
break;
|
|
case CE_TRIPMINE:
|
|
cl.Effects[index].Chain.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Chain.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Chain.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Chain.velocity[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Chain.velocity[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Chain.velocity[2] = MSG_ReadFloat ();
|
|
|
|
if ((cl.Effects[index].Chain.ent1 = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Chain.ent1];
|
|
VectorCopy(cl.Effects[index].Chain.origin, ent->origin);
|
|
ent->model = Mod_ForName("models/twspike.mdl", true);
|
|
}
|
|
else
|
|
ImmediateFree = true;
|
|
break;
|
|
case CE_TRIPMINESTILL:
|
|
// Con_DPrintf("Allocating chain effect...\n");
|
|
cl.Effects[index].Chain.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Chain.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Chain.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Chain.velocity[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Chain.velocity[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Chain.velocity[2] = MSG_ReadFloat ();
|
|
|
|
if ((cl.Effects[index].Chain.ent1 = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Chain.ent1];
|
|
VectorCopy(cl.Effects[index].Chain.velocity, ent->origin);
|
|
ent->model = Mod_ForName("models/twspike.mdl", true);
|
|
}
|
|
else
|
|
{
|
|
// Con_DPrintf("ERROR: Couldn't allocate chain effect!\n");
|
|
ImmediateFree = true;
|
|
}
|
|
break;
|
|
case CE_HWMISSILESTAR:
|
|
case CE_HWEIDOLONSTAR:
|
|
cl.Effects[index].Star.origin[0] = MSG_ReadCoord ();
|
|
cl.Effects[index].Star.origin[1] = MSG_ReadCoord ();
|
|
cl.Effects[index].Star.origin[2] = MSG_ReadCoord ();
|
|
|
|
cl.Effects[index].Star.velocity[0] = MSG_ReadFloat ();
|
|
cl.Effects[index].Star.velocity[1] = MSG_ReadFloat ();
|
|
cl.Effects[index].Star.velocity[2] = MSG_ReadFloat ();
|
|
vectoangles(cl.Effects[index].Star.velocity, cl.Effects[index].Star.angle);
|
|
cl.Effects[index].Missile.avelocity[2] = 300 + rand()%300;
|
|
|
|
if ((cl.Effects[index].Star.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Star.entity_index];
|
|
VectorCopy(cl.Effects[index].Star.origin, ent->origin);
|
|
VectorCopy(cl.Effects[index].Star.angle, ent->angles);
|
|
ent->model = Mod_ForName("models/ball.mdl", true);
|
|
}
|
|
else
|
|
ImmediateFree = true;
|
|
|
|
cl.Effects[index].Star.scaleDir = 1;
|
|
cl.Effects[index].Star.scale = 0.3;
|
|
|
|
if ((cl.Effects[index].Star.ent1 = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Star.ent1];
|
|
VectorCopy(cl.Effects[index].Star.origin, ent->origin);
|
|
ent->drawflags |= MLS_ABSLIGHT;
|
|
ent->abslight = 0.5;
|
|
ent->angles[2] = 90;
|
|
if(cl.Effects[index].type == CE_HWMISSILESTAR)
|
|
{
|
|
ent->model = Mod_ForName("models/star.mdl", true);
|
|
ent->scale = 0.3;
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_mmfire, ent->origin, 1, 1);
|
|
|
|
}
|
|
else
|
|
{
|
|
ent->model = Mod_ForName("models/glowball.mdl", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_eidolon, ent->origin, 1, 1);
|
|
}
|
|
}
|
|
if(cl.Effects[index].type == CE_HWMISSILESTAR)
|
|
{
|
|
if ((cl.Effects[index].Star.ent2 = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Star.ent2];
|
|
VectorCopy(cl.Effects[index].Star.origin, ent->origin);
|
|
ent->model = Mod_ForName("models/star.mdl", true);
|
|
ent->drawflags |= MLS_ABSLIGHT;
|
|
ent->abslight = 0.5;
|
|
ent->scale = 0.3;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
Sys_Error ("CL_ParseEffect: bad type");
|
|
}
|
|
|
|
if (ImmediateFree)
|
|
{
|
|
cl.Effects[index].type = CE_NONE;
|
|
}
|
|
}
|
|
|
|
// these are in cl_tent.c
|
|
void CreateRavenDeath(vec3_t pos);
|
|
void CreateExplosionWithSound(vec3_t pos);
|
|
|
|
void CL_EndEffect(void)
|
|
{
|
|
int index;
|
|
entity_t *ent;
|
|
|
|
index = MSG_ReadByte();
|
|
|
|
switch(cl.Effects[index].type )
|
|
{
|
|
case CE_HWRAVENPOWER:
|
|
if(cl.Effects[index].Missile.entity_index > -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
CreateRavenDeath(ent->origin);
|
|
}
|
|
break;
|
|
case CE_HWRAVENSTAFF:
|
|
if(cl.Effects[index].Missile.entity_index > -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
CreateExplosionWithSound(ent->origin);
|
|
}
|
|
break;
|
|
}
|
|
CL_FreeEffect(index);
|
|
}
|
|
|
|
void XbowImpactPuff(vec3_t origin, int material)//hopefully can use this with xbow & chain both
|
|
{
|
|
int part_color;
|
|
|
|
switch(material)
|
|
{
|
|
case XBOW_IMPACT_REDFLESH:
|
|
part_color = 256 + 8 * 16 + rand()%9; //Blood red
|
|
break;
|
|
case XBOW_IMPACT_STONE:
|
|
part_color = 256 + 20 + rand()%8; // Gray
|
|
break;
|
|
case XBOW_IMPACT_METAL:
|
|
part_color = 256 + (8 * 15); // Sparks
|
|
break;
|
|
case XBOW_IMPACT_WOOD:
|
|
part_color = 256 + (5 * 16) + rand()%8; // Wood chunks
|
|
break;
|
|
case XBOW_IMPACT_ICE:
|
|
part_color = 406+rand()%8; // Ice particles
|
|
break;
|
|
case XBOW_IMPACT_GREENFLESH:
|
|
part_color = 256 + 183 + rand()%8; // Spider's have green blood
|
|
break;
|
|
default:
|
|
part_color = 256 + (3 * 16) + 4; // Dust Brown
|
|
break;
|
|
}
|
|
|
|
R_RunParticleEffect4 (origin, 24, part_color, pt_fastgrav, 20);
|
|
}
|
|
|
|
void CL_ReviseEffect(void) // be sure to read, in the switch statement, everything
|
|
// in this message, even if the effect is not the right kind or invalid,
|
|
// or else client is sure to crash.
|
|
{
|
|
int index,type,revisionCode;
|
|
int curEnt,material,takedamage;
|
|
entity_t *ent;
|
|
vec3_t forward,right,up,pos;
|
|
float dist,speed;
|
|
entity_state_t *es;
|
|
|
|
|
|
index = MSG_ReadByte ();
|
|
type = MSG_ReadByte ();
|
|
|
|
if (cl.Effects[index].type==type)
|
|
switch(type)
|
|
{
|
|
case CE_SCARABCHAIN://attach to new guy or retract if new guy is world
|
|
curEnt = MSG_ReadShort();
|
|
if (cl.Effects[index].type==type)
|
|
{
|
|
cl.Effects[index].Chain.material = curEnt>>12;
|
|
curEnt &= 0x0fff;
|
|
|
|
if (curEnt)
|
|
{
|
|
cl.Effects[index].Chain.state = 1;
|
|
cl.Effects[index].Chain.owner = curEnt;
|
|
es = FindState(cl.Effects[index].Chain.owner);
|
|
if (es)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Chain.ent1];
|
|
XbowImpactPuff(ent->origin, cl.Effects[index].Chain.material);
|
|
}
|
|
}
|
|
else
|
|
cl.Effects[index].Chain.state = 2;
|
|
}
|
|
break;
|
|
case CE_HWXBOWSHOOT:
|
|
revisionCode = MSG_ReadByte();
|
|
//this is one packed byte!
|
|
//highest bit: for impact revision, indicates whether damage is done
|
|
// for redirect revision, indicates whether new origin was sent
|
|
//next 3 high bits: for all revisions, indicates which bolt is to be revised
|
|
//highest 3 of the low 4 bits: for impact revision, indicates the material that was hit
|
|
//lowest bit: indicates whether revision is of impact or redirect variety
|
|
|
|
|
|
curEnt = (revisionCode>>4)&7;
|
|
if (revisionCode & 1)//impact effect:
|
|
{
|
|
cl.Effects[index].Xbow.activebolts &= ~(1<<curEnt);
|
|
dist = MSG_ReadCoord();
|
|
if (cl.Effects[index].Xbow.ent[curEnt]!= -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[curEnt]];
|
|
|
|
//make sure bolt is in correct position
|
|
VectorCopy(cl.Effects[index].Xbow.vel[curEnt],forward);
|
|
VectorNormalize(forward);
|
|
VectorScale(forward,dist,forward);
|
|
VectorAdd(cl.Effects[index].Xbow.origin[curEnt],forward,ent->origin);
|
|
|
|
material = (revisionCode & 14);
|
|
takedamage = (revisionCode & 128);
|
|
|
|
if (takedamage)
|
|
{
|
|
cl.Effects[index].Xbow.gonetime[curEnt] = cl.time;
|
|
}
|
|
else
|
|
{
|
|
cl.Effects[index].Xbow.gonetime[curEnt] += cl.time;
|
|
}
|
|
|
|
VectorCopy(cl.Effects[index].Xbow.vel[curEnt],forward);
|
|
VectorNormalize(forward);
|
|
VectorScale(forward,8,forward);
|
|
|
|
// do a particle effect here, with the color depending on chType
|
|
XbowImpactPuff(ent->origin,material);
|
|
|
|
// impact sound:
|
|
switch (material)
|
|
{
|
|
case XBOW_IMPACT_GREENFLESH:
|
|
case XBOW_IMPACT_REDFLESH:
|
|
case XBOW_IMPACT_MUMMY:
|
|
S_StartSound (TempSoundChannel(), 0, cl_fxsfx_arr2flsh, ent->origin, 1, 1);
|
|
break;
|
|
case XBOW_IMPACT_WOOD:
|
|
S_StartSound (TempSoundChannel(), 0, cl_fxsfx_arr2wood, ent->origin, 1, 1);
|
|
break;
|
|
default:
|
|
S_StartSound (TempSoundChannel(), 0, cl_fxsfx_met2stn, ent->origin, 1, 1);
|
|
break;
|
|
}
|
|
|
|
CLTENT_XbowImpact(ent->origin, forward, material, takedamage, cl.Effects[index].Xbow.bolts);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cl.Effects[index].Xbow.ent[curEnt]!=-1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[curEnt]];
|
|
ent->angles[0] = MSG_ReadAngle();
|
|
if (ent->angles[0] < 0)
|
|
ent->angles[0] += 360;
|
|
ent->angles[0]*=-1;
|
|
ent->angles[1] = MSG_ReadAngle();
|
|
if (ent->angles[1] < 0)
|
|
ent->angles[1] += 360;
|
|
ent->angles[2] = 0;
|
|
|
|
if (revisionCode &128)//new origin
|
|
{
|
|
cl.Effects[index].Xbow.origin[curEnt][0]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][1]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][2]=MSG_ReadCoord();
|
|
}
|
|
|
|
AngleVectors(ent->angles,forward,right,up);
|
|
speed = Length(cl.Effects[index].Xbow.vel[curEnt]);
|
|
VectorScale(forward,speed,cl.Effects[index].Xbow.vel[curEnt]);
|
|
VectorCopy(cl.Effects[index].Xbow.origin[curEnt],ent->origin);
|
|
}
|
|
else
|
|
{
|
|
pos[0] = MSG_ReadAngle();
|
|
if (pos[0] < 0)
|
|
pos[0] += 360;
|
|
pos[0]*=-1;
|
|
pos[1] = MSG_ReadAngle();
|
|
if (pos[1] < 0)
|
|
pos[1] += 360;
|
|
pos[2] = 0;
|
|
|
|
if (revisionCode &128)//new origin
|
|
{
|
|
cl.Effects[index].Xbow.origin[curEnt][0]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][1]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][2]=MSG_ReadCoord();
|
|
}
|
|
|
|
AngleVectors(pos,forward,right,up);
|
|
speed = Length(cl.Effects[index].Xbow.vel[curEnt]);
|
|
VectorScale(forward,speed,cl.Effects[index].Xbow.vel[curEnt]);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CE_HWSHEEPINATOR:
|
|
revisionCode = MSG_ReadByte();
|
|
curEnt = (revisionCode>>4)&7;
|
|
if (revisionCode & 1)//impact
|
|
{
|
|
dist = MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.activebolts &= ~(1<<curEnt);
|
|
if (cl.Effects[index].Xbow.ent[curEnt] != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[curEnt]];
|
|
|
|
//make sure bolt is in correct position
|
|
VectorCopy(cl.Effects[index].Xbow.vel[curEnt],forward);
|
|
VectorNormalize(forward);
|
|
VectorScale(forward,dist,forward);
|
|
VectorAdd(cl.Effects[index].Xbow.origin[curEnt],forward,ent->origin);
|
|
R_ColoredParticleExplosion(ent->origin,(rand()%16)+144/*(144,159)*/,20,30);
|
|
}
|
|
}
|
|
else//direction change
|
|
{
|
|
if (cl.Effects[index].Xbow.ent[curEnt] != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[curEnt]];
|
|
ent->angles[0] = MSG_ReadAngle();
|
|
if (ent->angles[0] < 0)
|
|
ent->angles[0] += 360;
|
|
ent->angles[0]*=-1;
|
|
ent->angles[1] = MSG_ReadAngle();
|
|
if (ent->angles[1] < 0)
|
|
ent->angles[1] += 360;
|
|
ent->angles[2] = 0;
|
|
|
|
if (revisionCode &128)//new origin
|
|
{
|
|
cl.Effects[index].Xbow.origin[curEnt][0]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][1]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][2]=MSG_ReadCoord();
|
|
}
|
|
|
|
AngleVectors(ent->angles,forward,right,up);
|
|
speed = Length(cl.Effects[index].Xbow.vel[curEnt]);
|
|
VectorScale(forward,speed,cl.Effects[index].Xbow.vel[curEnt]);
|
|
VectorCopy(cl.Effects[index].Xbow.origin[curEnt],ent->origin);
|
|
}
|
|
else
|
|
{
|
|
pos[0] = MSG_ReadAngle();
|
|
if (pos[0] < 0)
|
|
pos[0] += 360;
|
|
pos[0]*=-1;
|
|
pos[1] = MSG_ReadAngle();
|
|
if (pos[1] < 0)
|
|
pos[1] += 360;
|
|
pos[2] = 0;
|
|
|
|
if (revisionCode &128)//new origin
|
|
{
|
|
cl.Effects[index].Xbow.origin[curEnt][0]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][1]=MSG_ReadCoord();
|
|
cl.Effects[index].Xbow.origin[curEnt][2]=MSG_ReadCoord();
|
|
}
|
|
|
|
AngleVectors(pos,forward,right,up);
|
|
speed = Length(cl.Effects[index].Xbow.vel[curEnt]);
|
|
VectorScale(forward,speed,cl.Effects[index].Xbow.vel[curEnt]);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case CE_HWDRILLA:
|
|
revisionCode = MSG_ReadByte();
|
|
if (revisionCode == 0)//impact
|
|
{
|
|
pos[0] = MSG_ReadCoord();
|
|
pos[1] = MSG_ReadCoord();
|
|
pos[2] = MSG_ReadCoord();
|
|
material = MSG_ReadByte();
|
|
|
|
//throw lil bits of victim at entry
|
|
XbowImpactPuff(pos,material);
|
|
|
|
if ((material == XBOW_IMPACT_GREENFLESH) || (material == XBOW_IMPACT_GREENFLESH))
|
|
{//meaty sound and some chunks too
|
|
S_StartSound (TempSoundChannel(), 0, cl_fxsfx_drillameat, pos, 1, 1);
|
|
|
|
//todo: the chunks
|
|
}
|
|
|
|
//lil bits at exit
|
|
VectorCopy(cl.Effects[index].Missile.velocity,forward);
|
|
VectorNormalize(forward);
|
|
VectorScale(forward,36,forward);
|
|
VectorAdd(forward,pos,pos);
|
|
XbowImpactPuff(pos,material);
|
|
}
|
|
else//turn
|
|
{
|
|
if (cl.Effects[index].Missile.entity_index!=-1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
ent->angles[0] = MSG_ReadAngle();
|
|
if (ent->angles[0] < 0)
|
|
ent->angles[0] += 360;
|
|
ent->angles[0]*=-1;
|
|
ent->angles[1] = MSG_ReadAngle();
|
|
if (ent->angles[1] < 0)
|
|
ent->angles[1] += 360;
|
|
ent->angles[2] = 0;
|
|
|
|
cl.Effects[index].Missile.origin[0]=MSG_ReadCoord();
|
|
cl.Effects[index].Missile.origin[1]=MSG_ReadCoord();
|
|
cl.Effects[index].Missile.origin[2]=MSG_ReadCoord();
|
|
|
|
AngleVectors(ent->angles,forward,right,up);
|
|
speed = Length(cl.Effects[index].Missile.velocity);
|
|
VectorScale(forward,speed,cl.Effects[index].Missile.velocity);
|
|
VectorCopy(cl.Effects[index].Missile.origin,ent->origin);
|
|
}
|
|
else
|
|
{
|
|
pos[0] = MSG_ReadAngle();
|
|
if (pos[0] < 0)
|
|
pos[0] += 360;
|
|
pos[0]*=-1;
|
|
pos[1] = MSG_ReadAngle();
|
|
if (pos[1] < 0)
|
|
pos[1] += 360;
|
|
pos[2] = 0;
|
|
|
|
cl.Effects[index].Missile.origin[0]=MSG_ReadCoord();
|
|
cl.Effects[index].Missile.origin[1]=MSG_ReadCoord();
|
|
cl.Effects[index].Missile.origin[2]=MSG_ReadCoord();
|
|
|
|
AngleVectors(pos,forward,right,up);
|
|
speed = Length(cl.Effects[index].Missile.velocity);
|
|
VectorScale(forward,speed,cl.Effects[index].Missile.velocity);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Con_DPrintf("Received Unrecognized Effect Update!\n");
|
|
switch(type)
|
|
{
|
|
case CE_SCARABCHAIN://attach to new guy or retract if new guy is world
|
|
curEnt = MSG_ReadShort();
|
|
break;
|
|
case CE_HWXBOWSHOOT:
|
|
revisionCode = MSG_ReadByte();
|
|
|
|
curEnt = (revisionCode>>4)&7;
|
|
if (revisionCode & 1)//impact effect:
|
|
{
|
|
MSG_ReadCoord();
|
|
}
|
|
else
|
|
{
|
|
MSG_ReadAngle();
|
|
MSG_ReadAngle();
|
|
if (revisionCode &128)//new origin
|
|
{
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
|
|
// create a clc message to retrieve effect information
|
|
// MSG_WriteByte (&cls.netchan.message, clc_get_effect);
|
|
// MSG_WriteByte (&cls.netchan.message, index);
|
|
}
|
|
}
|
|
break;
|
|
case CE_HWSHEEPINATOR:
|
|
revisionCode = MSG_ReadByte();
|
|
curEnt = (revisionCode>>4)&7;
|
|
if (revisionCode & 1)//impact
|
|
{
|
|
MSG_ReadCoord();
|
|
}
|
|
else//direction change
|
|
{
|
|
MSG_ReadAngle();
|
|
MSG_ReadAngle();
|
|
if (revisionCode &128)//new origin
|
|
{
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
|
|
// create a clc message to retrieve effect information
|
|
// MSG_WriteByte (&cls.netchan.message, clc_get_effect);
|
|
// MSG_WriteByte (&cls.netchan.message, index);
|
|
}
|
|
}
|
|
break;
|
|
case CE_HWDRILLA:
|
|
revisionCode = MSG_ReadByte();
|
|
if (revisionCode == 0)//impact
|
|
{
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
MSG_ReadByte();
|
|
}
|
|
else//turn
|
|
{
|
|
MSG_ReadAngle();
|
|
MSG_ReadAngle();
|
|
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
MSG_ReadCoord();
|
|
|
|
// create a clc message to retrieve effect information
|
|
// MSG_WriteByte (&cls.netchan.message, clc_get_effect);
|
|
// MSG_WriteByte (&cls.netchan.message, index);
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateMissilePath(vec3_t oldorg, vec3_t neworg, vec3_t newvel, float time)
|
|
{
|
|
vec3_t endpos; //the position it should be at currently
|
|
float delta;
|
|
|
|
delta = cl.time - time;
|
|
|
|
VectorMA(neworg, delta, newvel, endpos);
|
|
VectorCopy(neworg, oldorg); //set orig, maybe vel too
|
|
}
|
|
|
|
|
|
void CL_TurnEffect(void)
|
|
{
|
|
int index;
|
|
entity_t *ent;
|
|
vec3_t pos, vel;
|
|
float time;
|
|
|
|
index = MSG_ReadByte ();
|
|
time = MSG_ReadFloat ();
|
|
pos[0] = MSG_ReadCoord();
|
|
pos[1] = MSG_ReadCoord();
|
|
pos[2] = MSG_ReadCoord();
|
|
vel[0] = MSG_ReadCoord();
|
|
vel[1] = MSG_ReadCoord();
|
|
vel[2] = MSG_ReadCoord();
|
|
switch(cl.Effects[index].type)
|
|
{
|
|
case CE_HWRAVENSTAFF:
|
|
case CE_HWRAVENPOWER:
|
|
case CE_BONESHARD:
|
|
case CE_BONESHRAPNEL:
|
|
case CE_HWBONEBALL:
|
|
if(cl.Effects[index].Missile.entity_index > -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
UpdateMissilePath(ent->origin, pos, vel, time);
|
|
VectorCopy(vel, cl.Effects[index].Missile.velocity);
|
|
vectoangles(cl.Effects[index].Missile.velocity, cl.Effects[index].Missile.angle);
|
|
}
|
|
break;
|
|
case CE_HWMISSILESTAR:
|
|
case CE_HWEIDOLONSTAR:
|
|
if(cl.Effects[index].Star.entity_index > -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Star.entity_index];
|
|
UpdateMissilePath(ent->origin, pos, vel, time);
|
|
VectorCopy(vel, cl.Effects[index].Star.velocity);
|
|
}
|
|
break;
|
|
case 0:
|
|
// create a clc message to retrieve effect information
|
|
// MSG_WriteByte (&cls.netchan.message, clc_get_effect);
|
|
// MSG_WriteByte (&cls.netchan.message, index);
|
|
// Con_Printf("CL_TurnEffect: null effect %d\n", index);
|
|
break;
|
|
default:
|
|
Con_Printf ("CL_TurnEffect: bad type %d\n", cl.Effects[index].type);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void CL_LinkEntity(entity_t *ent)
|
|
{
|
|
if (cl_numvisedicts == MAX_VISEDICTS)
|
|
{ // object list is full
|
|
//Sys_Error("CL_LinkEntity: Out of vis edicts\n");
|
|
return;
|
|
}
|
|
|
|
//debug: if visedicts getting messed up, it should appear here.
|
|
// if (ent->model < 10)
|
|
// {
|
|
// ent->model = 3;
|
|
// }
|
|
|
|
cl_visedicts[cl_numvisedicts++] = *ent;
|
|
}
|
|
|
|
void R_RunQuakeEffect (vec3_t org, float distance);
|
|
void RiderParticle(int count, vec3_t origin);
|
|
|
|
void CL_UpdateEffects(void)
|
|
{
|
|
int index,cur_frame;
|
|
vec3_t mymin,mymax;
|
|
float frametime;
|
|
// edict_t test;
|
|
// trace_t trace;
|
|
vec3_t org,org2,old_origin;
|
|
int x_dir,y_dir;
|
|
entity_t *ent, *ent2;
|
|
float distance,smoketime;
|
|
int i;
|
|
entity_state_t *es;
|
|
mleaf_t *l;
|
|
|
|
frametime = host_frametime;
|
|
if (!frametime) return;
|
|
// Con_Printf("Here at %f\n",cl.time);
|
|
|
|
for(index=0;index<MAX_EFFECTS;index++)
|
|
{
|
|
if (!cl.Effects[index].type)
|
|
continue;
|
|
|
|
switch(cl.Effects[index].type)
|
|
{
|
|
case CE_RAIN:
|
|
org[0] = cl.Effects[index].Rain.min_org[0];
|
|
org[1] = cl.Effects[index].Rain.min_org[1];
|
|
org[2] = cl.Effects[index].Rain.max_org[2];
|
|
|
|
org2[0] = cl.Effects[index].Rain.e_size[0];
|
|
org2[1] = cl.Effects[index].Rain.e_size[1];
|
|
org2[2] = cl.Effects[index].Rain.e_size[2];
|
|
|
|
x_dir = cl.Effects[index].Rain.dir[0];
|
|
y_dir = cl.Effects[index].Rain.dir[1];
|
|
|
|
cl.Effects[index].Rain.next_time += frametime;
|
|
if (cl.Effects[index].Rain.next_time >= cl.Effects[index].Rain.wait)
|
|
{
|
|
R_RainEffect(org,org2,x_dir,y_dir,cl.Effects[index].Rain.color,
|
|
cl.Effects[index].Rain.count);
|
|
cl.Effects[index].Rain.next_time = 0;
|
|
}
|
|
break;
|
|
|
|
case CE_FOUNTAIN:
|
|
mymin[0] = (-3 * cl.Effects[index].Fountain.vright[0] * cl.Effects[index].Fountain.movedir[0]) +
|
|
(-3 * cl.Effects[index].Fountain.vforward[0] * cl.Effects[index].Fountain.movedir[1]) +
|
|
(2 * cl.Effects[index].Fountain.vup[0] * cl.Effects[index].Fountain.movedir[2]);
|
|
mymin[1] = (-3 * cl.Effects[index].Fountain.vright[1] * cl.Effects[index].Fountain.movedir[0]) +
|
|
(-3 * cl.Effects[index].Fountain.vforward[1] * cl.Effects[index].Fountain.movedir[1]) +
|
|
(2 * cl.Effects[index].Fountain.vup[1] * cl.Effects[index].Fountain.movedir[2]);
|
|
mymin[2] = (-3 * cl.Effects[index].Fountain.vright[2] * cl.Effects[index].Fountain.movedir[0]) +
|
|
(-3 * cl.Effects[index].Fountain.vforward[2] * cl.Effects[index].Fountain.movedir[1]) +
|
|
(2 * cl.Effects[index].Fountain.vup[2] * cl.Effects[index].Fountain.movedir[2]);
|
|
mymin[0] *= 15;
|
|
mymin[1] *= 15;
|
|
mymin[2] *= 15;
|
|
|
|
mymax[0] = (3 * cl.Effects[index].Fountain.vright[0] * cl.Effects[index].Fountain.movedir[0]) +
|
|
(3 * cl.Effects[index].Fountain.vforward[0] * cl.Effects[index].Fountain.movedir[1]) +
|
|
(10 * cl.Effects[index].Fountain.vup[0] * cl.Effects[index].Fountain.movedir[2]);
|
|
mymax[1] = (3 * cl.Effects[index].Fountain.vright[1] * cl.Effects[index].Fountain.movedir[0]) +
|
|
(3 * cl.Effects[index].Fountain.vforward[1] * cl.Effects[index].Fountain.movedir[1]) +
|
|
(10 * cl.Effects[index].Fountain.vup[1] * cl.Effects[index].Fountain.movedir[2]);
|
|
mymax[2] = (3 * cl.Effects[index].Fountain.vright[2] * cl.Effects[index].Fountain.movedir[0]) +
|
|
(3 * cl.Effects[index].Fountain.vforward[2] * cl.Effects[index].Fountain.movedir[1]) +
|
|
(10 * cl.Effects[index].Fountain.vup[2] * cl.Effects[index].Fountain.movedir[2]);
|
|
mymax[0] *= 15;
|
|
mymax[1] *= 15;
|
|
mymax[2] *= 15;
|
|
|
|
R_RunParticleEffect2 (cl.Effects[index].Fountain.pos,mymin,mymax,
|
|
cl.Effects[index].Fountain.color,2,cl.Effects[index].Fountain.cnt);
|
|
|
|
/* memset(&test,0,sizeof(test));
|
|
trace = SV_Move (cl.Effects[index].Fountain.pos, mymin, mymax, mymin, false, &test);
|
|
Con_Printf("Fraction is %f\n",trace.fraction);*/
|
|
break;
|
|
|
|
case CE_QUAKE:
|
|
R_RunQuakeEffect (cl.Effects[index].Quake.origin,cl.Effects[index].Quake.radius);
|
|
break;
|
|
|
|
case CE_RIPPLE:
|
|
cl.Effects[index].Smoke.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index];
|
|
|
|
smoketime = cl.Effects[index].Smoke.framelength;
|
|
if (!smoketime)
|
|
smoketime = HX_FRAME_TIME*2;
|
|
|
|
while(cl.Effects[index].Smoke.time_amount >= smoketime&&ent->scale<250)
|
|
{
|
|
ent->frame++;
|
|
ent->angles[1]+=1;
|
|
cl.Effects[index].Smoke.time_amount -= smoketime;
|
|
}
|
|
|
|
if (ent->frame >= 10)
|
|
{
|
|
CL_FreeEffect(index);
|
|
}
|
|
else
|
|
CL_LinkEntity(ent);
|
|
break;
|
|
|
|
|
|
case CE_WHITE_SMOKE:
|
|
case CE_GREEN_SMOKE:
|
|
case CE_GREY_SMOKE:
|
|
case CE_RED_SMOKE:
|
|
case CE_SLOW_WHITE_SMOKE:
|
|
case CE_TELESMK1:
|
|
case CE_TELESMK2:
|
|
case CE_GHOST:
|
|
case CE_REDCLOUD:
|
|
case CE_FLAMESTREAM:
|
|
case CE_ACID_MUZZFL:
|
|
case CE_FLAMEWALL:
|
|
case CE_FLAMEWALL2:
|
|
case CE_ONFIRE:
|
|
cl.Effects[index].Smoke.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index];
|
|
|
|
smoketime = cl.Effects[index].Smoke.framelength;
|
|
if (!smoketime)
|
|
smoketime = HX_FRAME_TIME;
|
|
|
|
ent->origin[0] += (frametime/smoketime) * cl.Effects[index].Smoke.velocity[0];
|
|
ent->origin[1] += (frametime/smoketime) * cl.Effects[index].Smoke.velocity[1];
|
|
ent->origin[2] += (frametime/smoketime) * cl.Effects[index].Smoke.velocity[2];
|
|
|
|
i=0;
|
|
while(cl.Effects[index].Smoke.time_amount >= smoketime)
|
|
{
|
|
ent->frame++;
|
|
i++;
|
|
cl.Effects[index].Smoke.time_amount -= smoketime;
|
|
}
|
|
|
|
if (ent->frame >= ent->model->numframes)
|
|
{
|
|
CL_FreeEffect(index);
|
|
}
|
|
else
|
|
CL_LinkEntity(ent);
|
|
|
|
|
|
if(cl.Effects[index].type == CE_TELESMK1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index2];
|
|
|
|
ent->origin[0] -= (frametime/smoketime) * cl.Effects[index].Smoke.velocity[0];
|
|
ent->origin[1] -= (frametime/smoketime) * cl.Effects[index].Smoke.velocity[1];
|
|
ent->origin[2] -= (frametime/smoketime) * cl.Effects[index].Smoke.velocity[2];
|
|
|
|
ent->frame += i;
|
|
if (ent->frame < ent->model->numframes)
|
|
{
|
|
CL_LinkEntity(ent);
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Just go through animation and then remove
|
|
case CE_SM_WHITE_FLASH:
|
|
case CE_YELLOWRED_FLASH:
|
|
case CE_BLUESPARK:
|
|
case CE_YELLOWSPARK:
|
|
case CE_SM_CIRCLE_EXP:
|
|
case CE_BG_CIRCLE_EXP:
|
|
case CE_SM_EXPLOSION:
|
|
case CE_SM_EXPLOSION2:
|
|
case CE_BG_EXPLOSION:
|
|
case CE_FLOOR_EXPLOSION:
|
|
case CE_BLUE_EXPLOSION:
|
|
case CE_REDSPARK:
|
|
case CE_GREENSPARK:
|
|
case CE_ICEHIT:
|
|
case CE_MEDUSA_HIT:
|
|
case CE_MEZZO_REFLECT:
|
|
case CE_FLOOR_EXPLOSION2:
|
|
case CE_XBOW_EXPLOSION:
|
|
case CE_NEW_EXPLOSION:
|
|
case CE_MAGIC_MISSILE_EXPLOSION:
|
|
case CE_BONE_EXPLOSION:
|
|
case CE_BLDRN_EXPL:
|
|
case CE_BRN_BOUNCE:
|
|
case CE_ACID_HIT:
|
|
case CE_ACID_SPLAT:
|
|
case CE_ACID_EXPL:
|
|
case CE_LBALL_EXPL:
|
|
case CE_FBOOM:
|
|
case CE_BOMB:
|
|
case CE_FIREWALL_SMALL:
|
|
case CE_FIREWALL_MEDIUM:
|
|
case CE_FIREWALL_LARGE:
|
|
|
|
cl.Effects[index].Smoke.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index];
|
|
|
|
if (cl.Effects[index].type != CE_BG_CIRCLE_EXP)
|
|
{
|
|
while(cl.Effects[index].Smoke.time_amount >= HX_FRAME_TIME)
|
|
{
|
|
ent->frame++;
|
|
cl.Effects[index].Smoke.time_amount -= HX_FRAME_TIME;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(cl.Effects[index].Smoke.time_amount >= HX_FRAME_TIME * 2)
|
|
{
|
|
ent->frame++;
|
|
cl.Effects[index].Smoke.time_amount -= HX_FRAME_TIME * 2;
|
|
}
|
|
}
|
|
|
|
|
|
if (ent->frame >= ent->model->numframes)
|
|
{
|
|
CL_FreeEffect(index);
|
|
}
|
|
else
|
|
CL_LinkEntity(ent);
|
|
|
|
break;
|
|
|
|
// Go forward then backward through animation then remove
|
|
case CE_WHITE_FLASH:
|
|
case CE_BLUE_FLASH:
|
|
case CE_SM_BLUE_FLASH:
|
|
case CE_HWSPLITFLASH:
|
|
case CE_RED_FLASH:
|
|
cl.Effects[index].Flash.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Flash.entity_index];
|
|
|
|
while(cl.Effects[index].Flash.time_amount >= HX_FRAME_TIME)
|
|
{
|
|
if (!cl.Effects[index].Flash.reverse)
|
|
{
|
|
if (ent->frame >= ent->model->numframes-1) // Ran through forward animation
|
|
{
|
|
cl.Effects[index].Flash.reverse = 1;
|
|
ent->frame--;
|
|
}
|
|
else
|
|
ent->frame++;
|
|
|
|
}
|
|
else
|
|
ent->frame--;
|
|
|
|
cl.Effects[index].Flash.time_amount -= HX_FRAME_TIME;
|
|
}
|
|
|
|
if ((ent->frame <= 0) && (cl.Effects[index].Flash.reverse))
|
|
{
|
|
CL_FreeEffect(index);
|
|
}
|
|
else
|
|
CL_LinkEntity(ent);
|
|
break;
|
|
|
|
case CE_RIDER_DEATH:
|
|
cl.Effects[index].RD.time_amount += frametime;
|
|
if (cl.Effects[index].RD.time_amount >= 1)
|
|
{
|
|
cl.Effects[index].RD.stage++;
|
|
cl.Effects[index].RD.time_amount -= 1;
|
|
}
|
|
|
|
VectorCopy(cl.Effects[index].RD.origin,org);
|
|
org[0] += sin(cl.Effects[index].RD.time_amount * 2 * M_PI) * 30;
|
|
org[1] += cos(cl.Effects[index].RD.time_amount * 2 * M_PI) * 30;
|
|
|
|
if (cl.Effects[index].RD.stage <= 6)
|
|
{
|
|
RiderParticle(cl.Effects[index].RD.stage+1,org);
|
|
}
|
|
else
|
|
{
|
|
// To set the rider's origin point for the particles
|
|
RiderParticle(0,org);
|
|
if (cl.Effects[index].RD.stage == 7)
|
|
{
|
|
cl.cshifts[CSHIFT_BONUS].destcolor[0] = 255;
|
|
cl.cshifts[CSHIFT_BONUS].destcolor[1] = 255;
|
|
cl.cshifts[CSHIFT_BONUS].destcolor[2] = 255;
|
|
cl.cshifts[CSHIFT_BONUS].percent = 256;
|
|
}
|
|
else if (cl.Effects[index].RD.stage > 13)
|
|
{
|
|
// cl.Effects[index].RD.stage = 0;
|
|
CL_FreeEffect(index);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CE_TELEPORTERPUFFS:
|
|
cl.Effects[index].Teleporter.time_amount += frametime;
|
|
smoketime = cl.Effects[index].Teleporter.framelength;
|
|
|
|
ent = &EffectEntities[cl.Effects[index].Teleporter.entity_index[0]];
|
|
while(cl.Effects[index].Teleporter.time_amount >= HX_FRAME_TIME)
|
|
{
|
|
ent->frame++;
|
|
cl.Effects[index].Teleporter.time_amount -= HX_FRAME_TIME;
|
|
}
|
|
cur_frame = ent->frame;
|
|
|
|
if (cur_frame >= ent->model->numframes)
|
|
{
|
|
CL_FreeEffect(index);
|
|
break;
|
|
}
|
|
|
|
for (i=0;i<8;++i)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Teleporter.entity_index[i]];
|
|
|
|
ent->origin[0] += (frametime/smoketime) * cl.Effects[index].Teleporter.velocity[i][0];
|
|
ent->origin[1] += (frametime/smoketime) * cl.Effects[index].Teleporter.velocity[i][1];
|
|
ent->origin[2] += (frametime/smoketime) * cl.Effects[index].Teleporter.velocity[i][2];
|
|
ent->frame = cur_frame;
|
|
|
|
CL_LinkEntity(ent);
|
|
}
|
|
break;
|
|
case CE_TELEPORTERBODY:
|
|
cl.Effects[index].Teleporter.time_amount += frametime;
|
|
smoketime = cl.Effects[index].Teleporter.framelength;
|
|
|
|
ent = &EffectEntities[cl.Effects[index].Teleporter.entity_index[0]];
|
|
while(cl.Effects[index].Teleporter.time_amount >= HX_FRAME_TIME)
|
|
{
|
|
ent->scale -= 15;
|
|
cl.Effects[index].Teleporter.time_amount -= HX_FRAME_TIME;
|
|
}
|
|
|
|
ent = &EffectEntities[cl.Effects[index].Teleporter.entity_index[0]];
|
|
ent->angles[1] += 45;
|
|
|
|
if (ent->scale <= 10)
|
|
{
|
|
CL_FreeEffect(index);
|
|
}
|
|
else
|
|
{
|
|
CL_LinkEntity(ent);
|
|
}
|
|
break;
|
|
|
|
case CE_HWDRILLA:
|
|
cl.Effects[index].Missile.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
|
|
if ((int)(cl.time) != (int)(cl.time - host_frametime))
|
|
{
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_drillaspin, ent->origin, 1, 1);
|
|
}
|
|
|
|
ent->angles[0] += frametime * cl.Effects[index].Missile.avelocity[0];
|
|
ent->angles[1] += frametime * cl.Effects[index].Missile.avelocity[1];
|
|
ent->angles[2] += frametime * cl.Effects[index].Missile.avelocity[2];
|
|
|
|
VectorCopy(ent->origin,old_origin);
|
|
|
|
ent->origin[0] += frametime * cl.Effects[index].Missile.velocity[0];
|
|
ent->origin[1] += frametime * cl.Effects[index].Missile.velocity[1];
|
|
ent->origin[2] += frametime * cl.Effects[index].Missile.velocity[2];
|
|
|
|
R_RocketTrail (old_origin, ent->origin, rt_setstaff);
|
|
|
|
CL_LinkEntity(ent);
|
|
break;
|
|
case CE_HWXBOWSHOOT:
|
|
cl.Effects[index].Xbow.time_amount += frametime;
|
|
for (i=0;i<cl.Effects[index].Xbow.bolts;i++)
|
|
{
|
|
if (cl.Effects[index].Xbow.ent[i] != -1)//only update valid effect ents
|
|
{
|
|
if (cl.Effects[index].Xbow.activebolts & (1<<i))//bolt in air, simply update position
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[i]];
|
|
|
|
ent->origin[0] += frametime * cl.Effects[index].Xbow.vel[i][0];
|
|
ent->origin[1] += frametime * cl.Effects[index].Xbow.vel[i][1];
|
|
ent->origin[2] += frametime * cl.Effects[index].Xbow.vel[i][2];
|
|
|
|
CL_LinkEntity(ent);
|
|
}
|
|
else if (cl.Effects[index].Xbow.bolts == 5)//fiery bolts don't just go away
|
|
{
|
|
if (cl.Effects[index].Xbow.state[i] == 0)//waiting to explode state
|
|
{
|
|
if (cl.Effects[index].Xbow.gonetime[i] > cl.time)//fiery bolts stick around for a while
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[i]];
|
|
CL_LinkEntity(ent);
|
|
}
|
|
else//when time's up on fiery guys, they explode
|
|
{
|
|
//set state to exploding
|
|
cl.Effects[index].Xbow.state[i] = 1;
|
|
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[i]];
|
|
|
|
//move bolt back a little to make explosion look better
|
|
VectorNormalize(cl.Effects[index].Xbow.vel[i]);
|
|
VectorScale(cl.Effects[index].Xbow.vel[i],-8,cl.Effects[index].Xbow.vel[i]);
|
|
VectorAdd(ent->origin,cl.Effects[index].Xbow.vel[i],ent->origin);
|
|
|
|
//turn bolt entity into an explosion
|
|
ent->model = Mod_ForName("models/xbowexpl.spr", true);
|
|
ent->frame = 0;
|
|
|
|
//set frame change counter
|
|
cl.Effects[index].Xbow.gonetime[i] = cl.time + HX_FRAME_TIME * 2;
|
|
|
|
//play explosion sound
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_explode, ent->origin, 1, 1);
|
|
|
|
CL_LinkEntity(ent);
|
|
}
|
|
}
|
|
else if (cl.Effects[index].Xbow.state[i] == 1)//fiery bolt exploding state
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[i]];
|
|
|
|
//increment frame if it's time
|
|
while(cl.Effects[index].Xbow.gonetime[i] <= cl.time)
|
|
{
|
|
ent->frame++;
|
|
cl.Effects[index].Xbow.gonetime[i] += HX_FRAME_TIME * 0.75;
|
|
}
|
|
|
|
|
|
if (ent->frame >= ent->model->numframes)
|
|
{
|
|
cl.Effects[index].Xbow.state[i] = 2;//if anim is over, set me to inactive state
|
|
}
|
|
else
|
|
CL_LinkEntity(ent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case CE_HWSHEEPINATOR:
|
|
cl.Effects[index].Xbow.time_amount += frametime;
|
|
for (i=0;i<cl.Effects[index].Xbow.bolts;i++)
|
|
{
|
|
if (cl.Effects[index].Xbow.ent[i] != -1)//only update valid effect ents
|
|
{
|
|
if (cl.Effects[index].Xbow.activebolts & (1<<i))//bolt in air, simply update position
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Xbow.ent[i]];
|
|
|
|
ent->origin[0] += frametime * cl.Effects[index].Xbow.vel[i][0];
|
|
ent->origin[1] += frametime * cl.Effects[index].Xbow.vel[i][1];
|
|
ent->origin[2] += frametime * cl.Effects[index].Xbow.vel[i][2];
|
|
|
|
R_RunParticleEffect4(ent->origin,7,(rand()%15)+144,pt_explode2,(rand()%5)+1);
|
|
|
|
CL_LinkEntity(ent);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case CE_DEATHBUBBLES:
|
|
cl.Effects[index].Bubble.time_amount += frametime;
|
|
if (cl.Effects[index].Bubble.time_amount > 0.1)//10 bubbles a sec
|
|
{
|
|
cl.Effects[index].Bubble.time_amount = 0;
|
|
cl.Effects[index].Bubble.count--;
|
|
es = FindState(cl.Effects[index].Bubble.owner);
|
|
if (es)
|
|
{
|
|
VectorCopy(es->origin,org);
|
|
VectorAdd(org,cl.Effects[index].Bubble.offset,org);
|
|
|
|
l = Mod_PointInLeaf (org, cl.worldmodel);
|
|
if(l->contents!=CONTENTS_WATER)
|
|
{ //not in water anymore
|
|
CL_FreeEffect(index);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
CLTENT_SpawnDeathBubble(org);
|
|
}
|
|
}
|
|
}
|
|
if (cl.Effects[index].Bubble.count <= 0)
|
|
CL_FreeEffect(index);
|
|
break;
|
|
case CE_SCARABCHAIN:
|
|
cl.Effects[index].Chain.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Chain.ent1];
|
|
|
|
switch (cl.Effects[index].Chain.state)
|
|
{
|
|
case 0://zooming in toward owner
|
|
es = FindState(cl.Effects[index].Chain.owner);
|
|
if (cl.Effects[index].Chain.sound_time <= cl.time)
|
|
{
|
|
cl.Effects[index].Chain.sound_time = cl.time + 0.5;
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_scarabhome, ent->origin, 1, 1);
|
|
}
|
|
if (es)
|
|
{
|
|
VectorCopy(es->origin,org);
|
|
org[2]+=cl.Effects[index].Chain.height;
|
|
VectorSubtract(org,ent->origin,org);
|
|
if (fabs(VectorNormalize(org))<500*frametime)
|
|
{
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_scarabgrab, ent->origin, 1, 1);
|
|
cl.Effects[index].Chain.state = 1;
|
|
VectorCopy(es->origin, ent->origin);
|
|
ent->origin[2] += cl.Effects[index].Chain.height;
|
|
XbowImpactPuff(ent->origin, cl.Effects[index].Chain.material);
|
|
}
|
|
else
|
|
{
|
|
VectorScale(org,500*frametime,org);
|
|
VectorAdd(ent->origin,org,ent->origin);
|
|
}
|
|
}
|
|
break;
|
|
case 1://attached--snap to owner's pos
|
|
es = FindState(cl.Effects[index].Chain.owner);
|
|
if (es)
|
|
{
|
|
VectorCopy(es->origin, ent->origin);
|
|
ent->origin[2] += cl.Effects[index].Chain.height;
|
|
}
|
|
break;
|
|
case 2://unattaching, server needs to set this state
|
|
VectorCopy(ent->origin,org);
|
|
VectorSubtract(cl.Effects[index].Chain.origin,org,org);
|
|
if (fabs(VectorNormalize(org))>350*frametime)//closer than 30 is too close?
|
|
{
|
|
VectorScale(org,350*frametime,org);
|
|
VectorAdd(ent->origin,org,ent->origin);
|
|
}
|
|
else//done--flash & git outa here (change type to redflash)
|
|
{
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_scarabbyebye, ent->origin, 1, 1);
|
|
cl.Effects[index].Flash.entity_index = cl.Effects[index].Chain.ent1;
|
|
cl.Effects[index].type = CE_RED_FLASH;
|
|
VectorCopy(ent->origin,cl.Effects[index].Flash.origin);
|
|
cl.Effects[index].Flash.reverse = 0;
|
|
ent->model = Mod_ForName("models/redspt.spr", true);
|
|
ent->frame = 0;
|
|
ent->drawflags = DRF_TRANSLUCENT;
|
|
}
|
|
break;
|
|
}
|
|
|
|
CL_LinkEntity(ent);
|
|
|
|
//damndamndamn--add stream stuff here!
|
|
VectorCopy(cl.Effects[index].Chain.origin, org);
|
|
VectorCopy(ent->origin, org2);
|
|
CreateStream(TE_STREAM_CHAIN, cl.Effects[index].Chain.ent1, 1, cl.Effects[index].Chain.tag, 0.1, 0, org, org2);
|
|
|
|
break;
|
|
case CE_TRIPMINESTILL:
|
|
cl.Effects[index].Chain.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Chain.ent1];
|
|
|
|
// if (cl.Effects[index].Chain.ent1 < 0)//fixme: remove this!!!
|
|
// Con_DPrintf("OHSHITOHSHIT--bad chain ent\n");
|
|
|
|
CL_LinkEntity(ent);
|
|
// Con_DPrintf("Chain Ent at: %d %d %d\n",(int)cl.Effects[index].Chain.origin[0],(int)cl.Effects[index].Chain.origin[1],(int)cl.Effects[index].Chain.origin[2]);
|
|
|
|
//damndamndamn--add stream stuff here!
|
|
VectorCopy(cl.Effects[index].Chain.origin, org);
|
|
VectorCopy(ent->origin, org2);
|
|
CreateStream(TE_STREAM_CHAIN, cl.Effects[index].Chain.ent1, 1, 1, 0.1, 0, org, org2);
|
|
|
|
break;
|
|
case CE_TRIPMINE:
|
|
cl.Effects[index].Chain.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Chain.ent1];
|
|
|
|
ent->origin[0] += frametime * cl.Effects[index].Chain.velocity[0];
|
|
ent->origin[1] += frametime * cl.Effects[index].Chain.velocity[1];
|
|
ent->origin[2] += frametime * cl.Effects[index].Chain.velocity[2];
|
|
|
|
CL_LinkEntity(ent);
|
|
|
|
//damndamndamn--add stream stuff here!
|
|
VectorCopy(cl.Effects[index].Chain.origin, org);
|
|
VectorCopy(ent->origin, org2);
|
|
CreateStream(TE_STREAM_CHAIN, cl.Effects[index].Chain.ent1, 1, 1, 0.1, 0, org, org2);
|
|
|
|
break;
|
|
case CE_BONESHARD:
|
|
case CE_BONESHRAPNEL:
|
|
case CE_HWBONEBALL:
|
|
case CE_HWRAVENSTAFF:
|
|
case CE_HWRAVENPOWER:
|
|
cl.Effects[index].Missile.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
|
|
// ent->angles[0] = cl.Effects[index].Missile.angle[0];
|
|
// ent->angles[1] = cl.Effects[index].Missile.angle[1];
|
|
// ent->angles[2] = cl.Effects[index].Missile.angle[2];
|
|
|
|
ent->angles[0] += frametime * cl.Effects[index].Missile.avelocity[0];
|
|
ent->angles[1] += frametime * cl.Effects[index].Missile.avelocity[1];
|
|
ent->angles[2] += frametime * cl.Effects[index].Missile.avelocity[2];
|
|
|
|
ent->origin[0] += frametime * cl.Effects[index].Missile.velocity[0];
|
|
ent->origin[1] += frametime * cl.Effects[index].Missile.velocity[1];
|
|
ent->origin[2] += frametime * cl.Effects[index].Missile.velocity[2];
|
|
if(cl.Effects[index].type == CE_HWRAVENPOWER)
|
|
{
|
|
while(cl.Effects[index].Missile.time_amount >= HX_FRAME_TIME)
|
|
{
|
|
ent->frame++;
|
|
cl.Effects[index].Missile.time_amount -= HX_FRAME_TIME;
|
|
}
|
|
|
|
if (ent->frame > 7)
|
|
{
|
|
ent->frame = 0;
|
|
break;
|
|
}
|
|
}
|
|
CL_LinkEntity(ent);
|
|
if(cl.Effects[index].type == CE_HWBONEBALL)
|
|
{
|
|
R_RunParticleEffect4 (ent->origin, 10, 368 + rand() % 16, pt_slowgrav, 3);
|
|
|
|
}
|
|
break;
|
|
case CE_HWMISSILESTAR:
|
|
case CE_HWEIDOLONSTAR:
|
|
// update scale
|
|
if(cl.Effects[index].Star.scaleDir)
|
|
{
|
|
cl.Effects[index].Star.scale += 0.05;
|
|
if(cl.Effects[index].Star.scale >= 1)
|
|
{
|
|
cl.Effects[index].Star.scaleDir = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cl.Effects[index].Star.scale -= 0.05;
|
|
if(cl.Effects[index].Star.scale <= 0.01)
|
|
{
|
|
cl.Effects[index].Star.scaleDir = 1;
|
|
}
|
|
}
|
|
|
|
cl.Effects[index].Star.time_amount += frametime;
|
|
ent = &EffectEntities[cl.Effects[index].Star.entity_index];
|
|
|
|
ent->angles[0] += frametime * cl.Effects[index].Star.avelocity[0];
|
|
ent->angles[1] += frametime * cl.Effects[index].Star.avelocity[1];
|
|
ent->angles[2] += frametime * cl.Effects[index].Star.avelocity[2];
|
|
|
|
ent->origin[0] += frametime * cl.Effects[index].Star.velocity[0];
|
|
ent->origin[1] += frametime * cl.Effects[index].Star.velocity[1];
|
|
ent->origin[2] += frametime * cl.Effects[index].Star.velocity[2];
|
|
|
|
CL_LinkEntity(ent);
|
|
|
|
if (cl.Effects[index].Star.ent1 != -1)
|
|
{
|
|
ent2= &EffectEntities[cl.Effects[index].Star.ent1];
|
|
VectorCopy(ent->origin, ent2->origin);
|
|
ent2->scale = cl.Effects[index].Star.scale;
|
|
ent2->angles[1] += frametime * 300;
|
|
ent2->angles[2] += frametime * 400;
|
|
CL_LinkEntity(ent2);
|
|
}
|
|
if(cl.Effects[index].type == CE_HWMISSILESTAR)
|
|
{
|
|
if (cl.Effects[index].Star.ent2 != -1)
|
|
{
|
|
ent2 = &EffectEntities[cl.Effects[index].Star.ent2];
|
|
VectorCopy(ent->origin, ent2->origin);
|
|
ent2->scale = cl.Effects[index].Star.scale;
|
|
ent2->angles[1] += frametime * -300;
|
|
ent2->angles[2] += frametime * -400;
|
|
CL_LinkEntity(ent2);
|
|
}
|
|
}
|
|
if(rand() % 10 < 3)
|
|
{
|
|
R_RunParticleEffect4 (ent->origin, 7, 148 + rand() % 11, pt_grav, 10 + rand() % 10);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
// Con_DPrintf("Effect Ents: %d\n",EffectEntityCount);
|
|
}
|
|
|
|
// this creates multi effects from one packet
|
|
void CreateRavenExplosions(vec3_t pos);
|
|
void CL_ParseMultiEffect(void)
|
|
{
|
|
int type, index, count;
|
|
vec3_t orig, vel, right;
|
|
entity_t *ent;
|
|
|
|
type = MSG_ReadByte();
|
|
switch(type)
|
|
{
|
|
case CE_HWRAVENPOWER:
|
|
orig[0] = MSG_ReadCoord();
|
|
orig[1] = MSG_ReadCoord();
|
|
orig[2] = MSG_ReadCoord();
|
|
vel[0] = MSG_ReadCoord();
|
|
vel[1] = MSG_ReadCoord();
|
|
vel[2] = MSG_ReadCoord();
|
|
for(count=0;count<3;count++)
|
|
{
|
|
index = MSG_ReadByte();
|
|
// create the effect
|
|
cl.Effects[index].type = type;
|
|
VectorCopy(orig, cl.Effects[index].Missile.origin);
|
|
VectorCopy(vel, cl.Effects[index].Missile.velocity);
|
|
vectoangles(cl.Effects[index].Missile.velocity, cl.Effects[index].Missile.angle);
|
|
if ((cl.Effects[index].Missile.entity_index = NewEffectEntity()) != -1)
|
|
{
|
|
ent = &EffectEntities[cl.Effects[index].Missile.entity_index];
|
|
VectorCopy(cl.Effects[index].Missile.origin, ent->origin);
|
|
VectorCopy(cl.Effects[index].Missile.angle, ent->angles);
|
|
ent->model = Mod_ForName("models/ravproj.mdl", true);
|
|
S_StartSound (TempSoundChannel(), 1, cl_fxsfx_ravengo, cl.Effects[index].Missile.origin, 1, 1);
|
|
}
|
|
}
|
|
CreateRavenExplosions(orig);
|
|
break;
|
|
default:
|
|
Sys_Error ("CL_ParseMultiEffect: bad type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// NewEffectEntity
|
|
//
|
|
//==========================================================================
|
|
|
|
static int NewEffectEntity(void)
|
|
{
|
|
entity_t *ent;
|
|
int counter;
|
|
|
|
if(cl_numvisedicts == MAX_VISEDICTS)
|
|
{
|
|
return -1;
|
|
}
|
|
if(EffectEntityCount == MAX_EFFECT_ENTITIES)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
for(counter=0;counter<MAX_EFFECT_ENTITIES;counter++)
|
|
if (!EntityUsed[counter])
|
|
break;
|
|
|
|
EntityUsed[counter] = true;
|
|
EffectEntityCount++;
|
|
ent = &EffectEntities[counter];
|
|
memset(ent, 0, sizeof(*ent));
|
|
ent->colormap = vid.colormap;
|
|
|
|
return counter;
|
|
}
|
|
|
|
static void FreeEffectEntity(int index)
|
|
{
|
|
if (index != -1 && EntityUsed[index])
|
|
{
|
|
EntityUsed[index] = false;
|
|
EffectEntityCount--;
|
|
}
|
|
else if (index != -1)
|
|
{
|
|
EffectEntityCount--;//still decrement counter; since value is -1, counter was incremented
|
|
// Con_DPrintf("ERROR: Redeleting Effect Entity: %d!\n",index);//fixme: this should not be in final version
|
|
}
|
|
else
|
|
{
|
|
// Con_DPrintf("ERROR: Deleting Invalid Effect Entity: %d!\n",index);//fixme: this should not be in final version
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* $Log: /HexenWorld/Client/cl_effect.c $
|
|
*
|
|
* 89 5/25/98 1:29p Mgummelt
|
|
*
|
|
* 88 5/07/98 8:26p Mgummelt
|
|
*
|
|
* 87 5/05/98 8:33p Mgummelt
|
|
* Added 6th playerclass for Siege only- Dwarf
|
|
*
|
|
* 86 4/24/98 1:31a Mgummelt
|
|
* Siege version 0.02 4/24/98 1:31 AM
|
|
*
|
|
* 85 4/23/98 5:15p Mgummelt
|
|
* Fixes for Siege
|
|
*
|
|
* 84 4/20/98 8:16p Mgummelt
|
|
* Added CE_Ripple
|
|
*
|
|
* 83 4/20/98 2:02p Rjohnson
|
|
* Big update
|
|
*
|
|
* 82 4/10/98 3:45p Ssengele
|
|
* made xbolt explosions fast...Way too fast...
|
|
*
|
|
* 81 4/01/98 3:03p Ssengele
|
|
* faster xbolts, initial optimizing of forcecube.
|
|
*
|
|
* 80 3/26/98 5:00p Mgummelt
|
|
* Added new Mission Pack client effects for succubus' weapons
|
|
*
|
|
* 79 3/20/98 1:41p Ssengele
|
|
* commented debug messages
|
|
*
|
|
* 78 3/19/98 8:32p Ssengele
|
|
* scarab chains instantly attach to ya, to alleviate possible problems
|
|
* with them setting values on a target they might not ever hit.
|
|
*
|
|
* 77 3/14/98 3:17p Ssengele
|
|
* lambinator doesn't make xbow sound when firing anymore--old cut 'n'
|
|
* paste thing. is there a lambinator sound?
|
|
*
|
|
* 76 3/13/98 1:20a Ssengele
|
|
* debug message out
|
|
*
|
|
* 75 3/13/98 1:19a Ssengele
|
|
* client effect crash fixed--xbow bolts were using visedicts even tho
|
|
* they were set to -1
|
|
*
|
|
* 74 3/12/98 12:31p Ssengele
|
|
* same fix as previous check-in, in a different spot.
|
|
*
|
|
* 73 3/12/98 12:30p Ssengele
|
|
* fixed bug with drilla--new coordinates always sent, but weren't always
|
|
* looked for.
|
|
*
|
|
* 72 3/11/98 9:46p Ssengele
|
|
* xbolts (& theoretically, setstaff & lambinator) teleport cleanly.
|
|
* currently cause a spike, which can and will be fixed soon.
|
|
* server by default only sends the effects close enough to client to
|
|
* matter to that client.
|
|
*
|
|
* 71 3/10/98 8:00p Ssengele
|
|
* debug print
|
|
*
|
|
* 70 3/10/98 5:31p Ssengele
|
|
* client asks for effect if origin changes and client doesn't recognize
|
|
* effect. more info for effect kept updated on server. almost ready for
|
|
* effects to work thru teleporters. hmm...will look into how much
|
|
* traffic the arrows, lambinator, and drilla would take if they used
|
|
* nailgun code.
|
|
*
|
|
* 69 3/10/98 3:54p Ssengele
|
|
* fixed client effects getting screwed up--xbolt effect ents were getting
|
|
* removed without being set validly
|
|
*
|
|
* 68 3/09/98 4:47p Ssengele
|
|
* started solidifying server tracking of updateable effects: not used
|
|
* yet; made recoil from daggerdive less extreme than jab; made sure
|
|
* update message doesn't write over effect info if the type updated is
|
|
* different from the type already there.
|
|
*
|
|
* 67 3/09/98 2:47p Rmidthun
|
|
* when turneffect is called and the effect does not exist, the client
|
|
* will ask for the effect.
|
|
*
|
|
* 66 3/07/98 3:52p Rjohnson
|
|
* Doesn't stop the game if max vis edicts is reached
|
|
*
|
|
* 65 3/07/98 3:07p Rjohnson
|
|
* Increased the max number of vis edicts, and added a check to make sure
|
|
* we don't overflow
|
|
*
|
|
* 64 3/06/98 4:07p Ssengele
|
|
* impact effect for ovinomancer jobby
|
|
*
|
|
* 63 3/06/98 12:04p Ssengele
|
|
* fixed bug in failsafe--cut-and-paste made drilla completely screwed
|
|
*
|
|
* 62 3/06/98 11:25a Rmidthun
|
|
* ravens needed their animation put back
|
|
*
|
|
* 61 3/05/98 9:58p Ssengele
|
|
* attempt to limit flickering of scarab chains; minimum of 3 b&g mana for
|
|
* untomed scarab
|
|
*
|
|
* 60 3/05/98 5:57p Ssengele
|
|
* failsafes for updating effects
|
|
*
|
|
* 59 3/05/98 12:19p Ssengele
|
|
* sheepinator spead corrected
|
|
*
|
|
* 58 3/04/98 9:58a Rmidthun
|
|
* moved ravenshot explosion into its remove effect
|
|
*
|
|
* 57 3/03/98 8:49p Ssengele
|
|
* untomed scarab staff should turn now
|
|
*
|
|
* 56 3/03/98 8:09p Ssengele
|
|
* reflection code for xbow bolts and sheepinator; also, a little variance
|
|
* for where bolts start out, so autoaim doesn't make them clump up quite
|
|
* as much (variance is consistent between sv & cl)
|
|
*
|
|
* 55 3/03/98 4:43p Ssengele
|
|
* sheepinator uses xbow code now.
|
|
*
|
|
* 54 3/03/98 3:01p Rmidthun
|
|
* client effect missiles needed an update function to be called when
|
|
* other things change their velocity, this was put into invntory.hc.
|
|
*
|
|
* 53 3/03/98 1:58p Ssengele
|
|
* er, took a break from weapon stuff to move the bubble code over to a
|
|
* client effect
|
|
*
|
|
* 52 3/03/98 11:51a Ssengele
|
|
* moved untomed setstaff drilling to client (will add meat chunks to
|
|
* client stuff if time permits)
|
|
*
|
|
* 51 3/02/98 6:02p Ssengele
|
|
* made scarab chains disappear w/o being burden on nettraffic
|
|
*
|
|
* 50 3/02/98 4:12p Ssengele
|
|
* minor improvement for xbow, punchdagger sheep gone away
|
|
*
|
|
* 49 3/02/98 2:35p Ssengele
|
|
* set staff worst-case not bad at all anymore--the drilla is an effect
|
|
*
|
|
* 48 3/02/98 12:36p Ssengele
|
|
* shaved a few bytes from powered up setstaff (moving puffs to client),
|
|
* have begun working on worst-case unpowered setstaff (explosions are now
|
|
* tempent
|
|
* vs effect & sound they were before). unpowered ss still clogs up net
|
|
* when firing fast--i believe i'll make the whole thing an effect.
|
|
*
|
|
* 47 2/28/98 3:40p Rjohnson
|
|
* Added protos for all the particle effects, and changed the radius for
|
|
* the crossbow hit
|
|
*
|
|
* 46 2/28/98 3:26p Ssengele
|
|
* some work on set staff
|
|
*
|
|
* 45 2/27/98 7:29p Ssengele
|
|
* shaved off a couple more bytes from the xbow
|
|
*
|
|
* 44 2/27/98 7:12p Ssengele
|
|
* grrrrrrrr...xbow more optimized than ever (plus chunks, or did i add
|
|
* those yesterday?), still spiking not-so-pretty (nudges first red line)
|
|
* occasionally in the worst case scenario.
|
|
*
|
|
* 43 2/27/98 1:48p Rmidthun
|
|
* seems to be a problem when turneffect is lagged, trying to correct it
|
|
*
|
|
* 42 2/26/98 7:47p Ssengele
|
|
* redirected arrows' angles correct
|
|
*
|
|
* 41 2/26/98 6:55p Ssengele
|
|
* arrows fall into bits
|
|
*
|
|
* 40 2/26/98 5:55p Rmidthun
|
|
* started work on correction mechanism for missile client effects
|
|
*
|
|
* 39 2/26/98 4:19p Rmidthun
|
|
* added pos to turneffect so it can correct if need be, still working on
|
|
* the actual correction
|
|
*
|
|
* 38 2/26/98 3:55p Rmidthun
|
|
* powered ravenstaff uses multieffect, also moved tempent stuff to be
|
|
* called from client effects, there is STILL a little red and I'm not
|
|
* sure if the client effects are always in the correct place, but it
|
|
* should be close anyway.
|
|
*
|
|
* 37 2/26/98 2:35p Ssengele
|
|
* added rubbly particles for xbow impact; er, they last kinda long right
|
|
* now...
|
|
*
|
|
* 36 2/26/98 2:03p Ssengele
|
|
* further optimizing of xbow--at impact, i send distance it travelled
|
|
* rather than end pos; pack alot of little pieces of info into a byte
|
|
*
|
|
* 35 2/26/98 1:34p Rmidthun
|
|
* working on multiple effects with one net message
|
|
*
|
|
* 34 2/25/98 7:21p Ssengele
|
|
* scarab chains look normal when they hit somebody other than their
|
|
* target.
|
|
*
|
|
* 33 2/25/98 4:00p Rmidthun
|
|
* ravens are now client effect too, still need to reduce the large
|
|
* creation spike
|
|
*
|
|
* 32 2/25/98 12:22p Rjohnson
|
|
* Put back some particle effects
|
|
*
|
|
* 31 2/24/98 2:26p Ssengele
|
|
* xbow impact in correct position. !whew!
|
|
*
|
|
* 30 2/24/98 11:44a Rmidthun
|
|
* magic missiles are client effects, the homing function sends updates
|
|
*
|
|
* 29 2/24/98 11:07a Ssengele
|
|
* debugging
|
|
*
|
|
* 28 2/24/98 10:18a Rmidthun
|
|
* telesmk1 will now do both smoke puffs and the sound
|
|
*
|
|
* 27 2/23/98 8:04p Ssengele
|
|
* erg--checking in so's not to hog these files TOO much. cleffect that
|
|
* handles multiple xbow bolts is IN, but impact is neither consistant nor
|
|
* in the right spot.
|
|
*
|
|
* 26 2/23/98 10:44a Rmidthun
|
|
* bone shards should rotate differently
|
|
*
|
|
* 25 2/23/98 9:48a Rmidthun
|
|
* combined small blue flash and split sound for raven staff
|
|
*
|
|
* 24 2/20/98 7:32p Ssengele
|
|
* scarab staff faster, lookin' good. much like the xbow stuff, it spikes
|
|
* and then becomes fine; will work more on it later (movin back to xbow
|
|
* improving).
|
|
*
|
|
* 23 2/20/98 4:45p Rmidthun
|
|
* moved rest of sounds to client side
|
|
*
|
|
* 22 2/20/98 3:53p Ssengele
|
|
* scarab staff ok, still needs a good chunk of work: only one chain seems
|
|
* to be rendering
|
|
*
|
|
* 21 2/20/98 1:21p Rmidthun
|
|
* missile rotation
|
|
*
|
|
* 20 2/20/98 1:05p Rmidthun
|
|
* sounds use TempSoundChannel so they don't cut each other off, fixed
|
|
* angles for missile effects
|
|
*
|
|
* 19 2/20/98 12:16p Ssengele
|
|
* client is ready for scarab chain to be a client effect--feel free to
|
|
* make ce_scarabchain be some other value
|
|
*
|
|
* 18 2/20/98 10:08a Rmidthun
|
|
* bone shards don't need to send angle or angular vel
|
|
*
|
|
* 17 2/19/98 8:07p Ssengele
|
|
* tripmine client effect in--added access to streams in cl_effect
|
|
*
|
|
* 16 2/19/98 7:01p Rmidthun
|
|
* ravenstaff is almost all client effect, added a "turneffect" builtin to
|
|
* reduce net traffic further
|
|
*
|
|
* 15 2/19/98 4:52p Rmidthun
|
|
* added ravenstaff missile, it isn't used just yet
|
|
*
|
|
* 14 2/19/98 3:55p Rmidthun
|
|
* boneball added
|
|
*
|
|
* 13 2/19/98 3:00p Ssengele
|
|
* very basic framework for tripmine chain--no access to streams from
|
|
* cl_effects, tho, which causes me great pain and sorrow
|
|
*
|
|
* 12 2/19/98 2:08p Rmidthun
|
|
*
|
|
* 11 2/19/98 12:45p Ssengele
|
|
* put in client effect for powered-up xbow; spikes even bigger than
|
|
* normal xbow,tho, so i'd like to chunk all of the arrows into one big
|
|
* client effect, rather than give each of them their own. this i'll do
|
|
* later.
|
|
*
|
|
* 10 2/19/98 11:13a Ssengele
|
|
* made xbow sound-playing a little nicer
|
|
*
|
|
* 9 2/18/98 8:25p Ssengele
|
|
* xbow client effect (for normal mode) lookin good--but it trades off
|
|
* significantly less traffic when arrows are in air for a slightly bigger
|
|
* spike when they're fired. will figure out how to minimize that spike
|
|
* yet.
|
|
*
|
|
* 8 2/18/98 5:37p Ssengele
|
|
* start at xbow bolt client effect
|
|
*
|
|
* 7 2/18/98 2:14p Rmidthun
|
|
* moved sound to client effect
|
|
*
|
|
* 6 2/18/98 11:50a Rmidthun
|
|
* eidolon missile (in case someone wants coop)
|
|
*
|
|
* 5 2/18/98 10:29a Rmidthun
|
|
*
|
|
* 4 2/17/98 6:52p Rmidthun
|
|
* started moving star to client effect, its about halfway done, I checked
|
|
* in so others could use it
|
|
*
|
|
* 3 2/06/98 4:43p Rjohnson
|
|
* Got client interpolation in
|
|
*
|
|
* 2 2/05/98 1:23a Rjohnson
|
|
* Got network protocols aligned
|
|
*
|
|
* 1 2/04/98 11:33p Rjohnson
|
|
*
|
|
* 32 10/13/97 10:28a Rlove
|
|
* Made the bone shard powerup more network friendly.
|
|
*
|
|
* 31 10/10/97 9:13a Rlove
|
|
* Moved bone shard shrapnel to client side effect
|
|
*
|
|
* 30 10/08/97 11:14a Rlove
|
|
*
|
|
* 29 10/06/97 12:19p Rjohnson
|
|
* Fixed a name
|
|
*
|
|
* 28 10/06/97 12:14p Rlove
|
|
*
|
|
* 27 10/06/97 11:41a Rjohnson
|
|
* Partically fixed teleporter effect
|
|
*
|
|
* 26 9/25/97 2:31p Rlove
|
|
*
|
|
* 25 9/04/97 4:44p Rjohnson
|
|
* Updates
|
|
*
|
|
* 24 8/22/97 7:25a Rlove
|
|
* Added red cloud temp effect
|
|
*
|
|
* 23 8/07/97 9:00a Rlove
|
|
*
|
|
* 22 8/06/97 3:46p Rjohnson
|
|
* Rider death update
|
|
*
|
|
* 21 8/04/97 4:44p Rjohnson
|
|
* Rider's Death doesn't repeat
|
|
*
|
|
* 20 7/31/97 2:49p Rlove
|
|
* Added a few new effect entities
|
|
*
|
|
* 19 7/25/97 3:12p Rlove
|
|
*
|
|
* 18 7/25/97 3:05p Rlove
|
|
*
|
|
* 17 7/24/97 3:31p Rlove
|
|
*
|
|
* 16 7/24/97 3:28p Rlove
|
|
*
|
|
* 15 7/01/97 4:09p Rjohnson
|
|
* Saving / Loading of client effects
|
|
*
|
|
* 14 6/30/97 10:29a Rlove
|
|
* Added wait to rain entity
|
|
*
|
|
* 13 6/13/97 11:42a Rlove
|
|
*
|
|
* 12 6/12/97 12:13p Rlove
|
|
* Added red and green sparks
|
|
*
|
|
* 11 6/12/97 6:42a Rlove
|
|
* Smoke entities are being deleted (before they weren't)
|
|
*
|
|
* 10 6/04/97 9:59a Rjohnson
|
|
* Added flash effect for rider's death
|
|
*
|
|
* 9 6/03/97 10:26a Rlove
|
|
*
|
|
* 8 6/03/97 9:00a Rlove
|
|
* Added fx_smoke_generator entity
|
|
*
|
|
* 7 5/30/97 12:01p Rlove
|
|
* New blue explosion
|
|
*
|
|
* 6 5/30/97 11:42a Rjohnson
|
|
* Removed the message field of the effects
|
|
*
|
|
* 5 5/28/97 10:45a Rlove
|
|
* Moved sprite effects to client side - smoke, explosions, and flashes.
|
|
*
|
|
* 4 5/27/97 4:46p Rjohnson
|
|
* Added the smoke puff effect
|
|
*
|
|
* 3 5/23/97 3:05p Rjohnson
|
|
* Update to effects / particle types
|
|
*
|
|
* 2 5/20/97 11:32a Rjohnson
|
|
* Revised Effects
|
|
*
|
|
* 1 5/19/97 2:54p Rjohnson
|
|
* Initial Version
|
|
*/
|