123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746 |
- /*
- Copyright (C) 1997-2001 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- // cl_tent.c -- client side temporary entities
- #include "client.h"
- typedef enum
- {
- ex_free, ex_explosion, ex_misc, ex_flash, ex_mflash, ex_poly, ex_poly2
- } exptype_t;
- typedef struct
- {
- exptype_t type;
- entity_t ent;
- int frames;
- float light;
- vec3_t lightcolor;
- float start;
- int baseframe;
- } explosion_t;
- #define MAX_EXPLOSIONS 32
- explosion_t cl_explosions[MAX_EXPLOSIONS];
- #define MAX_BEAMS 32
- typedef struct
- {
- int entity;
- int dest_entity;
- struct model_s *model;
- int endtime;
- vec3_t offset;
- vec3_t start, end;
- } beam_t;
- beam_t cl_beams[MAX_BEAMS];
- //PMM - added this for player-linked beams. Currently only used by the plasma beam
- beam_t cl_playerbeams[MAX_BEAMS];
- #define MAX_LASERS 32
- typedef struct
- {
- entity_t ent;
- int endtime;
- } laser_t;
- laser_t cl_lasers[MAX_LASERS];
- //ROGUE
- cl_sustain_t cl_sustains[MAX_SUSTAINS];
- //ROGUE
- //PGM
- extern void CL_TeleportParticles (vec3_t org);
- //PGM
- void CL_BlasterParticles (vec3_t org, vec3_t dir);
- void CL_ExplosionParticles (vec3_t org);
- void CL_BFGExplosionParticles (vec3_t org);
- // RAFAEL
- void CL_BlueBlasterParticles (vec3_t org, vec3_t dir);
- struct sfx_s *cl_sfx_ric1;
- struct sfx_s *cl_sfx_ric2;
- struct sfx_s *cl_sfx_ric3;
- struct sfx_s *cl_sfx_lashit;
- struct sfx_s *cl_sfx_spark5;
- struct sfx_s *cl_sfx_spark6;
- struct sfx_s *cl_sfx_spark7;
- struct sfx_s *cl_sfx_railg;
- struct sfx_s *cl_sfx_rockexp;
- struct sfx_s *cl_sfx_grenexp;
- struct sfx_s *cl_sfx_watrexp;
- // RAFAEL
- struct sfx_s *cl_sfx_plasexp;
- struct sfx_s *cl_sfx_footsteps[4];
- struct model_s *cl_mod_explode;
- struct model_s *cl_mod_smoke;
- struct model_s *cl_mod_flash;
- struct model_s *cl_mod_parasite_segment;
- struct model_s *cl_mod_grapple_cable;
- struct model_s *cl_mod_parasite_tip;
- struct model_s *cl_mod_explo4;
- struct model_s *cl_mod_bfg_explo;
- struct model_s *cl_mod_powerscreen;
- // RAFAEL
- struct model_s *cl_mod_plasmaexplo;
- //ROGUE
- struct sfx_s *cl_sfx_lightning;
- struct sfx_s *cl_sfx_disrexp;
- struct model_s *cl_mod_lightning;
- struct model_s *cl_mod_heatbeam;
- struct model_s *cl_mod_monster_heatbeam;
- struct model_s *cl_mod_explo4_big;
- //ROGUE
- /*
- =================
- CL_RegisterTEntSounds
- =================
- */
- void CL_RegisterTEntSounds (void)
- {
- int i;
- char name[MAX_QPATH];
- // PMM - version stuff
- // Com_Printf ("%s\n", ROGUE_VERSION_STRING);
- // PMM
- cl_sfx_ric1 = S_RegisterSound ("world/ric1.wav");
- cl_sfx_ric2 = S_RegisterSound ("world/ric2.wav");
- cl_sfx_ric3 = S_RegisterSound ("world/ric3.wav");
- cl_sfx_lashit = S_RegisterSound("weapons/lashit.wav");
- cl_sfx_spark5 = S_RegisterSound ("world/spark5.wav");
- cl_sfx_spark6 = S_RegisterSound ("world/spark6.wav");
- cl_sfx_spark7 = S_RegisterSound ("world/spark7.wav");
- cl_sfx_railg = S_RegisterSound ("weapons/railgf1a.wav");
- cl_sfx_rockexp = S_RegisterSound ("weapons/rocklx1a.wav");
- cl_sfx_grenexp = S_RegisterSound ("weapons/grenlx1a.wav");
- cl_sfx_watrexp = S_RegisterSound ("weapons/xpld_wat.wav");
- // RAFAEL
- // cl_sfx_plasexp = S_RegisterSound ("weapons/plasexpl.wav");
- S_RegisterSound ("player/land1.wav");
- S_RegisterSound ("player/fall2.wav");
- S_RegisterSound ("player/fall1.wav");
- for (i=0 ; i<4 ; i++)
- {
- Com_sprintf (name, sizeof(name), "player/step%i.wav", i+1);
- cl_sfx_footsteps[i] = S_RegisterSound (name);
- }
- //PGM
- cl_sfx_lightning = S_RegisterSound ("weapons/tesla.wav");
- cl_sfx_disrexp = S_RegisterSound ("weapons/disrupthit.wav");
- // version stuff
- sprintf (name, "weapons/sound%d.wav", ROGUE_VERSION_ID);
- if (name[0] == 'w')
- name[0] = 'W';
- //PGM
- }
- /*
- =================
- CL_RegisterTEntModels
- =================
- */
- void CL_RegisterTEntModels (void)
- {
- cl_mod_explode = re.RegisterModel ("models/objects/explode/tris.md2");
- cl_mod_smoke = re.RegisterModel ("models/objects/smoke/tris.md2");
- cl_mod_flash = re.RegisterModel ("models/objects/flash/tris.md2");
- cl_mod_parasite_segment = re.RegisterModel ("models/monsters/parasite/segment/tris.md2");
- cl_mod_grapple_cable = re.RegisterModel ("models/ctf/segment/tris.md2");
- cl_mod_parasite_tip = re.RegisterModel ("models/monsters/parasite/tip/tris.md2");
- cl_mod_explo4 = re.RegisterModel ("models/objects/r_explode/tris.md2");
- cl_mod_bfg_explo = re.RegisterModel ("sprites/s_bfg2.sp2");
- cl_mod_powerscreen = re.RegisterModel ("models/items/armor/effect/tris.md2");
- re.RegisterModel ("models/objects/laser/tris.md2");
- re.RegisterModel ("models/objects/grenade2/tris.md2");
- re.RegisterModel ("models/weapons/v_machn/tris.md2");
- re.RegisterModel ("models/weapons/v_handgr/tris.md2");
- re.RegisterModel ("models/weapons/v_shotg2/tris.md2");
- re.RegisterModel ("models/objects/gibs/bone/tris.md2");
- re.RegisterModel ("models/objects/gibs/sm_meat/tris.md2");
- re.RegisterModel ("models/objects/gibs/bone2/tris.md2");
- // RAFAEL
- // re.RegisterModel ("models/objects/blaser/tris.md2");
- re.RegisterPic ("w_machinegun");
- re.RegisterPic ("a_bullets");
- re.RegisterPic ("i_health");
- re.RegisterPic ("a_grenades");
- //ROGUE
- cl_mod_explo4_big = re.RegisterModel ("models/objects/r_explode2/tris.md2");
- cl_mod_lightning = re.RegisterModel ("models/proj/lightning/tris.md2");
- cl_mod_heatbeam = re.RegisterModel ("models/proj/beam/tris.md2");
- cl_mod_monster_heatbeam = re.RegisterModel ("models/proj/widowbeam/tris.md2");
- //ROGUE
- }
- /*
- =================
- CL_ClearTEnts
- =================
- */
- void CL_ClearTEnts (void)
- {
- memset (cl_beams, 0, sizeof(cl_beams));
- memset (cl_explosions, 0, sizeof(cl_explosions));
- memset (cl_lasers, 0, sizeof(cl_lasers));
- //ROGUE
- memset (cl_playerbeams, 0, sizeof(cl_playerbeams));
- memset (cl_sustains, 0, sizeof(cl_sustains));
- //ROGUE
- }
- /*
- =================
- CL_AllocExplosion
- =================
- */
- explosion_t *CL_AllocExplosion (void)
- {
- int i;
- int time;
- int index;
-
- for (i=0 ; i<MAX_EXPLOSIONS ; i++)
- {
- if (cl_explosions[i].type == ex_free)
- {
- memset (&cl_explosions[i], 0, sizeof (cl_explosions[i]));
- return &cl_explosions[i];
- }
- }
- // find the oldest explosion
- time = cl.time;
- index = 0;
- for (i=0 ; i<MAX_EXPLOSIONS ; i++)
- if (cl_explosions[i].start < time)
- {
- time = cl_explosions[i].start;
- index = i;
- }
- memset (&cl_explosions[index], 0, sizeof (cl_explosions[index]));
- return &cl_explosions[index];
- }
- /*
- =================
- CL_SmokeAndFlash
- =================
- */
- void CL_SmokeAndFlash(vec3_t origin)
- {
- explosion_t *ex;
- ex = CL_AllocExplosion ();
- VectorCopy (origin, ex->ent.origin);
- ex->type = ex_misc;
- ex->frames = 4;
- ex->ent.flags = RF_TRANSLUCENT;
- ex->start = cl.frame.servertime - 100;
- ex->ent.model = cl_mod_smoke;
- ex = CL_AllocExplosion ();
- VectorCopy (origin, ex->ent.origin);
- ex->type = ex_flash;
- ex->ent.flags = RF_FULLBRIGHT;
- ex->frames = 2;
- ex->start = cl.frame.servertime - 100;
- ex->ent.model = cl_mod_flash;
- }
- /*
- =================
- CL_ParseParticles
- =================
- */
- void CL_ParseParticles (void)
- {
- int color, count;
- vec3_t pos, dir;
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- color = MSG_ReadByte (&net_message);
- count = MSG_ReadByte (&net_message);
- CL_ParticleEffect (pos, dir, color, count);
- }
- /*
- =================
- CL_ParseBeam
- =================
- */
- int CL_ParseBeam (struct model_s *model)
- {
- int ent;
- vec3_t start, end;
- beam_t *b;
- int i;
-
- ent = MSG_ReadShort (&net_message);
-
- MSG_ReadPos (&net_message, start);
- MSG_ReadPos (&net_message, end);
- // override any beam with the same entity
- for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
- if (b->entity == ent)
- {
- b->entity = ent;
- b->model = model;
- b->endtime = cl.time + 200;
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorClear (b->offset);
- return ent;
- }
- // find a free beam
- for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
- {
- if (!b->model || b->endtime < cl.time)
- {
- b->entity = ent;
- b->model = model;
- b->endtime = cl.time + 200;
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorClear (b->offset);
- return ent;
- }
- }
- Com_Printf ("beam list overflow!\n");
- return ent;
- }
- /*
- =================
- CL_ParseBeam2
- =================
- */
- int CL_ParseBeam2 (struct model_s *model)
- {
- int ent;
- vec3_t start, end, offset;
- beam_t *b;
- int i;
-
- ent = MSG_ReadShort (&net_message);
-
- MSG_ReadPos (&net_message, start);
- MSG_ReadPos (&net_message, end);
- MSG_ReadPos (&net_message, offset);
- // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
- // override any beam with the same entity
- for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
- if (b->entity == ent)
- {
- b->entity = ent;
- b->model = model;
- b->endtime = cl.time + 200;
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorCopy (offset, b->offset);
- return ent;
- }
- // find a free beam
- for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
- {
- if (!b->model || b->endtime < cl.time)
- {
- b->entity = ent;
- b->model = model;
- b->endtime = cl.time + 200;
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorCopy (offset, b->offset);
- return ent;
- }
- }
- Com_Printf ("beam list overflow!\n");
- return ent;
- }
- // ROGUE
- /*
- =================
- CL_ParsePlayerBeam
- - adds to the cl_playerbeam array instead of the cl_beams array
- =================
- */
- int CL_ParsePlayerBeam (struct model_s *model)
- {
- int ent;
- vec3_t start, end, offset;
- beam_t *b;
- int i;
-
- ent = MSG_ReadShort (&net_message);
-
- MSG_ReadPos (&net_message, start);
- MSG_ReadPos (&net_message, end);
- // PMM - network optimization
- if (model == cl_mod_heatbeam)
- VectorSet(offset, 2, 7, -3);
- else if (model == cl_mod_monster_heatbeam)
- {
- model = cl_mod_heatbeam;
- VectorSet(offset, 0, 0, 0);
- }
- else
- MSG_ReadPos (&net_message, offset);
- // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
- // override any beam with the same entity
- // PMM - For player beams, we only want one per player (entity) so..
- for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
- {
- if (b->entity == ent)
- {
- b->entity = ent;
- b->model = model;
- b->endtime = cl.time + 200;
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorCopy (offset, b->offset);
- return ent;
- }
- }
- // find a free beam
- for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
- {
- if (!b->model || b->endtime < cl.time)
- {
- b->entity = ent;
- b->model = model;
- b->endtime = cl.time + 100; // PMM - this needs to be 100 to prevent multiple heatbeams
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorCopy (offset, b->offset);
- return ent;
- }
- }
- Com_Printf ("beam list overflow!\n");
- return ent;
- }
- //rogue
- /*
- =================
- CL_ParseLightning
- =================
- */
- int CL_ParseLightning (struct model_s *model)
- {
- int srcEnt, destEnt;
- vec3_t start, end;
- beam_t *b;
- int i;
-
- srcEnt = MSG_ReadShort (&net_message);
- destEnt = MSG_ReadShort (&net_message);
- MSG_ReadPos (&net_message, start);
- MSG_ReadPos (&net_message, end);
- // override any beam with the same source AND destination entities
- for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
- if (b->entity == srcEnt && b->dest_entity == destEnt)
- {
- // Com_Printf("%d: OVERRIDE %d -> %d\n", cl.time, srcEnt, destEnt);
- b->entity = srcEnt;
- b->dest_entity = destEnt;
- b->model = model;
- b->endtime = cl.time + 200;
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorClear (b->offset);
- return srcEnt;
- }
- // find a free beam
- for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
- {
- if (!b->model || b->endtime < cl.time)
- {
- // Com_Printf("%d: NORMAL %d -> %d\n", cl.time, srcEnt, destEnt);
- b->entity = srcEnt;
- b->dest_entity = destEnt;
- b->model = model;
- b->endtime = cl.time + 200;
- VectorCopy (start, b->start);
- VectorCopy (end, b->end);
- VectorClear (b->offset);
- return srcEnt;
- }
- }
- Com_Printf ("beam list overflow!\n");
- return srcEnt;
- }
- /*
- =================
- CL_ParseLaser
- =================
- */
- void CL_ParseLaser (int colors)
- {
- vec3_t start;
- vec3_t end;
- laser_t *l;
- int i;
- MSG_ReadPos (&net_message, start);
- MSG_ReadPos (&net_message, end);
- for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
- {
- if (l->endtime < cl.time)
- {
- l->ent.flags = RF_TRANSLUCENT | RF_BEAM;
- VectorCopy (start, l->ent.origin);
- VectorCopy (end, l->ent.oldorigin);
- l->ent.alpha = 0.30;
- l->ent.skinnum = (colors >> ((rand() % 4)*8)) & 0xff;
- l->ent.model = NULL;
- l->ent.frame = 4;
- l->endtime = cl.time + 100;
- return;
- }
- }
- }
- //=============
- //ROGUE
- void CL_ParseSteam (void)
- {
- vec3_t pos, dir;
- int id, i;
- int r;
- int cnt;
- int color;
- int magnitude;
- cl_sustain_t *s, *free_sustain;
- id = MSG_ReadShort (&net_message); // an id of -1 is an instant effect
- if (id != -1) // sustains
- {
- // Com_Printf ("Sustain effect id %d\n", id);
- free_sustain = NULL;
- for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
- {
- if (s->id == 0)
- {
- free_sustain = s;
- break;
- }
- }
- if (free_sustain)
- {
- s->id = id;
- s->count = MSG_ReadByte (&net_message);
- MSG_ReadPos (&net_message, s->org);
- MSG_ReadDir (&net_message, s->dir);
- r = MSG_ReadByte (&net_message);
- s->color = r & 0xff;
- s->magnitude = MSG_ReadShort (&net_message);
- s->endtime = cl.time + MSG_ReadLong (&net_message);
- s->think = CL_ParticleSteamEffect2;
- s->thinkinterval = 100;
- s->nextthink = cl.time;
- }
- else
- {
- // Com_Printf ("No free sustains!\n");
- // FIXME - read the stuff anyway
- cnt = MSG_ReadByte (&net_message);
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- r = MSG_ReadByte (&net_message);
- magnitude = MSG_ReadShort (&net_message);
- magnitude = MSG_ReadLong (&net_message); // really interval
- }
- }
- else // instant
- {
- cnt = MSG_ReadByte (&net_message);
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- r = MSG_ReadByte (&net_message);
- magnitude = MSG_ReadShort (&net_message);
- color = r & 0xff;
- CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
- // S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- }
- }
- void CL_ParseWidow (void)
- {
- vec3_t pos;
- int id, i;
- cl_sustain_t *s, *free_sustain;
- id = MSG_ReadShort (&net_message);
- free_sustain = NULL;
- for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
- {
- if (s->id == 0)
- {
- free_sustain = s;
- break;
- }
- }
- if (free_sustain)
- {
- s->id = id;
- MSG_ReadPos (&net_message, s->org);
- s->endtime = cl.time + 2100;
- s->think = CL_Widowbeamout;
- s->thinkinterval = 1;
- s->nextthink = cl.time;
- }
- else // no free sustains
- {
- // FIXME - read the stuff anyway
- MSG_ReadPos (&net_message, pos);
- }
- }
- void CL_ParseNuke (void)
- {
- vec3_t pos;
- int i;
- cl_sustain_t *s, *free_sustain;
- free_sustain = NULL;
- for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
- {
- if (s->id == 0)
- {
- free_sustain = s;
- break;
- }
- }
- if (free_sustain)
- {
- s->id = 21000;
- MSG_ReadPos (&net_message, s->org);
- s->endtime = cl.time + 1000;
- s->think = CL_Nukeblast;
- s->thinkinterval = 1;
- s->nextthink = cl.time;
- }
- else // no free sustains
- {
- // FIXME - read the stuff anyway
- MSG_ReadPos (&net_message, pos);
- }
- }
- //ROGUE
- //=============
- /*
- =================
- CL_ParseTEnt
- =================
- */
- static byte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8};
- void CL_ParseTEnt (void)
- {
- int type;
- vec3_t pos, pos2, dir;
- explosion_t *ex;
- int cnt;
- int color;
- int r;
- int ent;
- int magnitude;
- type = MSG_ReadByte (&net_message);
- switch (type)
- {
- case TE_BLOOD: // bullet hitting flesh
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- CL_ParticleEffect (pos, dir, 0xe8, 60);
- break;
- case TE_GUNSHOT: // bullet hitting wall
- case TE_SPARKS:
- case TE_BULLET_SPARKS:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- if (type == TE_GUNSHOT)
- CL_ParticleEffect (pos, dir, 0, 40);
- else
- CL_ParticleEffect (pos, dir, 0xe0, 6);
- if (type != TE_SPARKS)
- {
- CL_SmokeAndFlash(pos);
-
- // impact sound
- cnt = rand()&15;
- if (cnt == 1)
- S_StartSound (pos, 0, 0, cl_sfx_ric1, 1, ATTN_NORM, 0);
- else if (cnt == 2)
- S_StartSound (pos, 0, 0, cl_sfx_ric2, 1, ATTN_NORM, 0);
- else if (cnt == 3)
- S_StartSound (pos, 0, 0, cl_sfx_ric3, 1, ATTN_NORM, 0);
- }
- break;
-
- case TE_SCREEN_SPARKS:
- case TE_SHIELD_SPARKS:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- if (type == TE_SCREEN_SPARKS)
- CL_ParticleEffect (pos, dir, 0xd0, 40);
- else
- CL_ParticleEffect (pos, dir, 0xb0, 40);
- //FIXME : replace or remove this sound
- S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- break;
-
- case TE_SHOTGUN: // bullet hitting wall
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- CL_ParticleEffect (pos, dir, 0, 20);
- CL_SmokeAndFlash(pos);
- break;
- case TE_SPLASH: // bullet hitting water
- cnt = MSG_ReadByte (&net_message);
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- r = MSG_ReadByte (&net_message);
- if (r > 6)
- color = 0x00;
- else
- color = splash_color[r];
- CL_ParticleEffect (pos, dir, color, cnt);
- if (r == SPLASH_SPARKS)
- {
- r = rand() & 3;
- if (r == 0)
- S_StartSound (pos, 0, 0, cl_sfx_spark5, 1, ATTN_STATIC, 0);
- else if (r == 1)
- S_StartSound (pos, 0, 0, cl_sfx_spark6, 1, ATTN_STATIC, 0);
- else
- S_StartSound (pos, 0, 0, cl_sfx_spark7, 1, ATTN_STATIC, 0);
- }
- break;
- case TE_LASER_SPARKS:
- cnt = MSG_ReadByte (&net_message);
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- color = MSG_ReadByte (&net_message);
- CL_ParticleEffect2 (pos, dir, color, cnt);
- break;
- // RAFAEL
- case TE_BLUEHYPERBLASTER:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadPos (&net_message, dir);
- CL_BlasterParticles (pos, dir);
- break;
- case TE_BLASTER: // blaster hitting wall
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- CL_BlasterParticles (pos, dir);
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->ent.angles[0] = acos(dir[2])/M_PI*180;
- // PMM - fixed to correct for pitch of 0
- if (dir[0])
- ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
- else if (dir[1] > 0)
- ex->ent.angles[1] = 90;
- else if (dir[1] < 0)
- ex->ent.angles[1] = 270;
- else
- ex->ent.angles[1] = 0;
- ex->type = ex_misc;
- ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
- ex->start = cl.frame.servertime - 100;
- ex->light = 150;
- ex->lightcolor[0] = 1;
- ex->lightcolor[1] = 1;
- ex->ent.model = cl_mod_explode;
- ex->frames = 4;
- S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- break;
-
- case TE_RAILTRAIL: // railgun effect
- MSG_ReadPos (&net_message, pos);
- MSG_ReadPos (&net_message, pos2);
- CL_RailTrail (pos, pos2);
- S_StartSound (pos2, 0, 0, cl_sfx_railg, 1, ATTN_NORM, 0);
- break;
- case TE_EXPLOSION2:
- case TE_GRENADE_EXPLOSION:
- case TE_GRENADE_EXPLOSION_WATER:
- MSG_ReadPos (&net_message, pos);
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->type = ex_poly;
- ex->ent.flags = RF_FULLBRIGHT;
- ex->start = cl.frame.servertime - 100;
- ex->light = 350;
- ex->lightcolor[0] = 1.0;
- ex->lightcolor[1] = 0.5;
- ex->lightcolor[2] = 0.5;
- ex->ent.model = cl_mod_explo4;
- ex->frames = 19;
- ex->baseframe = 30;
- ex->ent.angles[1] = rand() % 360;
- CL_ExplosionParticles (pos);
- if (type == TE_GRENADE_EXPLOSION_WATER)
- S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
- else
- S_StartSound (pos, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
- break;
- // RAFAEL
- case TE_PLASMA_EXPLOSION:
- MSG_ReadPos (&net_message, pos);
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->type = ex_poly;
- ex->ent.flags = RF_FULLBRIGHT;
- ex->start = cl.frame.servertime - 100;
- ex->light = 350;
- ex->lightcolor[0] = 1.0;
- ex->lightcolor[1] = 0.5;
- ex->lightcolor[2] = 0.5;
- ex->ent.angles[1] = rand() % 360;
- ex->ent.model = cl_mod_explo4;
- if (frand() < 0.5)
- ex->baseframe = 15;
- ex->frames = 15;
- CL_ExplosionParticles (pos);
- S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
- break;
-
- case TE_EXPLOSION1:
- case TE_EXPLOSION1_BIG: // PMM
- case TE_ROCKET_EXPLOSION:
- case TE_ROCKET_EXPLOSION_WATER:
- case TE_EXPLOSION1_NP: // PMM
- MSG_ReadPos (&net_message, pos);
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->type = ex_poly;
- ex->ent.flags = RF_FULLBRIGHT;
- ex->start = cl.frame.servertime - 100;
- ex->light = 350;
- ex->lightcolor[0] = 1.0;
- ex->lightcolor[1] = 0.5;
- ex->lightcolor[2] = 0.5;
- ex->ent.angles[1] = rand() % 360;
- if (type != TE_EXPLOSION1_BIG) // PMM
- ex->ent.model = cl_mod_explo4; // PMM
- else
- ex->ent.model = cl_mod_explo4_big;
- if (frand() < 0.5)
- ex->baseframe = 15;
- ex->frames = 15;
- if ((type != TE_EXPLOSION1_BIG) && (type != TE_EXPLOSION1_NP)) // PMM
- CL_ExplosionParticles (pos); // PMM
- if (type == TE_ROCKET_EXPLOSION_WATER)
- S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
- else
- S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
- break;
- case TE_BFG_EXPLOSION:
- MSG_ReadPos (&net_message, pos);
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->type = ex_poly;
- ex->ent.flags = RF_FULLBRIGHT;
- ex->start = cl.frame.servertime - 100;
- ex->light = 350;
- ex->lightcolor[0] = 0.0;
- ex->lightcolor[1] = 1.0;
- ex->lightcolor[2] = 0.0;
- ex->ent.model = cl_mod_bfg_explo;
- ex->ent.flags |= RF_TRANSLUCENT;
- ex->ent.alpha = 0.30;
- ex->frames = 4;
- break;
- case TE_BFG_BIGEXPLOSION:
- MSG_ReadPos (&net_message, pos);
- CL_BFGExplosionParticles (pos);
- break;
- case TE_BFG_LASER:
- CL_ParseLaser (0xd0d1d2d3);
- break;
- case TE_BUBBLETRAIL:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadPos (&net_message, pos2);
- CL_BubbleTrail (pos, pos2);
- break;
- case TE_PARASITE_ATTACK:
- case TE_MEDIC_CABLE_ATTACK:
- ent = CL_ParseBeam (cl_mod_parasite_segment);
- break;
- case TE_BOSSTPORT: // boss teleporting to station
- MSG_ReadPos (&net_message, pos);
- CL_BigTeleportParticles (pos);
- S_StartSound (pos, 0, 0, S_RegisterSound ("misc/bigtele.wav"), 1, ATTN_NONE, 0);
- break;
- case TE_GRAPPLE_CABLE:
- ent = CL_ParseBeam2 (cl_mod_grapple_cable);
- break;
- // RAFAEL
- case TE_WELDING_SPARKS:
- cnt = MSG_ReadByte (&net_message);
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- color = MSG_ReadByte (&net_message);
- CL_ParticleEffect2 (pos, dir, color, cnt);
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->type = ex_flash;
- // note to self
- // we need a better no draw flag
- ex->ent.flags = RF_BEAM;
- ex->start = cl.frame.servertime - 0.1;
- ex->light = 100 + (rand()%75);
- ex->lightcolor[0] = 1.0;
- ex->lightcolor[1] = 1.0;
- ex->lightcolor[2] = 0.3;
- ex->ent.model = cl_mod_flash;
- ex->frames = 2;
- break;
- case TE_GREENBLOOD:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- CL_ParticleEffect2 (pos, dir, 0xdf, 30);
- break;
- // RAFAEL
- case TE_TUNNEL_SPARKS:
- cnt = MSG_ReadByte (&net_message);
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- color = MSG_ReadByte (&net_message);
- CL_ParticleEffect3 (pos, dir, color, cnt);
- break;
- //=============
- //PGM
- // PMM -following code integrated for flechette (different color)
- case TE_BLASTER2: // green blaster hitting wall
- case TE_FLECHETTE: // flechette
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
-
- // PMM
- if (type == TE_BLASTER2)
- CL_BlasterParticles2 (pos, dir, 0xd0);
- else
- CL_BlasterParticles2 (pos, dir, 0x6f); // 75
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->ent.angles[0] = acos(dir[2])/M_PI*180;
- // PMM - fixed to correct for pitch of 0
- if (dir[0])
- ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
- else if (dir[1] > 0)
- ex->ent.angles[1] = 90;
- else if (dir[1] < 0)
- ex->ent.angles[1] = 270;
- else
- ex->ent.angles[1] = 0;
- ex->type = ex_misc;
- ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
- // PMM
- if (type == TE_BLASTER2)
- ex->ent.skinnum = 1;
- else // flechette
- ex->ent.skinnum = 2;
- ex->start = cl.frame.servertime - 100;
- ex->light = 150;
- // PMM
- if (type == TE_BLASTER2)
- ex->lightcolor[1] = 1;
- else // flechette
- {
- ex->lightcolor[0] = 0.19;
- ex->lightcolor[1] = 0.41;
- ex->lightcolor[2] = 0.75;
- }
- ex->ent.model = cl_mod_explode;
- ex->frames = 4;
- S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- break;
- case TE_LIGHTNING:
- ent = CL_ParseLightning (cl_mod_lightning);
- S_StartSound (NULL, ent, CHAN_WEAPON, cl_sfx_lightning, 1, ATTN_NORM, 0);
- break;
- case TE_DEBUGTRAIL:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadPos (&net_message, pos2);
- CL_DebugTrail (pos, pos2);
- break;
- case TE_PLAIN_EXPLOSION:
- MSG_ReadPos (&net_message, pos);
- ex = CL_AllocExplosion ();
- VectorCopy (pos, ex->ent.origin);
- ex->type = ex_poly;
- ex->ent.flags = RF_FULLBRIGHT;
- ex->start = cl.frame.servertime - 100;
- ex->light = 350;
- ex->lightcolor[0] = 1.0;
- ex->lightcolor[1] = 0.5;
- ex->lightcolor[2] = 0.5;
- ex->ent.angles[1] = rand() % 360;
- ex->ent.model = cl_mod_explo4;
- if (frand() < 0.5)
- ex->baseframe = 15;
- ex->frames = 15;
- if (type == TE_ROCKET_EXPLOSION_WATER)
- S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
- else
- S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
- break;
- case TE_FLASHLIGHT:
- MSG_ReadPos(&net_message, pos);
- ent = MSG_ReadShort(&net_message);
- CL_Flashlight(ent, pos);
- break;
- case TE_FORCEWALL:
- MSG_ReadPos(&net_message, pos);
- MSG_ReadPos(&net_message, pos2);
- color = MSG_ReadByte (&net_message);
- CL_ForceWall(pos, pos2, color);
- break;
- case TE_HEATBEAM:
- ent = CL_ParsePlayerBeam (cl_mod_heatbeam);
- break;
- case TE_MONSTER_HEATBEAM:
- ent = CL_ParsePlayerBeam (cl_mod_monster_heatbeam);
- break;
- case TE_HEATBEAM_SPARKS:
- // cnt = MSG_ReadByte (&net_message);
- cnt = 50;
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- // r = MSG_ReadByte (&net_message);
- // magnitude = MSG_ReadShort (&net_message);
- r = 8;
- magnitude = 60;
- color = r & 0xff;
- CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
- S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- break;
-
- case TE_HEATBEAM_STEAM:
- // cnt = MSG_ReadByte (&net_message);
- cnt = 20;
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- // r = MSG_ReadByte (&net_message);
- // magnitude = MSG_ReadShort (&net_message);
- // color = r & 0xff;
- color = 0xe0;
- magnitude = 60;
- CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
- S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- break;
- case TE_STEAM:
- CL_ParseSteam();
- break;
- case TE_BUBBLETRAIL2:
- // cnt = MSG_ReadByte (&net_message);
- cnt = 8;
- MSG_ReadPos (&net_message, pos);
- MSG_ReadPos (&net_message, pos2);
- CL_BubbleTrail2 (pos, pos2, cnt);
- S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- break;
- case TE_MOREBLOOD:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- CL_ParticleEffect (pos, dir, 0xe8, 250);
- break;
- case TE_CHAINFIST_SMOKE:
- dir[0]=0; dir[1]=0; dir[2]=1;
- MSG_ReadPos(&net_message, pos);
- CL_ParticleSmokeEffect (pos, dir, 0, 20, 20);
- break;
- case TE_ELECTRIC_SPARKS:
- MSG_ReadPos (&net_message, pos);
- MSG_ReadDir (&net_message, dir);
- // CL_ParticleEffect (pos, dir, 109, 40);
- CL_ParticleEffect (pos, dir, 0x75, 40);
- //FIXME : replace or remove this sound
- S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
- break;
- case TE_TRACKER_EXPLOSION:
- MSG_ReadPos (&net_message, pos);
- CL_ColorFlash (pos, 0, 150, -1, -1, -1);
- CL_ColorExplosionParticles (pos, 0, 1);
- // CL_Tracker_Explode (pos);
- S_StartSound (pos, 0, 0, cl_sfx_disrexp, 1, ATTN_NORM, 0);
- break;
- case TE_TELEPORT_EFFECT:
- case TE_DBALL_GOAL:
- MSG_ReadPos (&net_message, pos);
- CL_TeleportParticles (pos);
- break;
- case TE_WIDOWBEAMOUT:
- CL_ParseWidow ();
- break;
- case TE_NUKEBLAST:
- CL_ParseNuke ();
- break;
- case TE_WIDOWSPLASH:
- MSG_ReadPos (&net_message, pos);
- CL_WidowSplash (pos);
- break;
- //PGM
- //==============
- default:
- Com_Error (ERR_DROP, "CL_ParseTEnt: bad type");
- }
- }
- /*
- =================
- CL_AddBeams
- =================
- */
- void CL_AddBeams (void)
- {
- int i,j;
- beam_t *b;
- vec3_t dist, org;
- float d;
- entity_t ent;
- float yaw, pitch;
- float forward;
- float len, steps;
- float model_length;
-
- // update beams
- for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
- {
- if (!b->model || b->endtime < cl.time)
- continue;
- // if coming from the player, update the start position
- if (b->entity == cl.playernum+1) // entity 0 is the world
- {
- VectorCopy (cl.refdef.vieworg, b->start);
- b->start[2] -= 22; // adjust for view height
- }
- VectorAdd (b->start, b->offset, org);
- // calculate pitch and yaw
- VectorSubtract (b->end, org, dist);
- if (dist[1] == 0 && dist[0] == 0)
- {
- yaw = 0;
- if (dist[2] > 0)
- pitch = 90;
- else
- pitch = 270;
- }
- else
- {
- // PMM - fixed to correct for pitch of 0
- if (dist[0])
- yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
- else if (dist[1] > 0)
- yaw = 90;
- else
- yaw = 270;
- if (yaw < 0)
- yaw += 360;
-
- forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
- pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
- if (pitch < 0)
- pitch += 360.0;
- }
- // add new entities for the beams
- d = VectorNormalize(dist);
- memset (&ent, 0, sizeof(ent));
- if (b->model == cl_mod_lightning)
- {
- model_length = 35.0;
- d-= 20.0; // correction so it doesn't end in middle of tesla
- }
- else
- {
- model_length = 30.0;
- }
- steps = ceil(d/model_length);
- len = (d-model_length)/(steps-1);
- // PMM - special case for lightning model .. if the real length is shorter than the model,
- // flip it around & draw it from the end to the start. This prevents the model from going
- // through the tesla mine (instead it goes through the target)
- if ((b->model == cl_mod_lightning) && (d <= model_length))
- {
- // Com_Printf ("special case\n");
- VectorCopy (b->end, ent.origin);
- // offset to push beam outside of tesla model (negative because dist is from end to start
- // for this beam)
- // for (j=0 ; j<3 ; j++)
- // ent.origin[j] -= dist[j]*10.0;
- ent.model = b->model;
- ent.flags = RF_FULLBRIGHT;
- ent.angles[0] = pitch;
- ent.angles[1] = yaw;
- ent.angles[2] = rand()%360;
- V_AddEntity (&ent);
- return;
- }
- while (d > 0)
- {
- VectorCopy (org, ent.origin);
- ent.model = b->model;
- if (b->model == cl_mod_lightning)
- {
- ent.flags = RF_FULLBRIGHT;
- ent.angles[0] = -pitch;
- ent.angles[1] = yaw + 180.0;
- ent.angles[2] = rand()%360;
- }
- else
- {
- ent.angles[0] = pitch;
- ent.angles[1] = yaw;
- ent.angles[2] = rand()%360;
- }
-
- // Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
- V_AddEntity (&ent);
- for (j=0 ; j<3 ; j++)
- org[j] += dist[j]*len;
- d -= model_length;
- }
- }
- }
- /*
- // Com_Printf ("Endpoint: %f %f %f\n", b->end[0], b->end[1], b->end[2]);
- // Com_Printf ("Pred View Angles: %f %f %f\n", cl.predicted_angles[0], cl.predicted_angles[1], cl.predicted_angles[2]);
- // Com_Printf ("Act View Angles: %f %f %f\n", cl.refdef.viewangles[0], cl.refdef.viewangles[1], cl.refdef.viewangles[2]);
- // VectorCopy (cl.predicted_origin, b->start);
- // b->start[2] += 22; // adjust for view height
- // if (fabs(cl.refdef.vieworg[2] - b->start[2]) >= 10) {
- // b->start[2] = cl.refdef.vieworg[2];
- // }
- // Com_Printf ("Time: %d %d %f\n", cl.time, cls.realtime, cls.frametime);
- */
- extern cvar_t *hand;
- /*
- =================
- ROGUE - draw player locked beams
- CL_AddPlayerBeams
- =================
- */
- void CL_AddPlayerBeams (void)
- {
- int i,j;
- beam_t *b;
- vec3_t dist, org;
- float d;
- entity_t ent;
- float yaw, pitch;
- float forward;
- float len, steps;
- int framenum;
- float model_length;
-
- float hand_multiplier;
- frame_t *oldframe;
- player_state_t *ps, *ops;
- //PMM
- if (hand)
- {
- if (hand->value == 2)
- hand_multiplier = 0;
- else if (hand->value == 1)
- hand_multiplier = -1;
- else
- hand_multiplier = 1;
- }
- else
- {
- hand_multiplier = 1;
- }
- //PMM
- // update beams
- for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
- {
- vec3_t f,r,u;
- if (!b->model || b->endtime < cl.time)
- continue;
- if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
- {
- // if coming from the player, update the start position
- if (b->entity == cl.playernum+1) // entity 0 is the world
- {
- // set up gun position
- // code straight out of CL_AddViewWeapon
- ps = &cl.frame.playerstate;
- j = (cl.frame.serverframe - 1) & UPDATE_MASK;
- oldframe = &cl.frames[j];
- if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
- oldframe = &cl.frame; // previous frame was dropped or involid
- ops = &oldframe->playerstate;
- for (j=0 ; j<3 ; j++)
- {
- b->start[j] = cl.refdef.vieworg[j] + ops->gunoffset[j]
- + cl.lerpfrac * (ps->gunoffset[j] - ops->gunoffset[j]);
- }
- VectorMA (b->start, (hand_multiplier * b->offset[0]), cl.v_right, org);
- VectorMA ( org, b->offset[1], cl.v_forward, org);
- VectorMA ( org, b->offset[2], cl.v_up, org);
- if ((hand) && (hand->value == 2)) {
- VectorMA (org, -1, cl.v_up, org);
- }
- // FIXME - take these out when final
- VectorCopy (cl.v_right, r);
- VectorCopy (cl.v_forward, f);
- VectorCopy (cl.v_up, u);
- }
- else
- VectorCopy (b->start, org);
- }
- else
- {
- // if coming from the player, update the start position
- if (b->entity == cl.playernum+1) // entity 0 is the world
- {
- VectorCopy (cl.refdef.vieworg, b->start);
- b->start[2] -= 22; // adjust for view height
- }
- VectorAdd (b->start, b->offset, org);
- }
- // calculate pitch and yaw
- VectorSubtract (b->end, org, dist);
- //PMM
- if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1))
- {
- vec_t len;
- len = VectorLength (dist);
- VectorScale (f, len, dist);
- VectorMA (dist, (hand_multiplier * b->offset[0]), r, dist);
- VectorMA (dist, b->offset[1], f, dist);
- VectorMA (dist, b->offset[2], u, dist);
- if ((hand) && (hand->value == 2)) {
- VectorMA (org, -1, cl.v_up, org);
- }
- }
- //PMM
- if (dist[1] == 0 && dist[0] == 0)
- {
- yaw = 0;
- if (dist[2] > 0)
- pitch = 90;
- else
- pitch = 270;
- }
- else
- {
- // PMM - fixed to correct for pitch of 0
- if (dist[0])
- yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
- else if (dist[1] > 0)
- yaw = 90;
- else
- yaw = 270;
- if (yaw < 0)
- yaw += 360;
-
- forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
- pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
- if (pitch < 0)
- pitch += 360.0;
- }
-
- if (cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
- {
- if (b->entity != cl.playernum+1)
- {
- framenum = 2;
- // Com_Printf ("Third person\n");
- ent.angles[0] = -pitch;
- ent.angles[1] = yaw + 180.0;
- ent.angles[2] = 0;
- // Com_Printf ("%f %f - %f %f %f\n", -pitch, yaw+180.0, b->offset[0], b->offset[1], b->offset[2]);
- AngleVectors(ent.angles, f, r, u);
-
- // if it's a non-origin offset, it's a player, so use the hardcoded player offset
- if (!VectorCompare (b->offset, vec3_origin))
- {
- VectorMA (org, -(b->offset[0])+1, r, org);
- VectorMA (org, -(b->offset[1]), f, org);
- VectorMA (org, -(b->offset[2])-10, u, org);
- }
- else
- {
- // if it's a monster, do the particle effect
- CL_MonsterPlasma_Shell(b->start);
- }
- }
- else
- {
- framenum = 1;
- }
- }
- // if it's the heatbeam, draw the particle effect
- if ((cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1)))
- {
- CL_Heatbeam (org, dist);
- }
- // add new entities for the beams
- d = VectorNormalize(dist);
- memset (&ent, 0, sizeof(ent));
- if (b->model == cl_mod_heatbeam)
- {
- model_length = 32.0;
- }
- else if (b->model == cl_mod_lightning)
- {
- model_length = 35.0;
- d-= 20.0; // correction so it doesn't end in middle of tesla
- }
- else
- {
- model_length = 30.0;
- }
- steps = ceil(d/model_length);
- len = (d-model_length)/(steps-1);
- // PMM - special case for lightning model .. if the real length is shorter than the model,
- // flip it around & draw it from the end to the start. This prevents the model from going
- // through the tesla mine (instead it goes through the target)
- if ((b->model == cl_mod_lightning) && (d <= model_length))
- {
- // Com_Printf ("special case\n");
- VectorCopy (b->end, ent.origin);
- // offset to push beam outside of tesla model (negative because dist is from end to start
- // for this beam)
- // for (j=0 ; j<3 ; j++)
- // ent.origin[j] -= dist[j]*10.0;
- ent.model = b->model;
- ent.flags = RF_FULLBRIGHT;
- ent.angles[0] = pitch;
- ent.angles[1] = yaw;
- ent.angles[2] = rand()%360;
- V_AddEntity (&ent);
- return;
- }
- while (d > 0)
- {
- VectorCopy (org, ent.origin);
- ent.model = b->model;
- if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
- {
- // ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
- // ent.alpha = 0.3;
- ent.flags = RF_FULLBRIGHT;
- ent.angles[0] = -pitch;
- ent.angles[1] = yaw + 180.0;
- ent.angles[2] = (cl.time) % 360;
- // ent.angles[2] = rand()%360;
- ent.frame = framenum;
- }
- else if (b->model == cl_mod_lightning)
- {
- ent.flags = RF_FULLBRIGHT;
- ent.angles[0] = -pitch;
- ent.angles[1] = yaw + 180.0;
- ent.angles[2] = rand()%360;
- }
- else
- {
- ent.angles[0] = pitch;
- ent.angles[1] = yaw;
- ent.angles[2] = rand()%360;
- }
-
- // Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
- V_AddEntity (&ent);
- for (j=0 ; j<3 ; j++)
- org[j] += dist[j]*len;
- d -= model_length;
- }
- }
- }
- /*
- =================
- CL_AddExplosions
- =================
- */
- void CL_AddExplosions (void)
- {
- entity_t *ent;
- int i;
- explosion_t *ex;
- float frac;
- int f;
- memset (&ent, 0, sizeof(ent));
- for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++)
- {
- if (ex->type == ex_free)
- continue;
- frac = (cl.time - ex->start)/100.0;
- f = floor(frac);
- ent = &ex->ent;
- switch (ex->type)
- {
- case ex_mflash:
- if (f >= ex->frames-1)
- ex->type = ex_free;
- break;
- case ex_misc:
- if (f >= ex->frames-1)
- {
- ex->type = ex_free;
- break;
- }
- ent->alpha = 1.0 - frac/(ex->frames-1);
- break;
- case ex_flash:
- if (f >= 1)
- {
- ex->type = ex_free;
- break;
- }
- ent->alpha = 1.0;
- break;
- case ex_poly:
- if (f >= ex->frames-1)
- {
- ex->type = ex_free;
- break;
- }
- ent->alpha = (16.0 - (float)f)/16.0;
- if (f < 10)
- {
- ent->skinnum = (f>>1);
- if (ent->skinnum < 0)
- ent->skinnum = 0;
- }
- else
- {
- ent->flags |= RF_TRANSLUCENT;
- if (f < 13)
- ent->skinnum = 5;
- else
- ent->skinnum = 6;
- }
- break;
- case ex_poly2:
- if (f >= ex->frames-1)
- {
- ex->type = ex_free;
- break;
- }
- ent->alpha = (5.0 - (float)f)/5.0;
- ent->skinnum = 0;
- ent->flags |= RF_TRANSLUCENT;
- break;
- }
- if (ex->type == ex_free)
- continue;
- if (ex->light)
- {
- V_AddLight (ent->origin, ex->light*ent->alpha,
- ex->lightcolor[0], ex->lightcolor[1], ex->lightcolor[2]);
- }
- VectorCopy (ent->origin, ent->oldorigin);
- if (f < 0)
- f = 0;
- ent->frame = ex->baseframe + f + 1;
- ent->oldframe = ex->baseframe + f;
- ent->backlerp = 1.0 - cl.lerpfrac;
- V_AddEntity (ent);
- }
- }
- /*
- =================
- CL_AddLasers
- =================
- */
- void CL_AddLasers (void)
- {
- laser_t *l;
- int i;
- for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
- {
- if (l->endtime >= cl.time)
- V_AddEntity (&l->ent);
- }
- }
- /* PMM - CL_Sustains */
- void CL_ProcessSustain ()
- {
- cl_sustain_t *s;
- int i;
- for (i=0, s=cl_sustains; i< MAX_SUSTAINS; i++, s++)
- {
- if (s->id)
- if ((s->endtime >= cl.time) && (cl.time >= s->nextthink))
- {
- // Com_Printf ("think %d %d %d\n", cl.time, s->nextthink, s->thinkinterval);
- s->think (s);
- }
- else if (s->endtime < cl.time)
- s->id = 0;
- }
- }
- /*
- =================
- CL_AddTEnts
- =================
- */
- void CL_AddTEnts (void)
- {
- CL_AddBeams ();
- // PMM - draw plasma beams
- CL_AddPlayerBeams ();
- CL_AddExplosions ();
- CL_AddLasers ();
- // PMM - set up sustain
- CL_ProcessSustain();
- }
|