hexen2/H2MP/code/cl_effect.c

2701 lines
87 KiB
C

//**************************************************************************
//**
//** cl_effect.c
//**
//** Client side effects.
//**
//** $Header: /H2 Mission Pack/cl_effect.c 41 3/20/98 12:55p Jmonroe $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
#include "quakedef.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
#define CE_NONE 0
#define CE_RAIN 1
#define CE_FOUNTAIN 2
#define CE_QUAKE 3
#define CE_WHITE_SMOKE 4 // whtsmk1.spr
#define CE_BLUESPARK 5 // bspark.spr
#define CE_YELLOWSPARK 6 // spark.spr
#define CE_SM_CIRCLE_EXP 7 // fcircle.spr
#define CE_BG_CIRCLE_EXP 8 // fcircle.spr
#define CE_SM_WHITE_FLASH 9 // sm_white.spr
#define CE_WHITE_FLASH 10 // gryspt.spr
#define CE_YELLOWRED_FLASH 11 // yr_flash.spr
#define CE_BLUE_FLASH 12 // bluflash.spr
#define CE_SM_BLUE_FLASH 13 // bluflash.spr
#define CE_RED_FLASH 14 // redspt.spr
#define CE_SM_EXPLOSION 15 // sm_expld.spr
#define CE_LG_EXPLOSION 16 // bg_expld.spr
#define CE_FLOOR_EXPLOSION 17 // fl_expld.spr
#define CE_RIDER_DEATH 18
#define CE_BLUE_EXPLOSION 19 // xpspblue.spr
#define CE_GREEN_SMOKE 20 // grnsmk1.spr
#define CE_GREY_SMOKE 21 // grysmk1.spr
#define CE_RED_SMOKE 22 // redsmk1.spr
#define CE_SLOW_WHITE_SMOKE 23 // whtsmk1.spr
#define CE_REDSPARK 24 // rspark.spr
#define CE_GREENSPARK 25 // gspark.spr
#define CE_TELESMK1 26 // telesmk1.spr
#define CE_TELESMK2 27 // telesmk2.spr
#define CE_ICEHIT 28 // icehit.spr
#define CE_MEDUSA_HIT 29 // medhit.spr
#define CE_MEZZO_REFLECT 30 // mezzoref.spr
#define CE_FLOOR_EXPLOSION2 31 // flrexpl2.spr
#define CE_XBOW_EXPLOSION 32 // xbowexpl.spr
#define CE_NEW_EXPLOSION 33 // gen_expl.spr
#define CE_MAGIC_MISSILE_EXPLOSION 34 // mm_expld.spr
#define CE_GHOST 35 // ghost.spr
#define CE_BONE_EXPLOSION 36
#define CE_REDCLOUD 37
#define CE_TELEPORTERPUFFS 38
#define CE_TELEPORTERBODY 39
#define CE_BONESHARD 40
#define CE_BONESHRAPNEL 41
#define CE_FLAMESTREAM 42 //Flamethrower
#define CE_SNOW 43
#define CE_GRAVITYWELL 44
#define CE_BLDRN_EXPL 45
#define CE_ACID_MUZZFL 46
#define CE_ACID_HIT 47
#define CE_FIREWALL_SMALL 48
#define CE_FIREWALL_MEDIUM 49
#define CE_FIREWALL_LARGE 50
#define CE_LBALL_EXPL 51
#define CE_ACID_SPLAT 52
#define CE_ACID_EXPL 53
#define CE_FBOOM 54
#define CE_CHUNK 55
#define CE_BOMB 56
#define CE_BRN_BOUNCE 57
#define CE_LSHOCK 58
#define CE_FLAMEWALL 59
#define CE_FLAMEWALL2 60
#define CE_FLOOR_EXPLOSION3 61
#define CE_ONFIRE 62
#define MAX_EFFECT_ENTITIES 256
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static int NewEffectEntity(void);
static void FreeEffectEntity(int index);
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern cvar_t sv_ce_scale;
extern cvar_t sv_ce_max_size;
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
static entity_t EffectEntities[MAX_EFFECT_ENTITIES];
static qboolean EntityUsed[MAX_EFFECT_ENTITIES];
static int EffectEntityCount;
// CODE --------------------------------------------------------------------
//==========================================================================
//
// CL_InitTEnts
//
//==========================================================================
void CL_InitEffects(void)
{
}
void CL_ClearEffects(void)
{
memset(cl.Effects,0,sizeof(cl.Effects));
memset(EntityUsed,0,sizeof(EntityUsed));
EffectEntityCount = 0;
}
void SV_ClearEffects(void)
{
memset(sv.Effects,0,sizeof(sv.Effects));
}
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
void SV_SendEffect(sizebuf_t *sb, int index)
{
qboolean DoTest;
vec3_t TestO1,Diff;
float Size,TestDistance;
int i,count;
if (sb == &sv.reliable_datagram && sv_ce_scale.value > 0)
DoTest = true;
else
DoTest = false;
VectorCopy(vec3_origin, TestO1);
TestDistance = 0;
switch(sv.Effects[index].type)
{
case CE_RAIN:
case CE_SNOW:
DoTest = false;
break;
case CE_FOUNTAIN:
DoTest = false;
break;
case CE_QUAKE:
VectorCopy(sv.Effects[index].Quake.origin, TestO1);
TestDistance = 700;
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:
VectorCopy(sv.Effects[index].Smoke.origin, TestO1);
TestDistance = 250;
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_LG_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_ACID_HIT:
case CE_LBALL_EXPL:
case CE_FIREWALL_SMALL:
case CE_FIREWALL_MEDIUM:
case CE_FIREWALL_LARGE:
case CE_ACID_SPLAT:
case CE_ACID_EXPL:
case CE_FBOOM:
case CE_BRN_BOUNCE:
case CE_LSHOCK:
case CE_BOMB:
case CE_FLOOR_EXPLOSION3:
VectorCopy(sv.Effects[index].Smoke.origin, TestO1);
TestDistance = 250;
break;
case CE_WHITE_FLASH:
case CE_BLUE_FLASH:
case CE_SM_BLUE_FLASH:
case CE_RED_FLASH:
VectorCopy(sv.Effects[index].Smoke.origin, TestO1);
TestDistance = 250;
break;
case CE_RIDER_DEATH:
DoTest = false;
break;
case CE_GRAVITYWELL:
DoTest = false;
break;
case CE_TELEPORTERPUFFS:
VectorCopy(sv.Effects[index].Teleporter.origin, TestO1);
TestDistance = 350;
break;
case CE_TELEPORTERBODY:
VectorCopy(sv.Effects[index].Teleporter.origin, TestO1);
TestDistance = 350;
break;
case CE_BONESHARD:
case CE_BONESHRAPNEL:
VectorCopy(sv.Effects[index].Missile.origin, TestO1);
TestDistance = 600;
break;
case CE_CHUNK:
VectorCopy(sv.Effects[index].Chunk.origin, TestO1);
TestDistance = 600;
break;
default:
// Sys_Error ("SV_SendEffect: bad type");
PR_RunError ("SV_SendEffect: bad type");
break;
}
if (!DoTest)
count = 1;
else
{
count = svs.maxclients;
TestDistance = (float)TestDistance * sv_ce_scale.value;
TestDistance *= TestDistance;
}
for(i=0;i<count;i++)
{
if (DoTest)
{
if (svs.clients[i].active)
{
sb = &svs.clients[i].datagram;
VectorSubtract(svs.clients[i].edict->v.origin,TestO1,Diff);
Size = (Diff[0]*Diff[0]) + (Diff[1]*Diff[1]) + (Diff[2]*Diff[2]);
if (Size > TestDistance)
continue;
if (sv_ce_max_size.value > 0 && sb->cursize > sv_ce_max_size.value)
continue;
}
else continue;
}
MSG_WriteByte (sb, svc_start_effect);
MSG_WriteByte (sb, index);
MSG_WriteByte (sb, sv.Effects[index].type);
switch(sv.Effects[index].type)
{
case CE_RAIN:
MSG_WriteCoord(sb, sv.Effects[index].Rain.min_org[0]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.min_org[1]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.min_org[2]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.max_org[0]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.max_org[1]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.max_org[2]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.e_size[0]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.e_size[1]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.e_size[2]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.dir[0]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.dir[1]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.dir[2]);
MSG_WriteShort(sb, sv.Effects[index].Rain.color);
MSG_WriteShort(sb, sv.Effects[index].Rain.count);
MSG_WriteFloat(sb, sv.Effects[index].Rain.wait);
break;
case CE_SNOW:
MSG_WriteCoord(sb, sv.Effects[index].Rain.min_org[0]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.min_org[1]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.min_org[2]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.max_org[0]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.max_org[1]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.max_org[2]);
MSG_WriteByte(sb, sv.Effects[index].Rain.flags);
MSG_WriteCoord(sb, sv.Effects[index].Rain.dir[0]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.dir[1]);
MSG_WriteCoord(sb, sv.Effects[index].Rain.dir[2]);
MSG_WriteByte(sb, sv.Effects[index].Rain.count);
//MSG_WriteShort(sb, sv.Effects[index].Rain.veer);
break;
case CE_FOUNTAIN:
MSG_WriteCoord(sb, sv.Effects[index].Fountain.pos[0]);
MSG_WriteCoord(sb, sv.Effects[index].Fountain.pos[1]);
MSG_WriteCoord(sb, sv.Effects[index].Fountain.pos[2]);
MSG_WriteAngle(sb, sv.Effects[index].Fountain.angle[0]);
MSG_WriteAngle(sb, sv.Effects[index].Fountain.angle[1]);
MSG_WriteAngle(sb, sv.Effects[index].Fountain.angle[2]);
MSG_WriteCoord(sb, sv.Effects[index].Fountain.movedir[0]);
MSG_WriteCoord(sb, sv.Effects[index].Fountain.movedir[1]);
MSG_WriteCoord(sb, sv.Effects[index].Fountain.movedir[2]);
MSG_WriteShort(sb, sv.Effects[index].Fountain.color);
MSG_WriteByte(sb, sv.Effects[index].Fountain.cnt);
break;
case CE_QUAKE:
MSG_WriteCoord(sb, sv.Effects[index].Quake.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Quake.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Quake.origin[2]);
MSG_WriteFloat(sb, sv.Effects[index].Quake.radius);
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:
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[2]);
MSG_WriteFloat(sb, sv.Effects[index].Smoke.velocity[0]);
MSG_WriteFloat(sb, sv.Effects[index].Smoke.velocity[1]);
MSG_WriteFloat(sb, sv.Effects[index].Smoke.velocity[2]);
MSG_WriteFloat(sb, sv.Effects[index].Smoke.framelength);
MSG_WriteFloat(sb, sv.Effects[index].Smoke.frame);
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_LG_EXPLOSION:
case CE_FLOOR_EXPLOSION:
case CE_FLOOR_EXPLOSION3:
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_ACID_HIT:
case CE_ACID_SPLAT:
case CE_ACID_EXPL:
case CE_LBALL_EXPL:
case CE_FIREWALL_SMALL:
case CE_FIREWALL_MEDIUM:
case CE_FIREWALL_LARGE:
case CE_FBOOM:
case CE_BOMB:
case CE_BRN_BOUNCE:
case CE_LSHOCK:
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[2]);
break;
case CE_WHITE_FLASH:
case CE_BLUE_FLASH:
case CE_SM_BLUE_FLASH:
case CE_RED_FLASH:
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Smoke.origin[2]);
break;
case CE_RIDER_DEATH:
MSG_WriteCoord(sb, sv.Effects[index].RD.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].RD.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].RD.origin[2]);
break;
case CE_TELEPORTERPUFFS:
MSG_WriteCoord(sb, sv.Effects[index].Teleporter.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Teleporter.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Teleporter.origin[2]);
break;
case CE_TELEPORTERBODY:
MSG_WriteCoord(sb, sv.Effects[index].Teleporter.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Teleporter.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Teleporter.origin[2]);
MSG_WriteFloat(sb, sv.Effects[index].Teleporter.velocity[0][0]);
MSG_WriteFloat(sb, sv.Effects[index].Teleporter.velocity[0][1]);
MSG_WriteFloat(sb, sv.Effects[index].Teleporter.velocity[0][2]);
MSG_WriteFloat(sb, sv.Effects[index].Teleporter.skinnum);
break;
case CE_BONESHARD:
case CE_BONESHRAPNEL:
MSG_WriteCoord(sb, sv.Effects[index].Missile.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Missile.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Missile.origin[2]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.velocity[0]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.velocity[1]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.velocity[2]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.angle[0]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.angle[1]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.angle[2]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.avelocity[0]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.avelocity[1]);
MSG_WriteFloat(sb, sv.Effects[index].Missile.avelocity[2]);
break;
case CE_GRAVITYWELL:
MSG_WriteCoord(sb, sv.Effects[index].RD.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].RD.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].RD.origin[2]);
MSG_WriteShort(sb, sv.Effects[index].RD.color);
MSG_WriteFloat(sb, sv.Effects[index].RD.lifetime);
break;
case CE_CHUNK:
MSG_WriteCoord(sb, sv.Effects[index].Chunk.origin[0]);
MSG_WriteCoord(sb, sv.Effects[index].Chunk.origin[1]);
MSG_WriteCoord(sb, sv.Effects[index].Chunk.origin[2]);
MSG_WriteByte (sb, sv.Effects[index].Chunk.type);
MSG_WriteCoord(sb, sv.Effects[index].Chunk.srcVel[0]);
MSG_WriteCoord(sb, sv.Effects[index].Chunk.srcVel[1]);
MSG_WriteCoord(sb, sv.Effects[index].Chunk.srcVel[2]);
MSG_WriteByte (sb, sv.Effects[index].Chunk.numChunks);
//Con_Printf("Adding %d chunks on server...\n",sv.Effects[index].Chunk.numChunks);
break;
default:
// Sys_Error ("SV_SendEffect: bad type");
PR_RunError ("SV_SendEffect: bad type");
break;
}
}
}
void SV_UpdateEffects(sizebuf_t *sb)
{
int index;
for(index=0;index<MAX_EFFECTS;index++)
if (sv.Effects[index].type)
SV_SendEffect(sb,index);
}
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
void SV_ParseEffect(sizebuf_t *sb)
{
int index;
byte effect;
effect = G_FLOAT(OFS_PARM0);
for(index=0;index<MAX_EFFECTS;index++)
if (!sv.Effects[index].type ||
(sv.Effects[index].expire_time && sv.Effects[index].expire_time <= sv.time))
break;
if (index >= MAX_EFFECTS)
{
PR_RunError ("MAX_EFFECTS reached");
return;
}
// Con_Printf("Effect #%d\n",index);
memset(&sv.Effects[index],0,sizeof(struct EffectT));
sv.Effects[index].type = effect;
G_FLOAT(OFS_RETURN) = index;
switch(effect)
{
case CE_RAIN:
VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Rain.min_org);
VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Rain.max_org);
VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Rain.e_size);
VectorCopy(G_VECTOR(OFS_PARM4),sv.Effects[index].Rain.dir);
sv.Effects[index].Rain.color = G_FLOAT(OFS_PARM5);
sv.Effects[index].Rain.count = G_FLOAT(OFS_PARM6);
sv.Effects[index].Rain.wait = G_FLOAT(OFS_PARM7);
sv.Effects[index].Rain.next_time = 0;
break;
case CE_SNOW:
VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Rain.min_org);
VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Rain.max_org);
sv.Effects[index].Rain.flags = G_FLOAT(OFS_PARM3);
VectorCopy(G_VECTOR(OFS_PARM4),sv.Effects[index].Rain.dir);
sv.Effects[index].Rain.count = G_FLOAT(OFS_PARM5);
//sv.Effects[index].Rain.veer = G_FLOAT(OFS_PARM6);
//sv.Effects[index].Rain.wait = 0.10;
sv.Effects[index].Rain.next_time = 0;
break;
case CE_FOUNTAIN:
VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Fountain.pos);
VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Fountain.angle);
VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Fountain.movedir);
sv.Effects[index].Fountain.color = G_FLOAT(OFS_PARM4);
sv.Effects[index].Fountain.cnt = G_FLOAT(OFS_PARM5);
break;
case CE_QUAKE:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Quake.origin);
sv.Effects[index].Quake.radius = G_FLOAT(OFS_PARM2);
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:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin);
VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Smoke.velocity);
sv.Effects[index].Smoke.framelength = G_FLOAT(OFS_PARM3);
sv.Effects[index].Smoke.frame = 0;
sv.Effects[index].expire_time = sv.time + 1;
break;
case CE_ACID_MUZZFL:
case CE_FLAMESTREAM:
case CE_FLAMEWALL:
case CE_FLAMEWALL2:
case CE_ONFIRE:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin);
VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Smoke.velocity);
sv.Effects[index].Smoke.framelength = 0.05;
sv.Effects[index].Smoke.frame = G_FLOAT(OFS_PARM3);
sv.Effects[index].expire_time = sv.time + 1;
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_LG_EXPLOSION:
case CE_FLOOR_EXPLOSION:
case CE_FLOOR_EXPLOSION3:
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_ACID_HIT:
case CE_ACID_SPLAT:
case CE_ACID_EXPL:
case CE_LBALL_EXPL:
case CE_FIREWALL_SMALL:
case CE_FIREWALL_MEDIUM:
case CE_FIREWALL_LARGE:
case CE_FBOOM:
case CE_BOMB:
case CE_BRN_BOUNCE:
case CE_LSHOCK:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin);
sv.Effects[index].expire_time = sv.time + 1;
break;
case CE_WHITE_FLASH:
case CE_BLUE_FLASH:
case CE_SM_BLUE_FLASH:
case CE_RED_FLASH:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Flash.origin);
sv.Effects[index].expire_time = sv.time + 1;
break;
case CE_RIDER_DEATH:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].RD.origin);
break;
case CE_GRAVITYWELL:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].RD.origin);
sv.Effects[index].RD.color = G_FLOAT(OFS_PARM2);
sv.Effects[index].RD.lifetime = G_FLOAT(OFS_PARM3);
break;
case CE_TELEPORTERPUFFS:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Teleporter.origin);
sv.Effects[index].expire_time = sv.time + 1;
break;
case CE_TELEPORTERBODY:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Teleporter.origin);
VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Teleporter.velocity[0]);
sv.Effects[index].Teleporter.skinnum = G_FLOAT(OFS_PARM3);
sv.Effects[index].expire_time = sv.time + 1;
break;
case CE_BONESHARD:
case CE_BONESHRAPNEL:
VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Missile.origin);
VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.velocity);
VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Missile.angle);
VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.avelocity);
sv.Effects[index].expire_time = sv.time + 10;
break;
case CE_CHUNK:
VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Chunk.origin);
sv.Effects[index].Chunk.type = G_FLOAT(OFS_PARM2);
VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Chunk.srcVel);
sv.Effects[index].Chunk.numChunks = G_FLOAT(OFS_PARM4);
sv.Effects[index].expire_time = sv.time + 3;
break;
default:
// Sys_Error ("SV_ParseEffect: bad type");
PR_RunError ("SV_SendEffect: bad type");
}
SV_SendEffect(sb,index);
}
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
void SV_SaveEffects(FILE *FH)
{
int index,count;
for(index=count=0;index<MAX_EFFECTS;index++)
if (sv.Effects[index].type)
count++;
fprintf(FH,"Effects: %d\n",count);
for(index=count=0;index<MAX_EFFECTS;index++)
if (sv.Effects[index].type)
{
fprintf(FH,"Effect: %d %d %f: ",index,sv.Effects[index].type,sv.Effects[index].expire_time);
switch(sv.Effects[index].type)
{
case CE_RAIN:
fprintf(FH, "%f ", sv.Effects[index].Rain.min_org[0]);
fprintf(FH, "%f ", sv.Effects[index].Rain.min_org[1]);
fprintf(FH, "%f ", sv.Effects[index].Rain.min_org[2]);
fprintf(FH, "%f ", sv.Effects[index].Rain.max_org[0]);
fprintf(FH, "%f ", sv.Effects[index].Rain.max_org[1]);
fprintf(FH, "%f ", sv.Effects[index].Rain.max_org[2]);
fprintf(FH, "%f ", sv.Effects[index].Rain.e_size[0]);
fprintf(FH, "%f ", sv.Effects[index].Rain.e_size[1]);
fprintf(FH, "%f ", sv.Effects[index].Rain.e_size[2]);
fprintf(FH, "%f ", sv.Effects[index].Rain.dir[0]);
fprintf(FH, "%f ", sv.Effects[index].Rain.dir[1]);
fprintf(FH, "%f ", sv.Effects[index].Rain.dir[2]);
fprintf(FH, "%d ", sv.Effects[index].Rain.color);
fprintf(FH, "%d ", sv.Effects[index].Rain.count);
fprintf(FH, "%f\n", sv.Effects[index].Rain.wait);
break;
case CE_SNOW:
fprintf(FH, "%f ", sv.Effects[index].Rain.min_org[0]);
fprintf(FH, "%f ", sv.Effects[index].Rain.min_org[1]);
fprintf(FH, "%f ", sv.Effects[index].Rain.min_org[2]);
fprintf(FH, "%f ", sv.Effects[index].Rain.max_org[0]);
fprintf(FH, "%f ", sv.Effects[index].Rain.max_org[1]);
fprintf(FH, "%f ", sv.Effects[index].Rain.max_org[2]);
fprintf(FH, "%d ", sv.Effects[index].Rain.flags);
fprintf(FH, "%f ", sv.Effects[index].Rain.dir[0]);
fprintf(FH, "%f ", sv.Effects[index].Rain.dir[1]);
fprintf(FH, "%f ", sv.Effects[index].Rain.dir[2]);
fprintf(FH, "%d ", sv.Effects[index].Rain.count);
//fprintf(FH, "%d ", sv.Effects[index].Rain.veer);
break;
case CE_FOUNTAIN:
fprintf(FH, "%f ", sv.Effects[index].Fountain.pos[0]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.pos[1]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.pos[2]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.angle[0]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.angle[1]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.angle[2]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.movedir[0]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.movedir[1]);
fprintf(FH, "%f ", sv.Effects[index].Fountain.movedir[2]);
fprintf(FH, "%d ", sv.Effects[index].Fountain.color);
fprintf(FH, "%d\n", sv.Effects[index].Fountain.cnt);
break;
case CE_QUAKE:
fprintf(FH, "%f ", sv.Effects[index].Quake.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Quake.origin[1]);
fprintf(FH, "%f ", sv.Effects[index].Quake.origin[2]);
fprintf(FH, "%f\n", sv.Effects[index].Quake.radius);
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:
fprintf(FH, "%f ", sv.Effects[index].Smoke.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Smoke.origin[1]);
fprintf(FH, "%f ", sv.Effects[index].Smoke.origin[2]);
fprintf(FH, "%f ", sv.Effects[index].Smoke.velocity[0]);
fprintf(FH, "%f ", sv.Effects[index].Smoke.velocity[1]);
fprintf(FH, "%f ", sv.Effects[index].Smoke.velocity[2]);
fprintf(FH, "%f ", sv.Effects[index].Smoke.framelength);
fprintf(FH, "%f\n", sv.Effects[index].Smoke.frame);
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_LG_EXPLOSION:
case CE_FLOOR_EXPLOSION:
case CE_FLOOR_EXPLOSION3:
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_FIREWALL_SMALL:
case CE_FIREWALL_MEDIUM:
case CE_FIREWALL_LARGE:
case CE_FBOOM:
case CE_BOMB:
fprintf(FH, "%f ", sv.Effects[index].Smoke.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Smoke.origin[1]);
fprintf(FH, "%f\n", sv.Effects[index].Smoke.origin[2]);
break;
case CE_WHITE_FLASH:
case CE_BLUE_FLASH:
case CE_SM_BLUE_FLASH:
case CE_RED_FLASH:
fprintf(FH, "%f ", sv.Effects[index].Flash.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Flash.origin[1]);
fprintf(FH, "%f\n", sv.Effects[index].Flash.origin[2]);
break;
case CE_RIDER_DEATH:
fprintf(FH, "%f ", sv.Effects[index].RD.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].RD.origin[1]);
fprintf(FH, "%f\n", sv.Effects[index].RD.origin[2]);
break;
case CE_GRAVITYWELL:
fprintf(FH, "%f ", sv.Effects[index].RD.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].RD.origin[1]);
fprintf(FH, "%f", sv.Effects[index].RD.origin[2]);
fprintf(FH, "%d", sv.Effects[index].RD.color);
fprintf(FH, "%f\n", sv.Effects[index].RD.lifetime);
break;
case CE_TELEPORTERPUFFS:
fprintf(FH, "%f ", sv.Effects[index].Teleporter.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Teleporter.origin[1]);
fprintf(FH, "%f\n", sv.Effects[index].Teleporter.origin[2]);
break;
case CE_TELEPORTERBODY:
fprintf(FH, "%f ", sv.Effects[index].Teleporter.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Teleporter.origin[1]);
fprintf(FH, "%f\n", sv.Effects[index].Teleporter.origin[2]);
break;
case CE_BONESHARD:
case CE_BONESHRAPNEL:
fprintf(FH, "%f ", sv.Effects[index].Missile.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Missile.origin[1]);
fprintf(FH, "%f ", sv.Effects[index].Missile.origin[2]);
fprintf(FH, "%f ", sv.Effects[index].Missile.velocity[0]);
fprintf(FH, "%f ", sv.Effects[index].Missile.velocity[1]);
fprintf(FH, "%f ", sv.Effects[index].Missile.velocity[2]);
fprintf(FH, "%f ", sv.Effects[index].Missile.angle[0]);
fprintf(FH, "%f ", sv.Effects[index].Missile.angle[1]);
fprintf(FH, "%f ", sv.Effects[index].Missile.angle[2]);
fprintf(FH, "%f ", sv.Effects[index].Missile.avelocity[0]);
fprintf(FH, "%f ", sv.Effects[index].Missile.avelocity[1]);
fprintf(FH, "%f ", sv.Effects[index].Missile.avelocity[2]);
break;
case CE_CHUNK:
fprintf(FH, "%f ", sv.Effects[index].Chunk.origin[0]);
fprintf(FH, "%f ", sv.Effects[index].Chunk.origin[1]);
fprintf(FH, "%f ", sv.Effects[index].Chunk.origin[2]);
fprintf(FH, "%d ", sv.Effects[index].Chunk.type);
fprintf(FH, "%f ", sv.Effects[index].Chunk.srcVel[0]);
fprintf(FH, "%f ", sv.Effects[index].Chunk.srcVel[1]);
fprintf(FH, "%f ", sv.Effects[index].Chunk.srcVel[2]);
fprintf(FH, "%d ", sv.Effects[index].Chunk.numChunks);
break;
default:
PR_RunError ("SV_SaveEffect: bad type");
break;
}
}
}
// All changes need to be in SV_SendEffect(), SV_ParseEffect(),
// SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect()
void SV_LoadEffects(FILE *FH)
{
int index,Total,count;
// Since the map is freshly loaded, clear out any effects as a result of
// the loading
SV_ClearEffects();
fscanf(FH,"Effects: %d\n",&Total);
for(count=0;count<Total;count++)
{
fscanf(FH,"Effect: %d ",&index);
fscanf(FH,"%d %f: ",&sv.Effects[index].type,&sv.Effects[index].expire_time);
switch(sv.Effects[index].type)
{
case CE_RAIN:
fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[0]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[1]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[2]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[0]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[1]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[2]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.e_size[0]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.e_size[1]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.e_size[2]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[0]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[1]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[2]);
fscanf(FH, "%d ", &sv.Effects[index].Rain.color);
fscanf(FH, "%d ", &sv.Effects[index].Rain.count);
fscanf(FH, "%f\n", &sv.Effects[index].Rain.wait);
break;
case CE_SNOW:
fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[0]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[1]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[2]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[0]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[1]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[2]);
fscanf(FH, "%d ", &sv.Effects[index].Rain.flags);
fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[0]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[1]);
fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[2]);
fscanf(FH, "%d ", &sv.Effects[index].Rain.count);
//fscanf(FH, "%d ", &sv.Effects[index].Rain.veer);
break;
case CE_FOUNTAIN:
fscanf(FH, "%f ", &sv.Effects[index].Fountain.pos[0]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.pos[1]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.pos[2]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.angle[0]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.angle[1]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.angle[2]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.movedir[0]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.movedir[1]);
fscanf(FH, "%f ", &sv.Effects[index].Fountain.movedir[2]);
fscanf(FH, "%d ", &sv.Effects[index].Fountain.color);
fscanf(FH, "%d\n", &sv.Effects[index].Fountain.cnt);
break;
case CE_QUAKE:
fscanf(FH, "%f ", &sv.Effects[index].Quake.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Quake.origin[1]);
fscanf(FH, "%f ", &sv.Effects[index].Quake.origin[2]);
fscanf(FH, "%f\n", &sv.Effects[index].Quake.radius);
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:
fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[1]);
fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[2]);
fscanf(FH, "%f ", &sv.Effects[index].Smoke.velocity[0]);
fscanf(FH, "%f ", &sv.Effects[index].Smoke.velocity[1]);
fscanf(FH, "%f ", &sv.Effects[index].Smoke.velocity[2]);
fscanf(FH, "%f ", &sv.Effects[index].Smoke.framelength);
fscanf(FH, "%f\n", &sv.Effects[index].Smoke.frame);
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_LG_EXPLOSION:
case CE_FLOOR_EXPLOSION:
case CE_FLOOR_EXPLOSION3:
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_FIREWALL_SMALL:
case CE_FIREWALL_MEDIUM:
case CE_FIREWALL_LARGE:
case CE_BOMB:
fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[1]);
fscanf(FH, "%f\n", &sv.Effects[index].Smoke.origin[2]);
break;
case CE_WHITE_FLASH:
case CE_BLUE_FLASH:
case CE_SM_BLUE_FLASH:
case CE_RED_FLASH:
fscanf(FH, "%f ", &sv.Effects[index].Flash.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Flash.origin[1]);
fscanf(FH, "%f\n", &sv.Effects[index].Flash.origin[2]);
break;
case CE_RIDER_DEATH:
fscanf(FH, "%f ", &sv.Effects[index].RD.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].RD.origin[1]);
fscanf(FH, "%f\n", &sv.Effects[index].RD.origin[2]);
break;
case CE_GRAVITYWELL:
fscanf(FH, "%f ", &sv.Effects[index].RD.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].RD.origin[1]);
fscanf(FH, "%f", &sv.Effects[index].RD.origin[2]);
fscanf(FH, "%d", &sv.Effects[index].RD.color);
fscanf(FH, "%f\n", &sv.Effects[index].RD.lifetime);
break;
case CE_TELEPORTERPUFFS:
fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[1]);
fscanf(FH, "%f\n", &sv.Effects[index].Teleporter.origin[2]);
break;
case CE_TELEPORTERBODY:
fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[1]);
fscanf(FH, "%f\n", &sv.Effects[index].Teleporter.origin[2]);
break;
case CE_BONESHARD:
case CE_BONESHRAPNEL:
fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[1]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[2]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[0]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[1]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[2]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[0]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[1]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[2]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.avelocity[0]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.avelocity[1]);
fscanf(FH, "%f ", &sv.Effects[index].Missile.avelocity[2]);
break;
case CE_CHUNK:
fscanf(FH, "%f ", &sv.Effects[index].Chunk.origin[0]);
fscanf(FH, "%f ", &sv.Effects[index].Chunk.origin[1]);
fscanf(FH, "%f ", &sv.Effects[index].Chunk.origin[2]);
fscanf(FH, "%d ", &sv.Effects[index].Chunk.type);
fscanf(FH, "%f ", &sv.Effects[index].Chunk.srcVel[0]);
fscanf(FH, "%f ", &sv.Effects[index].Chunk.srcVel[1]);
fscanf(FH, "%f ", &sv.Effects[index].Chunk.srcVel[2]);
fscanf(FH, "%d ", &sv.Effects[index].Chunk.numChunks);
break;
default:
PR_RunError ("SV_SaveEffect: bad type");
break;
}
}
}
void CL_FreeEffect(int index)
{
int i;
switch(cl.Effects[index].type)
{
case CE_RAIN:
break;
case CE_SNOW:
break;
case CE_FOUNTAIN:
break;
case CE_QUAKE:
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:
FreeEffectEntity(cl.Effects[index].Smoke.entity_index);
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_LG_EXPLOSION:
case CE_FLOOR_EXPLOSION:
case CE_FLOOR_EXPLOSION3:
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_RED_FLASH:
FreeEffectEntity(cl.Effects[index].Flash.entity_index);
break;
case CE_RIDER_DEATH:
break;
case CE_GRAVITYWELL:
break;
case CE_TELEPORTERPUFFS:
for (i=0;i<8;++i)
FreeEffectEntity(cl.Effects[index].Teleporter.entity_index[i]);
break;
case CE_TELEPORTERBODY:
FreeEffectEntity(cl.Effects[index].Teleporter.entity_index[0]);
break;
case CE_BONESHARD:
case CE_BONESHRAPNEL:
FreeEffectEntity(cl.Effects[index].Missile.entity_index);
break;
case CE_CHUNK:
//Con_Printf("Freeing a chunk here\n");
for (i=0;i < cl.Effects[index].Chunk.numChunks;i++)
{
if(cl.Effects[index].Chunk.entity_index[i] != -1)
{
FreeEffectEntity(cl.Effects[index].Chunk.entity_index[i]);
}
}
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;
float final;
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_SNOW:
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.flags = MSG_ReadByte();
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.count = MSG_ReadByte();
//cl.Effects[index].Rain.veer = MSG_ReadShort();
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:
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 ();
cl.Effects[index].Smoke.frame = 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;
}
if (cl.Effects[index].type != CE_REDCLOUD&&cl.Effects[index].type != CE_ACID_MUZZFL&&cl.Effects[index].type != CE_FLAMEWALL)
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;
}
}
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_LG_EXPLOSION:
case CE_FLOOR_EXPLOSION:
case CE_FLOOR_EXPLOSION3:
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_LG_EXPLOSION)
ent->model = Mod_ForName("models/bg_expld.spr", true);
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_FLOOR_EXPLOSION3)
ent->model = Mod_ForName("models/biggy.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);
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_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);
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_GRAVITYWELL:
cl.Effects[index].RD.origin[0] = MSG_ReadCoord ();
cl.Effects[index].RD.origin[1] = MSG_ReadCoord ();
cl.Effects[index].RD.origin[2] = MSG_ReadCoord ();
cl.Effects[index].RD.color = MSG_ReadShort ();
cl.Effects[index].RD.lifetime = MSG_ReadFloat ();
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_BONESHARD:
case CE_BONESHRAPNEL:
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);
if (cl.Effects[index].type == CE_BONESHARD)
ent->model = Mod_ForName("models/boneshot.mdl", true);
else if (cl.Effects[index].type == CE_BONESHRAPNEL)
ent->model = Mod_ForName("models/boneshrd.mdl", true);
}
else
ImmediateFree = true;
break;
case CE_CHUNK:
cl.Effects[index].Chunk.origin[0] = MSG_ReadCoord ();
cl.Effects[index].Chunk.origin[1] = MSG_ReadCoord ();
cl.Effects[index].Chunk.origin[2] = MSG_ReadCoord ();
cl.Effects[index].Chunk.type = MSG_ReadByte ();
cl.Effects[index].Chunk.srcVel[0] = MSG_ReadCoord ();
cl.Effects[index].Chunk.srcVel[1] = MSG_ReadCoord ();
cl.Effects[index].Chunk.srcVel[2] = MSG_ReadCoord ();
cl.Effects[index].Chunk.numChunks = MSG_ReadByte ();
cl.Effects[index].Chunk.time_amount = 4.0;
cl.Effects[index].Chunk.aveScale = 30 + 100 * (cl.Effects[index].Chunk.numChunks / 40.0);
if(cl.Effects[index].Chunk.numChunks > 16)cl.Effects[index].Chunk.numChunks = 16;
for (i=0;i < cl.Effects[index].Chunk.numChunks;i++)
{
if ((cl.Effects[index].Chunk.entity_index[i] = NewEffectEntity()) != -1)
{
ent = &EffectEntities[cl.Effects[index].Chunk.entity_index[i]];
VectorCopy(cl.Effects[index].Chunk.origin, ent->origin);
VectorCopy(cl.Effects[index].Chunk.srcVel, cl.Effects[index].Chunk.velocity[i]);
VectorScale(cl.Effects[index].Chunk.velocity[i], .80 + ((rand()%4)/10.0), cl.Effects[index].Chunk.velocity[i]);
// temp modify them...
cl.Effects[index].Chunk.velocity[i][0] += (rand()%140)-70;
cl.Effects[index].Chunk.velocity[i][1] += (rand()%140)-70;
cl.Effects[index].Chunk.velocity[i][2] += (rand()%140)-70;
// are these in degrees or radians?
ent->angles[0] = rand()%360;
ent->angles[1] = rand()%360;
ent->angles[2] = rand()%360;
ent->scale = cl.Effects[index].Chunk.aveScale + rand()%40;
// make this overcomplicated
final = (rand()%100)*.01;
if ((cl.Effects[index].Chunk.type==THINGTYPE_GLASS) || (cl.Effects[index].Chunk.type==THINGTYPE_REDGLASS) ||
(cl.Effects[index].Chunk.type==THINGTYPE_CLEARGLASS) || (cl.Effects[index].Chunk.type==THINGTYPE_WEBS))
{
if (final<0.20)
ent->model = Mod_ForName ("models/shard1.mdl", true);
else if (final<0.40)
ent->model = Mod_ForName ("models/shard2.mdl", true);
else if (final<0.60)
ent->model = Mod_ForName ("models/shard3.mdl", true);
else if (final<0.80)
ent->model = Mod_ForName ("models/shard4.mdl", true);
else
ent->model = Mod_ForName ("models/shard5.mdl", true);
if (cl.Effects[index].Chunk.type==THINGTYPE_CLEARGLASS)
{
ent->skinnum=1;
ent->drawflags |= DRF_TRANSLUCENT;
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_REDGLASS)
{
ent->skinnum=2;
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_WEBS)
{
ent->skinnum=3;
ent->drawflags |= DRF_TRANSLUCENT;
}
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_WOOD)
{
if (final < 0.25)
ent->model = Mod_ForName ("models/splnter1.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/splnter2.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/splnter3.mdl", true);
else
ent->model = Mod_ForName ("models/splnter4.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_METAL)
{
if (final < 0.25)
ent->model = Mod_ForName ("models/metlchk1.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/metlchk2.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/metlchk3.mdl", true);
else
ent->model = Mod_ForName ("models/metlchk4.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_FLESH)
{
if (final < 0.33)
ent->model = Mod_ForName ("models/flesh1.mdl", true);
else if (final < 0.66)
ent->model = Mod_ForName ("models/flesh2.mdl", true);
else
ent->model = Mod_ForName ("models/flesh3.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_BROWNSTONE)
{
if (final < 0.25)
ent->model = Mod_ForName ("models/schunk1.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/schunk2.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/schunk3.mdl", true);
else
ent->model = Mod_ForName ("models/schunk4.mdl", true);
ent->skinnum = 1;
}
else if ((cl.Effects[index].Chunk.type==THINGTYPE_CLAY) || (cl.Effects[index].Chunk.type==THINGTYPE_BONE))
{
if (final < 0.25)
ent->model = Mod_ForName ("models/clshard1.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/clshard2.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/clshard3.mdl", true);
else
ent->model = Mod_ForName ("models/clshard4.mdl", true);
if (cl.Effects[index].Chunk.type==THINGTYPE_BONE)
{
ent->skinnum=1;//bone skin is second
}
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_LEAVES)
{
if (final < 0.33)
ent->model = Mod_ForName ("models/leafchk1.mdl", true);
else if (final < 0.66)
ent->model = Mod_ForName ("models/leafchk2.mdl", true);
else
ent->model = Mod_ForName ("models/leafchk3.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_HAY)
{
if (final < 0.33)
ent->model = Mod_ForName ("models/hay1.mdl", true);
else if (final < 0.66)
ent->model = Mod_ForName ("models/hay2.mdl", true);
else
ent->model = Mod_ForName ("models/hay3.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_CLOTH)
{
if (final < 0.33)
ent->model = Mod_ForName ("models/clthchk1.mdl", true);
else if (final < 0.66)
ent->model = Mod_ForName ("models/clthchk2.mdl", true);
else
ent->model = Mod_ForName ("models/clthchk3.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_WOOD_LEAF)
{
if (final < 0.14)
ent->model = Mod_ForName ("models/splnter1.mdl", true);
else if (final < 0.28)
ent->model = Mod_ForName ("models/leafchk1.mdl", true);
else if (final < 0.42)
ent->model = Mod_ForName ("models/splnter2.mdl", true);
else if (final < 0.56)
ent->model = Mod_ForName ("models/leafchk2.mdl", true);
else if (final < 0.70)
ent->model = Mod_ForName ("models/splnter3.mdl", true);
else if (final < 0.84)
ent->model = Mod_ForName ("models/leafchk3.mdl", true);
else
ent->model = Mod_ForName ("models/splnter4.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_WOOD_METAL)
{
if (final < 0.125)
ent->model = Mod_ForName ("models/splnter1.mdl", true);
else if (final < 0.25)
ent->model = Mod_ForName ("models/metlchk1.mdl", true);
else if (final < 0.375)
ent->model = Mod_ForName ("models/splnter2.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/metlchk2.mdl", true);
else if (final < 0.625)
ent->model = Mod_ForName ("models/splnter3.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/metlchk3.mdl", true);
else if (final < 0.875)
ent->model = Mod_ForName ("models/splnter4.mdl", true);
else
ent->model = Mod_ForName ("models/metlchk4.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_WOOD_STONE)
{
if (final < 0.125)
ent->model = Mod_ForName ("models/splnter1.mdl", true);
else if (final < 0.25)
ent->model = Mod_ForName ("models/schunk1.mdl", true);
else if (final < 0.375)
ent->model = Mod_ForName ("models/splnter2.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/schunk2.mdl", true);
else if (final < 0.625)
ent->model = Mod_ForName ("models/splnter3.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/schunk3.mdl", true);
else if (final < 0.875)
ent->model = Mod_ForName ("models/splnter4.mdl", true);
else
ent->model = Mod_ForName ("models/schunk4.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_METAL_STONE)
{
if (final < 0.125)
ent->model = Mod_ForName ("models/metlchk1.mdl", true);
else if (final < 0.25)
ent->model = Mod_ForName ("models/schunk1.mdl", true);
else if (final < 0.375)
ent->model = Mod_ForName ("models/metlchk2.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/schunk2.mdl", true);
else if (final < 0.625)
ent->model = Mod_ForName ("models/metlchk3.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/schunk3.mdl", true);
else if (final < 0.875)
ent->model = Mod_ForName ("models/metlchk4.mdl", true);
else
ent->model = Mod_ForName ("models/schunk4.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_METAL_CLOTH)
{
if (final < 0.14)
ent->model = Mod_ForName ("models/metlchk1.mdl", true);
else if (final < 0.28)
ent->model = Mod_ForName ("models/clthchk1.mdl", true);
else if (final < 0.42)
ent->model = Mod_ForName ("models/metlchk2.mdl", true);
else if (final < 0.56)
ent->model = Mod_ForName ("models/clthchk2.mdl", true);
else if (final < 0.70)
ent->model = Mod_ForName ("models/metlchk3.mdl", true);
else if (final < 0.84)
ent->model = Mod_ForName ("models/clthchk3.mdl", true);
else
ent->model = Mod_ForName ("models/metlchk4.mdl", true);
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_ICE)
{
ent->model = Mod_ForName("models/shard.mdl", true);
ent->skinnum=0;
ent->frame = rand()%2;
ent->drawflags |= DRF_TRANSLUCENT|MLS_ABSLIGHT;
ent->abslight = 0.5;
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_METEOR)
{
ent->model = Mod_ForName("models/tempmetr.mdl", true);
ent->skinnum = 0;
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_ACID)
{ // no spinning if possible...
ent->model = Mod_ForName("models/sucwp2p.mdl", true);
ent->skinnum = 0;
}
else if (cl.Effects[index].Chunk.type==THINGTYPE_GREENFLESH)
{ // spider guts
if (final < 0.33)
ent->model = Mod_ForName ("models/sflesh1.mdl", true);
else if (final < 0.66)
ent->model = Mod_ForName ("models/sflesh2.mdl", true);
else
ent->model = Mod_ForName ("models/sflesh3.mdl", true);
ent->skinnum = 0;
}
else// if (cl.Effects[index].Chunk.type==THINGTYPE_GREYSTONE)
{
if (final < 0.25)
ent->model = Mod_ForName ("models/schunk1.mdl", true);
else if (final < 0.50)
ent->model = Mod_ForName ("models/schunk2.mdl", true);
else if (final < 0.75)
ent->model = Mod_ForName ("models/schunk3.mdl", true);
else
ent->model = Mod_ForName ("models/schunk4.mdl", true);
ent->skinnum = 0;
}
}
}
for(i=0; i < 3; i++)
{
cl.Effects[index].Chunk.avel[i][0] = rand()%850 - 425;
cl.Effects[index].Chunk.avel[i][1] = rand()%850 - 425;
cl.Effects[index].Chunk.avel[i][2] = rand()%850 - 425;
}
break;
default:
Sys_Error ("CL_ParseEffect: bad type");
}
if (ImmediateFree)
{
cl.Effects[index].type = CE_NONE;
}
}
void CL_EndEffect(void)
{
int index;
index = MSG_ReadByte();
CL_FreeEffect(index);
}
void CL_LinkEntity(entity_t *ent)
{
if (cl_numvisedicts < MAX_VISEDICTS)
{
cl_visedicts[cl_numvisedicts++] = ent;
}
}
void R_RunQuakeEffect (vec3_t org, float distance);
void RiderParticle(int count, vec3_t origin);
void GravityWellParticle(int count, vec3_t origin, int color);
void CL_UpdateEffects(void)
{
int index,cur_frame;
vec3_t mymin,mymax;
float frametime;
edict_t test;
trace_t trace;
vec3_t org,org2,alldir;
int x_dir,y_dir;
entity_t *ent;
float distance,smoketime;
int i;
vec3_t snow_org;
if (cls.state == ca_disconnected)
return;
frametime = cl.time - cl.oldtime;
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_SNOW:
VectorCopy(cl.Effects[index].Rain.min_org,org);
VectorCopy(cl.Effects[index].Rain.max_org,org2);
VectorCopy(cl.Effects[index].Rain.dir,alldir);
VectorAdd(org, org2, snow_org);
snow_org[0] *= 0.5;
snow_org[1] *= 0.5;
snow_org[2] *= 0.5;
snow_org[2] = r_origin[2];
VectorSubtract(snow_org, r_origin, snow_org);
distance = VectorNormalize(snow_org);
cl.Effects[index].Rain.next_time += frametime;
//jfm: fixme, check distance to player first
if (cl.Effects[index].Rain.next_time >= 0.10 && distance < 1024)
{
R_SnowEffect(org,org2,cl.Effects[index].Rain.flags,alldir,
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_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];
while(cl.Effects[index].Smoke.time_amount >= smoketime)
{
ent->frame++;
cl.Effects[index].Smoke.time_amount -= smoketime;
}
if (ent->frame >= ent->model->numframes)
{
CL_FreeEffect(index);
}
else
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_LG_EXPLOSION:
case CE_FLOOR_EXPLOSION:
case CE_FLOOR_EXPLOSION3:
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;
case CE_LSHOCK:
ent = &EffectEntities[cl.Effects[index].Smoke.entity_index];
if(ent->skinnum==0)
ent->skinnum=1;
else if(ent->skinnum==1)
ent->skinnum=0;
ent->scale-=10;
if (ent->scale<=10)
{
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_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,cl.Effects[index].RD.origin);
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_GRAVITYWELL:
cl.Effects[index].RD.time_amount += frametime*2;
if (cl.Effects[index].RD.time_amount >= 1)
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.lifetime < cl.time)
{
CL_FreeEffect(index);
}
else
GravityWellParticle(rand()%8,org, cl.Effects[index].RD.color);
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_BONESHARD:
case CE_BONESHRAPNEL:
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];
CL_LinkEntity(ent);
break;
case CE_CHUNK:
cl.Effects[index].Chunk.time_amount -= frametime;
if(cl.Effects[index].Chunk.time_amount < 0)
{
CL_FreeEffect(index);
}
else
{
for (i=0;i < cl.Effects[index].Chunk.numChunks;i++)
{
vec3_t oldorg;
mleaf_t *l;
int moving = 1;
ent = &EffectEntities[cl.Effects[index].Chunk.entity_index[i]];
VectorCopy(ent->origin, oldorg);
ent->origin[0] += frametime * cl.Effects[index].Chunk.velocity[i][0];
ent->origin[1] += frametime * cl.Effects[index].Chunk.velocity[i][1];
ent->origin[2] += frametime * cl.Effects[index].Chunk.velocity[i][2];
l = Mod_PointInLeaf (ent->origin, cl.worldmodel);
if(l->contents!=CONTENTS_EMPTY) //||in_solid==true
{ // bouncing prolly won't work...
VectorCopy(oldorg, ent->origin);
cl.Effects[index].Chunk.velocity[i][0] = 0;
cl.Effects[index].Chunk.velocity[i][1] = 0;
cl.Effects[index].Chunk.velocity[i][2] = 0;
moving = 0;
}
else
{
ent->angles[0] += frametime * cl.Effects[index].Chunk.avel[i%3][0];
ent->angles[1] += frametime * cl.Effects[index].Chunk.avel[i%3][1];
ent->angles[2] += frametime * cl.Effects[index].Chunk.avel[i%3][2];
}
if(cl.Effects[index].Chunk.time_amount < frametime * 3)
{ // chunk leaves in 3 frames
ent->scale *= .7;
}
CL_LinkEntity(ent);
cl.Effects[index].Chunk.velocity[i][2] -= frametime * 500; // apply gravity
switch(cl.Effects[index].Chunk.type)
{
case THINGTYPE_GREYSTONE:
break;
case THINGTYPE_WOOD:
break;
case THINGTYPE_METAL:
break;
case THINGTYPE_FLESH:
if(moving)R_RocketTrail (oldorg, ent->origin, 17);
break;
case THINGTYPE_FIRE:
break;
case THINGTYPE_CLAY:
case THINGTYPE_BONE:
break;
case THINGTYPE_LEAVES:
break;
case THINGTYPE_HAY:
break;
case THINGTYPE_BROWNSTONE:
break;
case THINGTYPE_CLOTH:
break;
case THINGTYPE_WOOD_LEAF:
break;
case THINGTYPE_WOOD_METAL:
break;
case THINGTYPE_WOOD_STONE:
break;
case THINGTYPE_METAL_STONE:
break;
case THINGTYPE_METAL_CLOTH:
break;
case THINGTYPE_WEBS:
break;
case THINGTYPE_GLASS:
break;
case THINGTYPE_ICE:
if(moving)R_RocketTrail (oldorg, ent->origin, rt_ice);
break;
case THINGTYPE_CLEARGLASS:
break;
case THINGTYPE_REDGLASS:
break;
case THINGTYPE_ACID:
if(moving)R_RocketTrail (oldorg, ent->origin, rt_acidball);
break;
case THINGTYPE_METEOR:
R_RocketTrail (oldorg, ent->origin, 1);
break;
case THINGTYPE_GREENFLESH:
if(moving)R_RocketTrail (oldorg, ent->origin, rt_acidball);
break;
}
}
}
break;
}
}
}
//==========================================================================
//
// 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)
{
EntityUsed[index] = false;
EffectEntityCount--;
}
/*
* $Log: /H2 Mission Pack/cl_effect.c $
*
* 41 3/20/98 12:55p Jmonroe
* made sbar arti safe, made linkedict safe, removed pent hull for NON MP
* maps.
*
* 40 3/19/98 12:23a Mgummelt
*
* 39 3/13/98 4:00p Jmonroe
*
* 38 3/13/98 3:35p Jweier
*
* 37 3/05/98 7:54p Jmonroe
* fixed startRain, optimized particle struct
*
* 36 3/02/98 12:41p Mgummelt
*
* 35 2/23/98 4:48p Jmonroe
* fixed snow to only spew at 10 fps instead of infinity
*
* 34 2/23/98 2:00p Jweier
*
* 33 2/20/98 1:00p Jmonroe
* added thingtype_bone
*
* 32 2/12/98 4:35p Jweier
*
* 31 2/12/98 10:38a Jweier
*
* 30 2/10/98 10:51a Jweier
*
* 29 2/08/98 6:47p Jweier
*
* 28 2/07/98 2:11p Mgummelt
*
* 27 2/07/98 1:58p Mgummelt
*
* 26 2/07/98 1:28p Jweier
*
* 25 2/06/98 5:06p Nalbury
* Added more chunk stuff.
*
* 24 2/06/98 4:18p Mgummelt
*
* 23 2/06/98 3:47p Mgummelt
*
* 22 2/06/98 3:38p Nalbury
* Added particles
*
* 21 2/06/98 12:15p Jweier
*
* 20 2/06/98 11:30a Mgummelt
*
* 19 2/06/98 5:03a Nalbury
* Put in preliminary chunks for network games...
*
* 18 2/05/98 11:25p Jweier
*
* 17 2/05/98 6:43p Mgummelt
*
* 16 2/05/98 3:35p Jweier
*
* 15 2/05/98 11:08a Jweier
*
* 14 2/04/98 6:31p Mgummelt
*
* 13 2/04/98 4:58p Mgummelt
* spawnflags on monsters cleared out
*
* 12 2/04/98 1:45p Jweier
*
* 11 2/04/98 1:36p Mgummelt
*
* 10 2/03/98 4:17p Mgummelt
*
* 9 2/03/98 1:44p Mgummelt
*
* 8 1/26/98 4:38p Plipo
* added pt_gravwell client effect
*
* 7 1/20/98 11:09a Jmonroe
* fix for bad model shit because of the remaining particles in restarts
*
* 6 1/18/98 8:05p Jmonroe
* all of rick's patch code is in now
*
* 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
*/