From c4fcffe436fbfb5b0f3b7be2e5ee103ec74932f7 Mon Sep 17 00:00:00 2001 From: Rene Stoeckel Date: Wed, 22 Sep 2004 19:22:16 +0000 Subject: major refactoring in game, server and client package --- src/jake2/client/CL_tent.java | 3482 +++++++++++++++++++++-------------------- 1 file changed, 1782 insertions(+), 1700 deletions(-) (limited to 'src/jake2/client/CL_tent.java') diff --git a/src/jake2/client/CL_tent.java b/src/jake2/client/CL_tent.java index bca8edf..132fa4a 100644 --- a/src/jake2/client/CL_tent.java +++ b/src/jake2/client/CL_tent.java @@ -1,1722 +1,1804 @@ /* - * CL_tent.java + * java * Copyright (C) 2004 * - * $Id: CL_tent.java,v 1.4 2004-07-09 10:19:57 hzi Exp $ + * $Id: CL_tent.java,v 1.5 2004-09-22 19:22:08 salomo Exp $ */ /* -Copyright (C) 1997-2001 Id Software, Inc. + 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 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. + 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. + 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. + 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. -*/ + */ package jake2.client; +import jake2.Defines; import jake2.Globals; +import jake2.client.cl_sustain_t.ThinkAdapter; import jake2.game.player_state_t; import jake2.qcommon.Com; import jake2.qcommon.MSG; import jake2.render.model_t; import jake2.sound.*; +import jake2.util.Lib; +import jake2.util.Math3D; /** * CL_tent */ -public class CL_tent extends Globals { - - static final int ex_free = 0; - static final int ex_explosion = 1; - static final int ex_misc = 2; - static final int ex_flash = 3; - static final int ex_mflash = 4; - static final int ex_poly = 5; - static final int ex_poly2 = 6; - - - static class explosion_t { - int type; - entity_t ent = new entity_t(); - - int frames; - float light; - float[] lightcolor = new float[3]; - float start; - int baseframe; - void clear() { - lightcolor[0] = lightcolor[1] = lightcolor[2] = - light = start = type = frames = baseframe = 0; - ent = new entity_t(); - } - } - - static final int MAX_EXPLOSIONS = 32; - static explosion_t[] cl_explosions = new explosion_t[MAX_EXPLOSIONS]; - static { - for (int i = 0; i < cl_explosions.length; i++) - cl_explosions[i] = new explosion_t(); - } - - static final int MAX_BEAMS = 32; - - static class beam_t { - int entity; - int dest_entity; - model_t model; - int endtime; - float[] offset = new float[3]; - float[] start = new float[3]; - float[] end = new float[3]; - void clear() { - offset[0] = offset[1] = offset[2] = - start[0] = start[1] = start[2] = - end[0] = end[1] = end[2] = - entity = dest_entity = endtime = 0; - model = null; - } - } - static beam_t[] cl_beams = new beam_t[MAX_BEAMS]; - // PMM - added this for player-linked beams. Currently only used by the plasma beam - static beam_t[] cl_playerbeams = new beam_t[MAX_BEAMS]; - static { - for (int i = 0; i < cl_beams.length; i++) - cl_beams[i] = new beam_t(); - for (int i = 0; i < cl_playerbeams.length; i++) - cl_playerbeams[i] = new beam_t(); - } - - static final int MAX_LASERS = 32; - - static class laser_t { - entity_t ent = new entity_t(); - int endtime; - void clear() { - endtime = 0; - ent = new entity_t(); - } - } - static laser_t[] cl_lasers = new laser_t[MAX_LASERS]; - static { - for (int i = 0; i < cl_lasers.length; i++) - cl_lasers[i] = new laser_t(); - } - -// ROGUE - static final int MAX_SUSTAINS = 32; - static cl_sustain_t[] cl_sustains = new cl_sustain_t[MAX_SUSTAINS]; - static { - for (int i = 0; i < cl_sustains.length; i++) - cl_sustains[i] = new cl_sustain_t(); - } -// ROGUE - - // all are references; - static sfx_t cl_sfx_ric1; - static sfx_t cl_sfx_ric2; - static sfx_t cl_sfx_ric3; - static sfx_t cl_sfx_lashit; - static sfx_t cl_sfx_spark5; - static sfx_t cl_sfx_spark6; - static sfx_t cl_sfx_spark7; - static sfx_t cl_sfx_railg; - static sfx_t cl_sfx_rockexp; - static sfx_t cl_sfx_grenexp; - static sfx_t cl_sfx_watrexp; - // RAFAEL - static sfx_t cl_sfx_plasexp; - static sfx_t cl_sfx_footsteps[] = new sfx_t[4]; - - static model_t cl_mod_explode; - static model_t cl_mod_smoke; - static model_t cl_mod_flash; - static model_t cl_mod_parasite_segment; - static model_t cl_mod_grapple_cable; - static model_t cl_mod_parasite_tip; - static model_t cl_mod_explo4; - static model_t cl_mod_bfg_explo; - static model_t cl_mod_powerscreen; - // RAFAEL - static model_t cl_mod_plasmaexplo; - - // ROGUE - static sfx_t cl_sfx_lightning; - static sfx_t cl_sfx_disrexp; - static model_t cl_mod_lightning; - static model_t cl_mod_heatbeam; - static model_t cl_mod_monster_heatbeam; - static model_t cl_mod_explo4_big; - -// ROGUE - /* - ================= - CL_RegisterTEntSounds - ================= - */ - static void RegisterTEntSounds() { - int i; - String name; - - // 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); - name = "player/step" + (i + 1) + ".wav"; - 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 - ================= - */ - static void RegisterTEntModels() { - 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 - ================= - */ - static void ClearTEnts() { - // memset (cl_beams, 0, sizeof(cl_beams)); - for (int i = 0; i < cl_beams.length; i++) - cl_beams[i].clear(); - // memset (cl_explosions, 0, sizeof(cl_explosions)); - for (int i = 0; i < cl_explosions.length; i++) - cl_explosions[i].clear(); - // memset (cl_lasers, 0, sizeof(cl_lasers)); - for (int i = 0; i < cl_lasers.length; i++) - cl_lasers[i].clear(); - // - // ROGUE - // memset (cl_playerbeams, 0, sizeof(cl_playerbeams)); - for (int i = 0; i < cl_playerbeams.length; i++) - cl_playerbeams[i].clear(); - // memset (cl_sustains, 0, sizeof(cl_sustains)); - for (int i = 0; i < cl_sustains.length; i++) - cl_sustains[i].clear(); - // ROGUE - } - - /* - ================= - CL_AllocExplosion - ================= - */ - static explosion_t AllocExplosion() { - 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])); - cl_explosions[i].clear(); - 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 = (int)cl_explosions[i].start; - index = i; - } - //memset (&cl_explosions[index], 0, sizeof (cl_explosions[index])); - cl_explosions[index].clear(); - return cl_explosions[index]; - } - - /* - ================= - CL_SmokeAndFlash - ================= - */ - static void SmokeAndFlash(float[] 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 - ================= - */ - static void ParseParticles() { - int color, count; - float[] pos = new float[3]; - float[] dir = new float[3]; - - 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 - ================= - */ - static int ParseBeam(model_t model) { - int ent; - float[] start = new float[3]; - float[] end = new float[3]; - 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 - b = cl_beams; - for (i = 0; i < MAX_BEAMS; i++) - if (b[i].entity == ent) { - b[i].entity = ent; - b[i].model = model; - b[i].endtime = cl.time + 200; - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorClear(b[i].offset); - return ent; - } - - // find a free beam - b = cl_beams; - for (i = 0; i < MAX_BEAMS; i++) { - if (b[i].model == null || b[i].endtime < cl.time) { - b[i].entity = ent; - b[i].model = model; - b[i].endtime = cl.time + 200; - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorClear(b[i].offset); - return ent; - } - } - Com.Printf("beam list overflow!\n"); - return ent; - } - - /* - ================= - CL_ParseBeam2 - ================= - */ - static int ParseBeam2(model_t model) { - int ent; - float[] start = new float[3]; - float[] end = new float[3]; - float[] offset = new float[3]; - 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 - b = cl_beams; - for (i = 0; i < MAX_BEAMS; i++) - if (b[i].entity == ent) { - b[i].entity = ent; - b[i].model = model; - b[i].endtime = cl.time + 200; - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorCopy(offset, b[i].offset); - return ent; - } - - // find a free beam - b = cl_beams; - for (i = 0; i < MAX_BEAMS; i++) { - if (b[i].model == null || b[i].endtime < cl.time) { - b[i].entity = ent; - b[i].model = model; - b[i].endtime = cl.time + 200; - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorCopy(offset, b[i].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 - ================= - */ - static int ParsePlayerBeam(model_t model) { - int ent; - float[] start = new float[3]; - float[] end = new float[3]; - float[] offset = new float[3]; - 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.. - b = cl_playerbeams; - for (i = 0; i < MAX_BEAMS; i++) { - if (b[i].entity == ent) { - b[i].entity = ent; - b[i].model = model; - b[i].endtime = cl.time + 200; - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorCopy(offset, b[i].offset); - return ent; - } - } - - // find a free beam - b = cl_playerbeams; - for (i = 0; i < MAX_BEAMS; i++) { - if (b[i].model == null || b[i].endtime < cl.time) { - b[i].entity = ent; - b[i].model = model; - b[i].endtime = cl.time + 100; // PMM - this needs to be 100 to prevent multiple heatbeams - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorCopy(offset, b[i].offset); - return ent; - } - } - Com.Printf("beam list overflow!\n"); - return ent; - } -// rogue - - /* - ================= - CL_ParseLightning - ================= - */ - static int ParseLightning(model_t model) { - int srcEnt, destEnt; - float[] start = new float[3]; - float[] end = new float[3]; - 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 - b = cl_beams; - for (i = 0; i < MAX_BEAMS; i++) - if (b[i].entity == srcEnt && b[i].dest_entity == destEnt) { - // Com_Printf("%d: OVERRIDE %d . %d\n", cl.time, srcEnt, destEnt); - b[i].entity = srcEnt; - b[i].dest_entity = destEnt; - b[i].model = model; - b[i].endtime = cl.time + 200; - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorClear(b[i].offset); - return srcEnt; - } - - // find a free beam - b = cl_beams; - for (i = 0; i < MAX_BEAMS; i++) { - if (b[i].model == null || b[i].endtime < cl.time) { - // Com_Printf("%d: NORMAL %d . %d\n", cl.time, srcEnt, destEnt); - b[i].entity = srcEnt; - b[i].dest_entity = destEnt; - b[i].model = model; - b[i].endtime = cl.time + 200; - VectorCopy(start, b[i].start); - VectorCopy(end, b[i].end); - VectorClear(b[i].offset); - return srcEnt; - } - } - Com.Printf("beam list overflow!\n"); - return srcEnt; - } - - /* - ================= - CL_ParseLaser - ================= - */ - static void ParseLaser(int colors) { - float[] start = new float[3]; - float[] end = new float[3]; - laser_t[] l; - int i; - - MSG.ReadPos(net_message, start); - MSG.ReadPos(net_message, end); - - l = cl_lasers; - for (i = 0; i < MAX_LASERS; i++) { - if (l[i].endtime < cl.time) { - l[i].ent.flags = RF_TRANSLUCENT | RF_BEAM; - VectorCopy(start, l[i].ent.origin); - VectorCopy(end, l[i].ent.oldorigin); - l[i].ent.alpha = 0.30f; - l[i].ent.skinnum = (colors >> ((rand() % 4) * 8)) & 0xff; - l[i].ent.model = null; - l[i].ent.frame = 4; - l[i].endtime = cl.time + 100; - return; - } - } - } - -// ============= -// ROGUE - static void ParseSteam() { - float[] pos = new float[3]; - float[] dir = new float[3]; - int id, i; - int r; - int cnt; - int color; - int magnitude; - cl_sustain_t[] s; - cl_sustain_t 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; - s = cl_sustains; - for (i = 0; i < MAX_SUSTAINS; i++) { - if (s[i].id == 0) { - free_sustain = s[i]; - break; - } - } - if (free_sustain != null) { - s[i].id = id; - s[i].count = MSG.ReadByte(net_message); - MSG.ReadPos(net_message, s[i].org); - MSG.ReadDir(net_message, s[i].dir); - r = MSG.ReadByte(net_message); - s[i].color = r & 0xff; - s[i].magnitude = MSG.ReadShort(net_message); - s[i].endtime = cl.time + MSG.ReadLong(net_message); - s[i].think = new cl_sustain_t.ThinkAdapter() { - void think(cl_sustain_t self) { - CL.ParticleSteamEffect2(self); - } - }; - s[i].thinkinterval = 100; - s[i].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); - } - } - - static void ParseWidow() { - float[] pos = new float[3]; - int id, i; - cl_sustain_t[] s; - cl_sustain_t free_sustain; - - id = MSG.ReadShort(net_message); - - free_sustain = null; - s = cl_sustains; - for (i = 0; i < MAX_SUSTAINS; i++) { - if (s[i].id == 0) { - free_sustain = s[i]; - break; - } - } - if (free_sustain != null) { - s[i].id = id; - MSG.ReadPos(net_message, s[i].org); - s[i].endtime = cl.time + 2100; - s[i].think = new cl_sustain_t.ThinkAdapter() { - void think(cl_sustain_t self) { - CL.Widowbeamout(self); - } - }; - s[i].thinkinterval = 1; - s[i].nextthink = cl.time; - } else // no free sustains - { - // FIXME - read the stuff anyway - MSG.ReadPos(net_message, pos); - } - } - - static void ParseNuke() { - float[] pos = new float[3]; - int i; - cl_sustain_t[] s; - cl_sustain_t free_sustain; - - free_sustain = null; - s = cl_sustains; - for (i = 0; i < MAX_SUSTAINS; i++) { - if (s[i].id == 0) { - free_sustain = s[i]; - break; - } - } - if (free_sustain != null) { - s[i].id = 21000; - MSG.ReadPos(net_message, s[i].org); - s[i].endtime = cl.time + 1000; - s[i].think = new cl_sustain_t.ThinkAdapter() { - void think(cl_sustain_t self) { - CL.Nukeblast(self); - } - }; - s[i].thinkinterval = 1; - s[i].nextthink = cl.time; - } else // no free sustains - { - // FIXME - read the stuff anyway - MSG.ReadPos(net_message, pos); - } - } - -// ROGUE -// ============= - - - /* - ================= - CL_ParseTEnt - ================= - */ - static int[] splash_color = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8}; - static void ParseTEnt() { - int type; - float[] pos = new float[3]; - float[] pos2 = new float[3]; - float[] dir = new float[3]; - 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] = (float) (Math.acos(dir[2]) / Math.PI * 180); - // PMM - fixed to correct for pitch of 0 - if (dir[0] != 0.0f) - ex.ent.angles[1] = (float) (Math.atan2(dir[1], dir[0]) / Math.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.0f; - ex.lightcolor[1] = 0.5f; - ex.lightcolor[2] = 0.5f; - 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.0f; - ex.lightcolor[1] = 0.5f; - ex.lightcolor[2] = 0.5f; - ex.ent.angles[1] = rand() % 360; - ex.ent.model = cl_mod_explo4; - if (Globals.rnd.nextFloat() < 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.0f; - ex.lightcolor[1] = 0.5f; - ex.lightcolor[2] = 0.5f; - 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 (Globals.rnd.nextFloat() < 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.0f; - ex.lightcolor[1] = 1.0f; - ex.lightcolor[2] = 0.0f; - ex.ent.model = cl_mod_bfg_explo; - ex.ent.flags |= RF_TRANSLUCENT; - ex.ent.alpha = 0.30f; - 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.1f; - ex.light = 100 + (rand() % 75); - ex.lightcolor[0] = 1.0f; - ex.lightcolor[1] = 1.0f; - ex.lightcolor[2] = 0.3f; - 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] = (float) (Math.acos(dir[2]) / Math.PI * 180); - // PMM - fixed to correct for pitch of 0 - if (dir[0] != 0.0f) - ex.ent.angles[1] = (float) (Math.atan2(dir[1], dir[0]) / Math.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.19f; - ex.lightcolor[1] = 0.41f; - ex.lightcolor[2] = 0.75f; - } - 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.0f; - ex.lightcolor[1] = 0.5f; - ex.lightcolor[2] = 0.5f; - ex.ent.angles[1] = rand() % 360; - ex.ent.model = cl_mod_explo4; - if (Globals.rnd.nextFloat() < 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 : - 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 - ================= - */ - static void AddBeams() { - int i, j; - beam_t[] b; - float[] dist = new float[3]; - float[] org = new float[3]; - float d; - entity_t ent = new entity_t(); - float yaw, pitch; - float forward; - float len, steps; - float model_length; - - // update beams - b = cl_beams; - for (i = 0; i < MAX_BEAMS; i++) { - if (b[i].model == null || b[i].endtime < cl.time) - continue; - - // if coming from the player, update the start position - if (b[i].entity == cl.playernum + 1) // entity 0 is the world - { - VectorCopy(cl.refdef.vieworg, b[i].start); - b[i].start[2] -= 22; // adjust for view height - } - VectorAdd(b[i].start, b[i].offset, org); - - // calculate pitch and yaw - VectorSubtract(b[i].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] != 0.0f) - yaw = (float) (Math.atan2(dist[1], dist[0]) * 180 / Math.PI); - else if (dist[1] > 0) - yaw = 90; - else - yaw = 270; - if (yaw < 0) - yaw += 360; - - forward = (float)Math.sqrt(dist[0] * dist[0] + dist[1] * dist[1]); - pitch = (float) (Math.atan2(dist[2], forward) * -180.0 / Math.PI); - if (pitch < 0) - pitch += 360.0; - } - - // add new entities for the beams - d = VectorNormalize(dist); - - //memset (&ent, 0, sizeof(ent)); - ent = new entity_t(); - if (b[i].model == cl_mod_lightning) { - model_length = 35.0f; - d -= 20.0; // correction so it doesn't end in middle of tesla - } else { - model_length = 30.0f; - } - steps = (float)Math.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[i].model == cl_mod_lightning) && (d <= model_length)) { - // Com_Printf ("special case\n"); - VectorCopy(b[i].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[i].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[i].model; - if (b[i].model == cl_mod_lightning) { - ent.flags = RF_FULLBRIGHT; - ent.angles[0] = -pitch; - ent.angles[1] = yaw + 180.0f; - 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[i].entity, b[i].dest_entity); - V.AddEntity(ent); - - for (j = 0; j < 3; j++) - org[j] += dist[j] * len; - d -= model_length; - } - } - } - - //extern cvar_t *hand; - - /* - ================= - ROGUE - draw player locked beams - CL_AddPlayerBeams - ================= - */ - static void AddPlayerBeams() { - float[] dist = new float[3]; - float[] org = new float[3]; - float d; - entity_t ent = new entity_t(); - float yaw, pitch; - float forward; - float len, steps; - int framenum = 0; - float model_length; - - float hand_multiplier; - frame_t oldframe; - player_state_t ps, ops; - - // PMM - if (hand != null) { - 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 - beam_t[] b = cl_playerbeams; - float[] f = new float[3]; - float[] u = new float[3]; - float[] r = new float[3]; - for (int i = 0; i < MAX_BEAMS; i++) { - - if (b[i].model == null || b[i].endtime < cl.time) - continue; - - if (cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam)) { - - // if coming from the player, update the start position - if (b[i].entity == cl.playernum + 1) // entity 0 is the world - { - // set up gun position - // code straight out of CL_AddViewWeapon - ps = cl.frame.playerstate; - int 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[i].start[j] = - cl.refdef.vieworg[j] - + ops.gunoffset[j] - + cl.lerpfrac * (ps.gunoffset[j] - ops.gunoffset[j]); - } - VectorMA(b[i].start, (hand_multiplier * b[i].offset[0]), cl.v_right, org); - VectorMA(org, b[i].offset[1], cl.v_forward, org); - VectorMA(org, b[i].offset[2], cl.v_up, org); - if ((hand != null) && (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[i].start, org); - } else { - // if coming from the player, update the start position - if (b[i].entity == cl.playernum + 1) // entity 0 is the world - { - VectorCopy(cl.refdef.vieworg, b[i].start); - b[i].start[2] -= 22; // adjust for view height - } - VectorAdd(b[i].start, b[i].offset, org); - } - - // calculate pitch and yaw - VectorSubtract(b[i].end, org, dist); - - // PMM - if (cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam) && (b[i].entity == cl.playernum + 1)) { - - len = VectorLength(dist); - VectorScale(f, len, dist); - VectorMA(dist, (hand_multiplier * b[i].offset[0]), r, dist); - VectorMA(dist, b[i].offset[1], f, dist); - VectorMA(dist, b[i].offset[2], u, dist); - if ((hand != null) && (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] != 0.0f) - yaw = (float) (Math.atan2(dist[1], dist[0]) * 180 / Math.PI); - else if (dist[1] > 0) - yaw = 90; - else - yaw = 270; - if (yaw < 0) - yaw += 360; - - forward = (float)Math.sqrt(dist[0] * dist[0] + dist[1] * dist[1]); - pitch = (float) (Math.atan2(dist[2], forward) * -180.0 / Math.PI); - if (pitch < 0) - pitch += 360.0; - } - - if (cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam)) { - if (b[i].entity != cl.playernum + 1) { - framenum = 2; - // Com_Printf ("Third person\n"); - ent.angles[0] = -pitch; - ent.angles[1] = yaw + 180.0f; - ent.angles[2] = 0; - // Com_Printf ("%f %f - %f %f %f\n", -pitch, yaw+180.0, b[i].offset[0], b[i].offset[1], b[i].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[i].offset, vec3_origin) == 0) { - VectorMA(org, - (b[i].offset[0]) + 1, r, org); - VectorMA(org, - (b[i].offset[1]), f, org); - VectorMA(org, - (b[i].offset[2]) - 10, u, org); - } else { - // if it's a monster, do the particle effect - CL.MonsterPlasma_Shell(b[i].start); - } - } else { - framenum = 1; - } - } - - // if it's the heatbeam, draw the particle effect - if ((cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam) && (b[i].entity == cl.playernum + 1))) { - CL.Heatbeam(org, dist); - } - - // add new entities for the beams - d = VectorNormalize(dist); - - //memset (&ent, 0, sizeof(ent)); - //ent = new entity_t(); - // this is not required. hoz - - if (b[i].model == cl_mod_heatbeam) { - model_length = 32.0f; - } else if (b[i].model == cl_mod_lightning) { - model_length = 35.0f; - d -= 20.0; // correction so it doesn't end in middle of tesla - } else { - model_length = 30.0f; - } - steps = (float)Math.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[i].model == cl_mod_lightning) && (d <= model_length)) { - // Com_Printf ("special case\n"); - VectorCopy(b[i].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[i].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[i].model; - if (cl_mod_heatbeam != null && (b[i].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.0f; - ent.angles[2] = (cl.time) % 360; - // ent.angles[2] = rand()%360; - ent.frame = framenum; - } else if (b[i].model == cl_mod_lightning) { - ent.flags = RF_FULLBRIGHT; - ent.angles[0] = -pitch; - ent.angles[1] = yaw + 180.0f; - 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[i].entity, b[i].dest_entity); - V.AddEntity(ent); - - for (int j = 0; j < 3; j++) - org[j] += dist[j] * len; - d -= model_length; - } - } - } - - /* - ================= - CL_AddExplosions - ================= - */ - static void AddExplosions() { - entity_t ent; - int i; - explosion_t[] ex; - float frac; - int f; - - //memset (&ent, 0, sizeof(ent)); Pointer! - ent = null; - ex = cl_explosions; - for (i = 0; i < MAX_EXPLOSIONS; i++) { - if (ex[i].type == ex_free) - continue; - frac = (cl.time - ex[i].start) / 100.0f; - f = (int)Math.floor(frac); - - ent = ex[i].ent; - - switch (ex[i].type) { - case ex_mflash : - if (f >= ex[i].frames - 1) - ex[i].type = ex_free; - break; - case ex_misc : - if (f >= ex[i].frames - 1) { - ex[i].type = ex_free; - break; - } - ent.alpha = 1.0f - frac / (ex[i].frames - 1); - break; - case ex_flash : - if (f >= 1) { - ex[i].type = ex_free; - break; - } - ent.alpha = 1.0f; - break; - case ex_poly : - if (f >= ex[i].frames - 1) { - ex[i].type = ex_free; - break; - } - - ent.alpha = (16.0f - (float)f) / 16.0f; - - 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[i].frames - 1) { - ex[i].type = ex_free; - break; - } - - ent.alpha = (5.0f - (float)f) / 5.0f; - ent.skinnum = 0; - ent.flags |= RF_TRANSLUCENT; - break; - } - - if (ex[i].type == ex_free) - continue; - if (ex[i].light != 0.0f) { - V.AddLight( - ent.origin, - ex[i].light * ent.alpha, - ex[i].lightcolor[0], - ex[i].lightcolor[1], - ex[i].lightcolor[2]); - } - - VectorCopy(ent.origin, ent.oldorigin); - - if (f < 0) - f = 0; - ent.frame = ex[i].baseframe + f + 1; - ent.oldframe = ex[i].baseframe + f; - ent.backlerp = 1.0f - cl.lerpfrac; - - V.AddEntity(ent); - } - } - - /* - ================= - CL_AddLasers - ================= - */ - static void AddLasers() { - laser_t[] l; - int i; - - l = cl_lasers; - for (i = 0; i < MAX_LASERS; i++) { - if (l[i].endtime >= cl.time) - V.AddEntity(l[i].ent); - } - } - - /* PMM - CL_Sustains */ - static void ProcessSustain() { - cl_sustain_t[] s; - int i; - - s = cl_sustains; - for (i = 0; i < MAX_SUSTAINS; i++) { - if (s[i].id != 0) - if ((s[i].endtime >= cl.time) && (cl.time >= s[i].nextthink)) { - s[i].think.think(s[i]); - } else if (s[i].endtime < cl.time) - s[i].id = 0; - } - } - - /* - ================= - CL_AddTEnts - ================= - */ - static void AddTEnts() { - CL.AddBeams(); - // PMM - draw plasma beams - CL.AddPlayerBeams(); - CL.AddExplosions(); - CL.AddLasers(); - // PMM - set up sustain - CL.ProcessSustain(); - } -} +public class CL_tent { + + static class explosion_t { + int type; + + entity_t ent = new entity_t(); + + int frames; + + float light; + + float[] lightcolor = new float[3]; + + float start; + + int baseframe; + + void clear() { + lightcolor[0] = lightcolor[1] = lightcolor[2] = light = start = type = frames = baseframe = 0; + ent = new entity_t(); + } + } + + static final int MAX_EXPLOSIONS = 32; + + static explosion_t[] cl_explosions = new explosion_t[MAX_EXPLOSIONS]; + + static final int MAX_BEAMS = 32; + + static beam_t[] cl_beams = new beam_t[MAX_BEAMS]; + + // PMM - added this for player-linked beams. Currently only used by the + // plasma beam + static beam_t[] cl_playerbeams = new beam_t[MAX_BEAMS]; + + static final int MAX_LASERS = 32; + + static laser_t[] cl_lasers = new laser_t[MAX_LASERS]; + + // ROGUE + static final int MAX_SUSTAINS = 32; + + static cl_sustain_t[] cl_sustains = new cl_sustain_t[MAX_SUSTAINS]; + + static class beam_t { + int entity; + + int dest_entity; + + model_t model; + + int endtime; + + float[] offset = new float[3]; + + float[] start = new float[3]; + + float[] end = new float[3]; + + void clear() { + offset[0] = offset[1] = offset[2] = start[0] = start[1] = start[2] = end[0] = end[1] = end[2] = entity = dest_entity = endtime = 0; + model = null; + } + } + + static { + for (int i = 0; i < cl_explosions.length; i++) + cl_explosions[i] = new explosion_t(); + } + static { + for (int i = 0; i < cl_beams.length; i++) + cl_beams[i] = new beam_t(); + for (int i = 0; i < cl_playerbeams.length; i++) + cl_playerbeams[i] = new beam_t(); + } + + static class laser_t { + entity_t ent = new entity_t(); + + int endtime; + + void clear() { + endtime = 0; + ent = new entity_t(); + } + } + + static { + for (int i = 0; i < cl_lasers.length; i++) + cl_lasers[i] = new laser_t(); + } + + static { + for (int i = 0; i < cl_sustains.length; i++) + cl_sustains[i] = new cl_sustain_t(); + } + + static final int ex_free = 0; + + static final int ex_explosion = 1; + + static final int ex_misc = 2; + + static final int ex_flash = 3; + + static final int ex_mflash = 4; + + static final int ex_poly = 5; + + static final int ex_poly2 = 6; + + // ROGUE + + // all are references; + static sfx_t cl_sfx_ric1; + + static sfx_t cl_sfx_ric2; + + static sfx_t cl_sfx_ric3; + + static sfx_t cl_sfx_lashit; + + static sfx_t cl_sfx_spark5; + + static sfx_t cl_sfx_spark6; + + static sfx_t cl_sfx_spark7; + + static sfx_t cl_sfx_railg; + + static sfx_t cl_sfx_rockexp; + + static sfx_t cl_sfx_grenexp; + + static sfx_t cl_sfx_watrexp; + + // RAFAEL + static sfx_t cl_sfx_plasexp; + + static sfx_t cl_sfx_footsteps[] = new sfx_t[4]; + + static model_t cl_mod_explode; + + static model_t cl_mod_smoke; + + static model_t cl_mod_flash; + + static model_t cl_mod_parasite_segment; + + static model_t cl_mod_grapple_cable; + + static model_t cl_mod_parasite_tip; + + static model_t cl_mod_explo4; + + static model_t cl_mod_bfg_explo; + + static model_t cl_mod_powerscreen; + + // RAFAEL + static model_t cl_mod_plasmaexplo; + + // ROGUE + static sfx_t cl_sfx_lightning; + + static sfx_t cl_sfx_disrexp; + + static model_t cl_mod_lightning; + + static model_t cl_mod_heatbeam; + + static model_t cl_mod_monster_heatbeam; + + static model_t cl_mod_explo4_big; + + // ROGUE + /* + * ================= CL_RegisterTEntSounds ================= + */ + static void RegisterTEntSounds() { + int i; + String name; + + // 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); + name = "player/step" + (i + 1) + ".wav"; + 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 ================= + */ + static void RegisterTEntModels() { + cl_mod_explode = Globals.re + .RegisterModel("models/objects/explode/tris.md2"); + cl_mod_smoke = Globals.re + .RegisterModel("models/objects/smoke/tris.md2"); + cl_mod_flash = Globals.re + .RegisterModel("models/objects/flash/tris.md2"); + cl_mod_parasite_segment = Globals.re + .RegisterModel("models/monsters/parasite/segment/tris.md2"); + cl_mod_grapple_cable = Globals.re + .RegisterModel("models/ctf/segment/tris.md2"); + cl_mod_parasite_tip = Globals.re + .RegisterModel("models/monsters/parasite/tip/tris.md2"); + cl_mod_explo4 = Globals.re + .RegisterModel("models/objects/r_explode/tris.md2"); + cl_mod_bfg_explo = Globals.re.RegisterModel("sprites/s_bfg2.sp2"); + cl_mod_powerscreen = Globals.re + .RegisterModel("models/items/armor/effect/tris.md2"); + + Globals.re.RegisterModel("models/objects/laser/tris.md2"); + Globals.re.RegisterModel("models/objects/grenade2/tris.md2"); + Globals.re.RegisterModel("models/weapons/v_machn/tris.md2"); + Globals.re.RegisterModel("models/weapons/v_handgr/tris.md2"); + Globals.re.RegisterModel("models/weapons/v_shotg2/tris.md2"); + Globals.re.RegisterModel("models/objects/gibs/bone/tris.md2"); + Globals.re.RegisterModel("models/objects/gibs/sm_meat/tris.md2"); + Globals.re.RegisterModel("models/objects/gibs/bone2/tris.md2"); + // RAFAEL + // re.RegisterModel ("models/objects/blaser/tris.md2"); + + Globals.re.RegisterPic("w_machinegun"); + Globals.re.RegisterPic("a_bullets"); + Globals.re.RegisterPic("i_health"); + Globals.re.RegisterPic("a_grenades"); + + // ROGUE + cl_mod_explo4_big = Globals.re + .RegisterModel("models/objects/r_explode2/tris.md2"); + cl_mod_lightning = Globals.re + .RegisterModel("models/proj/lightning/tris.md2"); + cl_mod_heatbeam = Globals.re.RegisterModel("models/proj/beam/tris.md2"); + cl_mod_monster_heatbeam = Globals.re + .RegisterModel("models/proj/widowbeam/tris.md2"); + // ROGUE + } + + /* + * ================= CL_ClearTEnts ================= + */ + static void ClearTEnts() { + // memset (cl_beams, 0, sizeof(cl_beams)); + for (int i = 0; i < cl_beams.length; i++) + cl_beams[i].clear(); + // memset (cl_explosions, 0, sizeof(cl_explosions)); + for (int i = 0; i < cl_explosions.length; i++) + cl_explosions[i].clear(); + // memset (cl_lasers, 0, sizeof(cl_lasers)); + for (int i = 0; i < cl_lasers.length; i++) + cl_lasers[i].clear(); + // + // ROGUE + // memset (cl_playerbeams, 0, sizeof(cl_playerbeams)); + for (int i = 0; i < cl_playerbeams.length; i++) + cl_playerbeams[i].clear(); + // memset (cl_sustains, 0, sizeof(cl_sustains)); + for (int i = 0; i < cl_sustains.length; i++) + cl_sustains[i].clear(); + // ROGUE + } + + /* + * ================= CL_AllocExplosion ================= + */ + static explosion_t AllocExplosion() { + 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])); + cl_explosions[i].clear(); + return cl_explosions[i]; + } + } + // find the oldest explosion + time = Globals.cl.time; + index = 0; + + for (i = 0; i < MAX_EXPLOSIONS; i++) + if (cl_explosions[i].start < time) { + time = (int) cl_explosions[i].start; + index = i; + } + //memset (&cl_explosions[index], 0, sizeof (cl_explosions[index])); + cl_explosions[index].clear(); + return cl_explosions[index]; + } + + /* + * ================= CL_SmokeAndFlash ================= + */ + static void SmokeAndFlash(float[] origin) { + explosion_t ex; + + ex = AllocExplosion(); + Math3D.VectorCopy(origin, ex.ent.origin); + ex.type = ex_misc; + ex.frames = 4; + ex.ent.flags = Defines.RF_TRANSLUCENT; + ex.start = Globals.cl.frame.servertime - 100; + ex.ent.model = cl_mod_smoke; + + ex = AllocExplosion(); + Math3D.VectorCopy(origin, ex.ent.origin); + ex.type = ex_flash; + ex.ent.flags = Defines.RF_FULLBRIGHT; + ex.frames = 2; + ex.start = Globals.cl.frame.servertime - 100; + ex.ent.model = cl_mod_flash; + } + + /* + * ================= CL_ParseParticles ================= + */ + static void ParseParticles() { + int color, count; + float[] pos = new float[3]; + float[] dir = new float[3]; + + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + + color = MSG.ReadByte(Globals.net_message); + + count = MSG.ReadByte(Globals.net_message); + + CL_fx.ParticleEffect(pos, dir, color, count); + } + + /* + * ================= CL_ParseBeam ================= + */ + static int ParseBeam(model_t model) { + int ent; + float[] start = new float[3]; + float[] end = new float[3]; + beam_t[] b; + int i; + + ent = MSG.ReadShort(Globals.net_message); + + MSG.ReadPos(Globals.net_message, start); + MSG.ReadPos(Globals.net_message, end); + + // override any beam with the same entity + b = cl_beams; + for (i = 0; i < MAX_BEAMS; i++) + if (b[i].entity == ent) { + b[i].entity = ent; + b[i].model = model; + b[i].endtime = Globals.cl.time + 200; + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorClear(b[i].offset); + return ent; + } + + // find a free beam + b = cl_beams; + for (i = 0; i < MAX_BEAMS; i++) { + if (b[i].model == null || b[i].endtime < Globals.cl.time) { + b[i].entity = ent; + b[i].model = model; + b[i].endtime = Globals.cl.time + 200; + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorClear(b[i].offset); + return ent; + } + } + Com.Printf("beam list overflow!\n"); + return ent; + } + + /* + * ================= CL_ParseBeam2 ================= + */ + static int ParseBeam2(model_t model) { + int ent; + float[] start = new float[3]; + float[] end = new float[3]; + float[] offset = new float[3]; + beam_t[] b; + int i; + + ent = MSG.ReadShort(Globals.net_message); + + MSG.ReadPos(Globals.net_message, start); + MSG.ReadPos(Globals.net_message, end); + MSG.ReadPos(Globals.net_message, offset); + + // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]); + + // override any beam with the same entity + b = cl_beams; + for (i = 0; i < MAX_BEAMS; i++) + if (b[i].entity == ent) { + b[i].entity = ent; + b[i].model = model; + b[i].endtime = Globals.cl.time + 200; + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorCopy(offset, b[i].offset); + return ent; + } + + // find a free beam + b = cl_beams; + for (i = 0; i < MAX_BEAMS; i++) { + if (b[i].model == null || b[i].endtime < Globals.cl.time) { + b[i].entity = ent; + b[i].model = model; + b[i].endtime = Globals.cl.time + 200; + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorCopy(offset, b[i].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 ================= + */ + static int ParsePlayerBeam(model_t model) { + int ent; + float[] start = new float[3]; + float[] end = new float[3]; + float[] offset = new float[3]; + beam_t[] b; + int i; + + ent = MSG.ReadShort(Globals.net_message); + + MSG.ReadPos(Globals.net_message, start); + MSG.ReadPos(Globals.net_message, end); + // PMM - network optimization + if (model == cl_mod_heatbeam) + Math3D.VectorSet(offset, 2, 7, -3); + else if (model == cl_mod_monster_heatbeam) { + model = cl_mod_heatbeam; + Math3D.VectorSet(offset, 0, 0, 0); + } else + MSG.ReadPos(Globals.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.. + b = cl_playerbeams; + for (i = 0; i < MAX_BEAMS; i++) { + if (b[i].entity == ent) { + b[i].entity = ent; + b[i].model = model; + b[i].endtime = Globals.cl.time + 200; + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorCopy(offset, b[i].offset); + return ent; + } + } + + // find a free beam + b = cl_playerbeams; + for (i = 0; i < MAX_BEAMS; i++) { + if (b[i].model == null || b[i].endtime < Globals.cl.time) { + b[i].entity = ent; + b[i].model = model; + b[i].endtime = Globals.cl.time + 100; // PMM - this needs to be + // 100 to prevent multiple + // heatbeams + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorCopy(offset, b[i].offset); + return ent; + } + } + Com.Printf("beam list overflow!\n"); + return ent; + } + + // rogue + + /* + * ================= CL_ParseLightning ================= + */ + static int ParseLightning(model_t model) { + int srcEnt, destEnt; + float[] start = new float[3]; + float[] end = new float[3]; + beam_t[] b; + int i; + + srcEnt = MSG.ReadShort(Globals.net_message); + destEnt = MSG.ReadShort(Globals.net_message); + + MSG.ReadPos(Globals.net_message, start); + MSG.ReadPos(Globals.net_message, end); + + // override any beam with the same source AND destination entities + b = cl_beams; + for (i = 0; i < MAX_BEAMS; i++) + if (b[i].entity == srcEnt && b[i].dest_entity == destEnt) { + // Com_Printf("%d: OVERRIDE %d . %d\n", cl.time, srcEnt, + // destEnt); + b[i].entity = srcEnt; + b[i].dest_entity = destEnt; + b[i].model = model; + b[i].endtime = Globals.cl.time + 200; + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorClear(b[i].offset); + return srcEnt; + } + + // find a free beam + b = cl_beams; + for (i = 0; i < MAX_BEAMS; i++) { + if (b[i].model == null || b[i].endtime < Globals.cl.time) { + // Com_Printf("%d: NORMAL %d . %d\n", cl.time, srcEnt, destEnt); + b[i].entity = srcEnt; + b[i].dest_entity = destEnt; + b[i].model = model; + b[i].endtime = Globals.cl.time + 200; + Math3D.VectorCopy(start, b[i].start); + Math3D.VectorCopy(end, b[i].end); + Math3D.VectorClear(b[i].offset); + return srcEnt; + } + } + Com.Printf("beam list overflow!\n"); + return srcEnt; + } + + /* + * ================= CL_ParseLaser ================= + */ + static void ParseLaser(int colors) { + float[] start = new float[3]; + float[] end = new float[3]; + laser_t[] l; + int i; + + MSG.ReadPos(Globals.net_message, start); + MSG.ReadPos(Globals.net_message, end); + + l = cl_lasers; + for (i = 0; i < MAX_LASERS; i++) { + if (l[i].endtime < Globals.cl.time) { + l[i].ent.flags = Defines.RF_TRANSLUCENT | Defines.RF_BEAM; + Math3D.VectorCopy(start, l[i].ent.origin); + Math3D.VectorCopy(end, l[i].ent.oldorigin); + l[i].ent.alpha = 0.30f; + l[i].ent.skinnum = (colors >> ((Lib.rand() % 4) * 8)) & 0xff; + l[i].ent.model = null; + l[i].ent.frame = 4; + l[i].endtime = Globals.cl.time + 100; + return; + } + } + } + + // ============= + // ROGUE + static void ParseSteam() { + float[] pos = new float[3]; + float[] dir = new float[3]; + int id, i; + int r; + int cnt; + int color; + int magnitude; + cl_sustain_t[] s; + cl_sustain_t free_sustain; + + id = MSG.ReadShort(Globals.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; + s = cl_sustains; + for (i = 0; i < MAX_SUSTAINS; i++) { + if (s[i].id == 0) { + free_sustain = s[i]; + break; + } + } + if (free_sustain != null) { + s[i].id = id; + s[i].count = MSG.ReadByte(Globals.net_message); + MSG.ReadPos(Globals.net_message, s[i].org); + MSG.ReadDir(Globals.net_message, s[i].dir); + r = MSG.ReadByte(Globals.net_message); + s[i].color = r & 0xff; + s[i].magnitude = MSG.ReadShort(Globals.net_message); + s[i].endtime = Globals.cl.time + + MSG.ReadLong(Globals.net_message); + s[i].think = new cl_sustain_t.ThinkAdapter() { + void think(cl_sustain_t self) { + CL_newfx.ParticleSteamEffect2(self); + } + }; + s[i].thinkinterval = 100; + s[i].nextthink = Globals.cl.time; + } else { + // Com_Printf ("No free sustains!\n"); + // FIXME - read the stuff anyway + cnt = MSG.ReadByte(Globals.net_message); + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + r = MSG.ReadByte(Globals.net_message); + magnitude = MSG.ReadShort(Globals.net_message); + magnitude = MSG.ReadLong(Globals.net_message); // really + // interval + } + } else // instant + { + cnt = MSG.ReadByte(Globals.net_message); + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + r = MSG.ReadByte(Globals.net_message); + magnitude = MSG.ReadShort(Globals.net_message); + color = r & 0xff; + CL_newfx.ParticleSteamEffect(pos, dir, color, cnt, magnitude); + // S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); + } + } + + static void ParseWidow() { + float[] pos = new float[3]; + int id, i; + cl_sustain_t[] s; + cl_sustain_t free_sustain; + + id = MSG.ReadShort(Globals.net_message); + + free_sustain = null; + s = cl_sustains; + for (i = 0; i < MAX_SUSTAINS; i++) { + if (s[i].id == 0) { + free_sustain = s[i]; + break; + } + } + if (free_sustain != null) { + s[i].id = id; + MSG.ReadPos(Globals.net_message, s[i].org); + s[i].endtime = Globals.cl.time + 2100; + s[i].think = new cl_sustain_t.ThinkAdapter() { + void think(cl_sustain_t self) { + CL_newfx.Widowbeamout(self); + } + }; + s[i].thinkinterval = 1; + s[i].nextthink = Globals.cl.time; + } else // no free sustains + { + // FIXME - read the stuff anyway + MSG.ReadPos(Globals.net_message, pos); + } + } + + static void ParseNuke() { + float[] pos = new float[3]; + int i; + cl_sustain_t[] s; + cl_sustain_t free_sustain; + + free_sustain = null; + s = cl_sustains; + for (i = 0; i < MAX_SUSTAINS; i++) { + if (s[i].id == 0) { + free_sustain = s[i]; + break; + } + } + if (free_sustain != null) { + s[i].id = 21000; + MSG.ReadPos(Globals.net_message, s[i].org); + s[i].endtime = Globals.cl.time + 1000; + s[i].think = new cl_sustain_t.ThinkAdapter() { + void think(cl_sustain_t self) { + CL_newfx.Nukeblast(self); + } + }; + s[i].thinkinterval = 1; + s[i].nextthink = Globals.cl.time; + } else // no free sustains + { + // FIXME - read the stuff anyway + MSG.ReadPos(Globals.net_message, pos); + } + } + + // ROGUE + // ============= + + /* + * ================= CL_ParseTEnt ================= + */ + static int[] splash_color = { 0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8 }; + + static void ParseTEnt() { + int type; + float[] pos = new float[3]; + float[] pos2 = new float[3]; + float[] dir = new float[3]; + explosion_t ex; + int cnt; + int color; + int r; + int ent; + int magnitude; + + type = MSG.ReadByte(Globals.net_message); + + switch (type) { + case Defines.TE_BLOOD: // bullet hitting flesh + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + CL_fx.ParticleEffect(pos, dir, 0xe8, 60); + break; + + case Defines.TE_GUNSHOT: // bullet hitting wall + case Defines.TE_SPARKS: + case Defines.TE_BULLET_SPARKS: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + if (type == Defines.TE_GUNSHOT) + CL_fx.ParticleEffect(pos, dir, 0, 40); + else + CL_fx.ParticleEffect(pos, dir, 0xe0, 6); + + if (type != Defines.TE_SPARKS) { + SmokeAndFlash(pos); + + // impact sound + cnt = Lib.rand() & 15; + if (cnt == 1) + S.StartSound(pos, 0, 0, cl_sfx_ric1, 1, Defines.ATTN_NORM, + 0); + else if (cnt == 2) + S.StartSound(pos, 0, 0, cl_sfx_ric2, 1, Defines.ATTN_NORM, + 0); + else if (cnt == 3) + S.StartSound(pos, 0, 0, cl_sfx_ric3, 1, Defines.ATTN_NORM, + 0); + } + + break; + + case Defines.TE_SCREEN_SPARKS: + case Defines.TE_SHIELD_SPARKS: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + if (type == Defines.TE_SCREEN_SPARKS) + CL_fx.ParticleEffect(pos, dir, 0xd0, 40); + else + CL_fx.ParticleEffect(pos, dir, 0xb0, 40); + //FIXME : replace or remove this sound + S.StartSound(pos, 0, 0, cl_sfx_lashit, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_SHOTGUN: // bullet hitting wall + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + CL_fx.ParticleEffect(pos, dir, 0, 20); + SmokeAndFlash(pos); + break; + + case Defines.TE_SPLASH: // bullet hitting water + cnt = MSG.ReadByte(Globals.net_message); + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + r = MSG.ReadByte(Globals.net_message); + if (r > 6) + color = 0x00; + else + color = splash_color[r]; + CL_fx.ParticleEffect(pos, dir, color, cnt); + + if (r == Defines.SPLASH_SPARKS) { + r = Lib.rand() & 3; + if (r == 0) + S.StartSound(pos, 0, 0, cl_sfx_spark5, 1, + Defines.ATTN_STATIC, 0); + else if (r == 1) + S.StartSound(pos, 0, 0, cl_sfx_spark6, 1, + Defines.ATTN_STATIC, 0); + else + S.StartSound(pos, 0, 0, cl_sfx_spark7, 1, + Defines.ATTN_STATIC, 0); + } + break; + + case Defines.TE_LASER_SPARKS: + cnt = MSG.ReadByte(Globals.net_message); + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + color = MSG.ReadByte(Globals.net_message); + CL_fx.ParticleEffect2(pos, dir, color, cnt); + break; + + // RAFAEL + case Defines.TE_BLUEHYPERBLASTER: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadPos(Globals.net_message, dir); + CL_fx.BlasterParticles(pos, dir); + break; + + case Defines.TE_BLASTER: // blaster hitting wall + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + CL_fx.BlasterParticles(pos, dir); + + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.ent.angles[0] = (float) (Math.acos(dir[2]) / Math.PI * 180); + // PMM - fixed to correct for pitch of 0 + if (dir[0] != 0.0f) + ex.ent.angles[1] = (float) (Math.atan2(dir[1], dir[0]) + / Math.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 = Defines.RF_FULLBRIGHT | Defines.RF_TRANSLUCENT; + ex.start = Globals.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, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_RAILTRAIL: // railgun effect + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadPos(Globals.net_message, pos2); + CL_fx.RailTrail(pos, pos2); + S.StartSound(pos2, 0, 0, cl_sfx_railg, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_EXPLOSION2: + case Defines.TE_GRENADE_EXPLOSION: + case Defines.TE_GRENADE_EXPLOSION_WATER: + MSG.ReadPos(Globals.net_message, pos); + + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.type = ex_poly; + ex.ent.flags = Defines.RF_FULLBRIGHT; + ex.start = Globals.cl.frame.servertime - 100; + ex.light = 350; + ex.lightcolor[0] = 1.0f; + ex.lightcolor[1] = 0.5f; + ex.lightcolor[2] = 0.5f; + ex.ent.model = cl_mod_explo4; + ex.frames = 19; + ex.baseframe = 30; + ex.ent.angles[1] = Lib.rand() % 360; + CL_fx.ExplosionParticles(pos); + if (type == Defines.TE_GRENADE_EXPLOSION_WATER) + S + .StartSound(pos, 0, 0, cl_sfx_watrexp, 1, + Defines.ATTN_NORM, 0); + else + S + .StartSound(pos, 0, 0, cl_sfx_grenexp, 1, + Defines.ATTN_NORM, 0); + break; + + // RAFAEL + case Defines.TE_PLASMA_EXPLOSION: + MSG.ReadPos(Globals.net_message, pos); + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.type = ex_poly; + ex.ent.flags = Defines.RF_FULLBRIGHT; + ex.start = Globals.cl.frame.servertime - 100; + ex.light = 350; + ex.lightcolor[0] = 1.0f; + ex.lightcolor[1] = 0.5f; + ex.lightcolor[2] = 0.5f; + ex.ent.angles[1] = Lib.rand() % 360; + ex.ent.model = cl_mod_explo4; + if (Globals.rnd.nextFloat() < 0.5) + ex.baseframe = 15; + ex.frames = 15; + CL_fx.ExplosionParticles(pos); + S.StartSound(pos, 0, 0, cl_sfx_rockexp, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_EXPLOSION1: + case Defines.TE_EXPLOSION1_BIG: // PMM + case Defines.TE_ROCKET_EXPLOSION: + case Defines.TE_ROCKET_EXPLOSION_WATER: + case Defines.TE_EXPLOSION1_NP: // PMM + MSG.ReadPos(Globals.net_message, pos); + + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.type = ex_poly; + ex.ent.flags = Defines.RF_FULLBRIGHT; + ex.start = Globals.cl.frame.servertime - 100; + ex.light = 350; + ex.lightcolor[0] = 1.0f; + ex.lightcolor[1] = 0.5f; + ex.lightcolor[2] = 0.5f; + ex.ent.angles[1] = Lib.rand() % 360; + if (type != Defines.TE_EXPLOSION1_BIG) // PMM + ex.ent.model = cl_mod_explo4; // PMM + else + ex.ent.model = cl_mod_explo4_big; + if (Globals.rnd.nextFloat() < 0.5) + ex.baseframe = 15; + ex.frames = 15; + if ((type != Defines.TE_EXPLOSION1_BIG) + && (type != Defines.TE_EXPLOSION1_NP)) // PMM + CL_fx.ExplosionParticles(pos); // PMM + if (type == Defines.TE_ROCKET_EXPLOSION_WATER) + S + .StartSound(pos, 0, 0, cl_sfx_watrexp, 1, + Defines.ATTN_NORM, 0); + else + S + .StartSound(pos, 0, 0, cl_sfx_rockexp, 1, + Defines.ATTN_NORM, 0); + break; + + case Defines.TE_BFG_EXPLOSION: + MSG.ReadPos(Globals.net_message, pos); + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.type = ex_poly; + ex.ent.flags = Defines.RF_FULLBRIGHT; + ex.start = Globals.cl.frame.servertime - 100; + ex.light = 350; + ex.lightcolor[0] = 0.0f; + ex.lightcolor[1] = 1.0f; + ex.lightcolor[2] = 0.0f; + ex.ent.model = cl_mod_bfg_explo; + ex.ent.flags |= Defines.RF_TRANSLUCENT; + ex.ent.alpha = 0.30f; + ex.frames = 4; + break; + + case Defines.TE_BFG_BIGEXPLOSION: + MSG.ReadPos(Globals.net_message, pos); + CL_fx.BFGExplosionParticles(pos); + break; + + case Defines.TE_BFG_LASER: + ParseLaser(0xd0d1d2d3); + break; + + case Defines.TE_BUBBLETRAIL: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadPos(Globals.net_message, pos2); + CL_fx.BubbleTrail(pos, pos2); + break; + + case Defines.TE_PARASITE_ATTACK: + case Defines.TE_MEDIC_CABLE_ATTACK: + ent = ParseBeam(cl_mod_parasite_segment); + break; + + case Defines.TE_BOSSTPORT: // boss teleporting to station + MSG.ReadPos(Globals.net_message, pos); + CL_fx.BigTeleportParticles(pos); + S.StartSound(pos, 0, 0, S.RegisterSound("misc/bigtele.wav"), 1, + Defines.ATTN_NONE, 0); + break; + + case Defines.TE_GRAPPLE_CABLE: + ent = ParseBeam2(cl_mod_grapple_cable); + break; + + // RAFAEL + case Defines.TE_WELDING_SPARKS: + cnt = MSG.ReadByte(Globals.net_message); + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + color = MSG.ReadByte(Globals.net_message); + CL_fx.ParticleEffect2(pos, dir, color, cnt); + + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.type = ex_flash; + // note to self + // we need a better no draw flag + ex.ent.flags = Defines.RF_BEAM; + ex.start = Globals.cl.frame.servertime - 0.1f; + ex.light = 100 + (Lib.rand() % 75); + ex.lightcolor[0] = 1.0f; + ex.lightcolor[1] = 1.0f; + ex.lightcolor[2] = 0.3f; + ex.ent.model = cl_mod_flash; + ex.frames = 2; + break; + + case Defines.TE_GREENBLOOD: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + CL_fx.ParticleEffect2(pos, dir, 0xdf, 30); + break; + + // RAFAEL + case Defines.TE_TUNNEL_SPARKS: + cnt = MSG.ReadByte(Globals.net_message); + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + color = MSG.ReadByte(Globals.net_message); + CL_fx.ParticleEffect3(pos, dir, color, cnt); + break; + + // ============= + // PGM + // PMM -following code integrated for flechette (different color) + case Defines.TE_BLASTER2: // green blaster hitting wall + case Defines.TE_FLECHETTE: // flechette + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + + // PMM + if (type == Defines.TE_BLASTER2) + CL_newfx.BlasterParticles2(pos, dir, 0xd0); + else + CL_newfx.BlasterParticles2(pos, dir, 0x6f); // 75 + + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.ent.angles[0] = (float) (Math.acos(dir[2]) / Math.PI * 180); + // PMM - fixed to correct for pitch of 0 + if (dir[0] != 0.0f) + ex.ent.angles[1] = (float) (Math.atan2(dir[1], dir[0]) + / Math.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 = Defines.RF_FULLBRIGHT | Defines.RF_TRANSLUCENT; + + // PMM + if (type == Defines.TE_BLASTER2) + ex.ent.skinnum = 1; + else + // flechette + ex.ent.skinnum = 2; + + ex.start = Globals.cl.frame.servertime - 100; + ex.light = 150; + // PMM + if (type == Defines.TE_BLASTER2) + ex.lightcolor[1] = 1; + else // flechette + { + ex.lightcolor[0] = 0.19f; + ex.lightcolor[1] = 0.41f; + ex.lightcolor[2] = 0.75f; + } + ex.ent.model = cl_mod_explode; + ex.frames = 4; + S.StartSound(pos, 0, 0, cl_sfx_lashit, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_LIGHTNING: + ent = ParseLightning(cl_mod_lightning); + S.StartSound(null, ent, Defines.CHAN_WEAPON, cl_sfx_lightning, 1, + Defines.ATTN_NORM, 0); + break; + + case Defines.TE_DEBUGTRAIL: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadPos(Globals.net_message, pos2); + CL_newfx.DebugTrail(pos, pos2); + break; + + case Defines.TE_PLAIN_EXPLOSION: + MSG.ReadPos(Globals.net_message, pos); + + ex = AllocExplosion(); + Math3D.VectorCopy(pos, ex.ent.origin); + ex.type = ex_poly; + ex.ent.flags = Defines.RF_FULLBRIGHT; + ex.start = Globals.cl.frame.servertime - 100; + ex.light = 350; + ex.lightcolor[0] = 1.0f; + ex.lightcolor[1] = 0.5f; + ex.lightcolor[2] = 0.5f; + ex.ent.angles[1] = Lib.rand() % 360; + ex.ent.model = cl_mod_explo4; + if (Globals.rnd.nextFloat() < 0.5) + ex.baseframe = 15; + ex.frames = 15; + if (type == Defines.TE_ROCKET_EXPLOSION_WATER) + S + .StartSound(pos, 0, 0, cl_sfx_watrexp, 1, + Defines.ATTN_NORM, 0); + else + S + .StartSound(pos, 0, 0, cl_sfx_rockexp, 1, + Defines.ATTN_NORM, 0); + break; + + case Defines.TE_FLASHLIGHT: + MSG.ReadPos(Globals.net_message, pos); + ent = MSG.ReadShort(Globals.net_message); + CL_newfx.Flashlight(ent, pos); + break; + + case Defines.TE_FORCEWALL: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadPos(Globals.net_message, pos2); + color = MSG.ReadByte(Globals.net_message); + CL_newfx.ForceWall(pos, pos2, color); + break; + + case Defines.TE_HEATBEAM: + ent = ParsePlayerBeam(cl_mod_heatbeam); + break; + + case Defines.TE_MONSTER_HEATBEAM: + ent = ParsePlayerBeam(cl_mod_monster_heatbeam); + break; + + case Defines.TE_HEATBEAM_SPARKS: + // cnt = MSG.ReadByte (net_message); + cnt = 50; + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + // r = MSG.ReadByte (net_message); + // magnitude = MSG.ReadShort (net_message); + r = 8; + magnitude = 60; + color = r & 0xff; + CL_newfx.ParticleSteamEffect(pos, dir, color, cnt, magnitude); + S.StartSound(pos, 0, 0, cl_sfx_lashit, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_HEATBEAM_STEAM: + // cnt = MSG.ReadByte (net_message); + cnt = 20; + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + // r = MSG.ReadByte (net_message); + // magnitude = MSG.ReadShort (net_message); + // color = r & 0xff; + color = 0xe0; + magnitude = 60; + CL_newfx.ParticleSteamEffect(pos, dir, color, cnt, magnitude); + S.StartSound(pos, 0, 0, cl_sfx_lashit, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_STEAM: + ParseSteam(); + break; + + case Defines.TE_BUBBLETRAIL2: + // cnt = MSG.ReadByte (net_message); + cnt = 8; + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadPos(Globals.net_message, pos2); + CL_newfx.BubbleTrail2(pos, pos2, cnt); + S.StartSound(pos, 0, 0, cl_sfx_lashit, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_MOREBLOOD: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + CL_fx.ParticleEffect(pos, dir, 0xe8, 250); + break; + + case Defines.TE_CHAINFIST_SMOKE: + dir[0] = 0; + dir[1] = 0; + dir[2] = 1; + MSG.ReadPos(Globals.net_message, pos); + CL_newfx.ParticleSmokeEffect(pos, dir, 0, 20, 20); + break; + + case Defines.TE_ELECTRIC_SPARKS: + MSG.ReadPos(Globals.net_message, pos); + MSG.ReadDir(Globals.net_message, dir); + // CL_ParticleEffect (pos, dir, 109, 40); + CL_fx.ParticleEffect(pos, dir, 0x75, 40); + //FIXME : replace or remove this sound + S.StartSound(pos, 0, 0, cl_sfx_lashit, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_TRACKER_EXPLOSION: + MSG.ReadPos(Globals.net_message, pos); + CL_newfx.ColorFlash(pos, 0, 150, -1, -1, -1); + CL_newfx.ColorExplosionParticles(pos, 0, 1); + // CL_Tracker_Explode (pos); + S.StartSound(pos, 0, 0, cl_sfx_disrexp, 1, Defines.ATTN_NORM, 0); + break; + + case Defines.TE_TELEPORT_EFFECT: + case Defines.TE_DBALL_GOAL: + MSG.ReadPos(Globals.net_message, pos); + CL_fx.TeleportParticles(pos); + break; + + case Defines.TE_WIDOWBEAMOUT: + ParseWidow(); + break; + + case Defines.TE_NUKEBLAST: + ParseNuke(); + break; + + case Defines.TE_WIDOWSPLASH: + MSG.ReadPos(Globals.net_message, pos); + CL_newfx.WidowSplash(pos); + break; + // PGM + // ============== + + default: + Com.Error(Defines.ERR_DROP, "CL_ParseTEnt: bad type"); + } + } + + /* + * ================= CL_AddBeams ================= + */ + static void AddBeams() { + int i, j; + beam_t[] b; + float[] dist = new float[3]; + float[] org = new float[3]; + float d; + entity_t ent = new entity_t(); + float yaw, pitch; + float forward; + float len, steps; + float model_length; + + // update beams + b = cl_beams; + for (i = 0; i < MAX_BEAMS; i++) { + if (b[i].model == null || b[i].endtime < Globals.cl.time) + continue; + + // if coming from the player, update the start position + if (b[i].entity == Globals.cl.playernum + 1) // entity 0 is the + // world + { + Math3D.VectorCopy(Globals.cl.refdef.vieworg, b[i].start); + b[i].start[2] -= 22; // adjust for view height + } + Math3D.VectorAdd(b[i].start, b[i].offset, org); + + // calculate pitch and yaw + Math3D.VectorSubtract(b[i].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] != 0.0f) + yaw = (float) (Math.atan2(dist[1], dist[0]) * 180 / Math.PI); + else if (dist[1] > 0) + yaw = 90; + else + yaw = 270; + if (yaw < 0) + yaw += 360; + + forward = (float) Math.sqrt(dist[0] * dist[0] + dist[1] + * dist[1]); + pitch = (float) (Math.atan2(dist[2], forward) * -180.0 / Math.PI); + if (pitch < 0) + pitch += 360.0; + } + + // add new entities for the beams + d = Math3D.VectorNormalize(dist); + + //memset (&ent, 0, sizeof(ent)); + ent = new entity_t(); + if (b[i].model == cl_mod_lightning) { + model_length = 35.0f; + d -= 20.0; // correction so it doesn't end in middle of tesla + } else { + model_length = 30.0f; + } + steps = (float) Math.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[i].model == cl_mod_lightning) && (d <= model_length)) { + // Com_Printf ("special case\n"); + Math3D.VectorCopy(b[i].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[i].model; + ent.flags = Defines.RF_FULLBRIGHT; + ent.angles[0] = pitch; + ent.angles[1] = yaw; + ent.angles[2] = Lib.rand() % 360; + V.AddEntity(ent); + return; + } + while (d > 0) { + Math3D.VectorCopy(org, ent.origin); + ent.model = b[i].model; + if (b[i].model == cl_mod_lightning) { + ent.flags = Defines.RF_FULLBRIGHT; + ent.angles[0] = -pitch; + ent.angles[1] = yaw + 180.0f; + ent.angles[2] = Lib.rand() % 360; + } else { + ent.angles[0] = pitch; + ent.angles[1] = yaw; + ent.angles[2] = Lib.rand() % 360; + } + + // Com_Printf("B: %d . %d\n", b[i].entity, b[i].dest_entity); + V.AddEntity(ent); + + for (j = 0; j < 3; j++) + org[j] += dist[j] * len; + d -= model_length; + } + } + } + + //extern cvar_t *hand; + + /* + * ================= ROGUE - draw player locked beams CL_AddPlayerBeams + * ================= + */ + static void AddPlayerBeams() { + float[] dist = new float[3]; + float[] org = new float[3]; + float d; + entity_t ent = new entity_t(); + float yaw, pitch; + float forward; + float len, steps; + int framenum = 0; + float model_length; + + float hand_multiplier; + frame_t oldframe; + player_state_t ps, ops; + + // PMM + if (Globals.hand != null) { + if (Globals.hand.value == 2) + hand_multiplier = 0; + else if (Globals.hand.value == 1) + hand_multiplier = -1; + else + hand_multiplier = 1; + } else { + hand_multiplier = 1; + } + // PMM + + // update beams + beam_t[] b = cl_playerbeams; + float[] f = new float[3]; + float[] u = new float[3]; + float[] r = new float[3]; + for (int i = 0; i < MAX_BEAMS; i++) { + + if (b[i].model == null || b[i].endtime < Globals.cl.time) + continue; + + if (cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam)) { + + // if coming from the player, update the start position + if (b[i].entity == Globals.cl.playernum + 1) // entity 0 is the + // world + { + // set up gun position + // code straight out of CL_AddViewWeapon + ps = Globals.cl.frame.playerstate; + int j = (Globals.cl.frame.serverframe - 1) + & Defines.UPDATE_MASK; + oldframe = Globals.cl.frames[j]; + + if (oldframe.serverframe != Globals.cl.frame.serverframe - 1 + || !oldframe.valid) + oldframe = Globals.cl.frame; // previous frame was + // dropped or involid + + ops = oldframe.playerstate; + for (j = 0; j < 3; j++) { + b[i].start[j] = Globals.cl.refdef.vieworg[j] + + ops.gunoffset[j] + Globals.cl.lerpfrac + * (ps.gunoffset[j] - ops.gunoffset[j]); + } + Math3D.VectorMA(b[i].start, + (hand_multiplier * b[i].offset[0]), + Globals.cl.v_right, org); + Math3D.VectorMA(org, b[i].offset[1], Globals.cl.v_forward, + org); + Math3D.VectorMA(org, b[i].offset[2], Globals.cl.v_up, org); + if ((Globals.hand != null) && (Globals.hand.value == 2)) { + Math3D.VectorMA(org, -1, Globals.cl.v_up, org); + } + // FIXME - take these out when final + Math3D.VectorCopy(Globals.cl.v_right, r); + Math3D.VectorCopy(Globals.cl.v_forward, f); + Math3D.VectorCopy(Globals.cl.v_up, u); + + } else + Math3D.VectorCopy(b[i].start, org); + } else { + // if coming from the player, update the start position + if (b[i].entity == Globals.cl.playernum + 1) // entity 0 is the + // world + { + Math3D.VectorCopy(Globals.cl.refdef.vieworg, b[i].start); + b[i].start[2] -= 22; // adjust for view height + } + Math3D.VectorAdd(b[i].start, b[i].offset, org); + } + + // calculate pitch and yaw + Math3D.VectorSubtract(b[i].end, org, dist); + + // PMM + if (cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam) + && (b[i].entity == Globals.cl.playernum + 1)) { + + len = Math3D.VectorLength(dist); + Math3D.VectorScale(f, len, dist); + Math3D.VectorMA(dist, (hand_multiplier * b[i].offset[0]), r, + dist); + Math3D.VectorMA(dist, b[i].offset[1], f, dist); + Math3D.VectorMA(dist, b[i].offset[2], u, dist); + if ((Globals.hand != null) && (Globals.hand.value == 2)) { + Math3D.VectorMA(org, -1, Globals.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] != 0.0f) + yaw = (float) (Math.atan2(dist[1], dist[0]) * 180 / Math.PI); + else if (dist[1] > 0) + yaw = 90; + else + yaw = 270; + if (yaw < 0) + yaw += 360; + + forward = (float) Math.sqrt(dist[0] * dist[0] + dist[1] + * dist[1]); + pitch = (float) (Math.atan2(dist[2], forward) * -180.0 / Math.PI); + if (pitch < 0) + pitch += 360.0; + } + + if (cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam)) { + if (b[i].entity != Globals.cl.playernum + 1) { + framenum = 2; + // Com_Printf ("Third person\n"); + ent.angles[0] = -pitch; + ent.angles[1] = yaw + 180.0f; + ent.angles[2] = 0; + // Com_Printf ("%f %f - %f %f %f\n", -pitch, yaw+180.0, + // b[i].offset[0], b[i].offset[1], b[i].offset[2]); + Math3D.AngleVectors(ent.angles, f, r, u); + + // if it's a non-origin offset, it's a player, so use the + // hardcoded player offset + if (Math3D.VectorCompare(b[i].offset, Globals.vec3_origin) == 0) { + Math3D.VectorMA(org, -(b[i].offset[0]) + 1, r, org); + Math3D.VectorMA(org, -(b[i].offset[1]), f, org); + Math3D.VectorMA(org, -(b[i].offset[2]) - 10, u, org); + } else { + // if it's a monster, do the particle effect + CL_newfx.MonsterPlasma_Shell(b[i].start); + } + } else { + framenum = 1; + } + } + + // if it's the heatbeam, draw the particle effect + if ((cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam) && (b[i].entity == Globals.cl.playernum + 1))) { + CL_newfx.Heatbeam(org, dist); + } + + // add new entities for the beams + d = Math3D.VectorNormalize(dist); + + //memset (&ent, 0, sizeof(ent)); + //ent = new entity_t(); + // this is not required. hoz + + if (b[i].model == cl_mod_heatbeam) { + model_length = 32.0f; + } else if (b[i].model == cl_mod_lightning) { + model_length = 35.0f; + d -= 20.0; // correction so it doesn't end in middle of tesla + } else { + model_length = 30.0f; + } + steps = (float) Math.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[i].model == cl_mod_lightning) && (d <= model_length)) { + // Com_Printf ("special case\n"); + Math3D.VectorCopy(b[i].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[i].model; + ent.flags = Defines.RF_FULLBRIGHT; + ent.angles[0] = pitch; + ent.angles[1] = yaw; + ent.angles[2] = Lib.rand() % 360; + V.AddEntity(ent); + return; + } + while (d > 0) { + Math3D.VectorCopy(org, ent.origin); + ent.model = b[i].model; + if (cl_mod_heatbeam != null && (b[i].model == cl_mod_heatbeam)) { + // ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT; + // ent.alpha = 0.3; + ent.flags = Defines.RF_FULLBRIGHT; + ent.angles[0] = -pitch; + ent.angles[1] = yaw + 180.0f; + ent.angles[2] = (Globals.cl.time) % 360; + // ent.angles[2] = rand()%360; + ent.frame = framenum; + } else if (b[i].model == cl_mod_lightning) { + ent.flags = Defines.RF_FULLBRIGHT; + ent.angles[0] = -pitch; + ent.angles[1] = yaw + 180.0f; + ent.angles[2] = Lib.rand() % 360; + } else { + ent.angles[0] = pitch; + ent.angles[1] = yaw; + ent.angles[2] = Lib.rand() % 360; + } + + // Com_Printf("B: %d . %d\n", b[i].entity, b[i].dest_entity); + V.AddEntity(ent); + + for (int j = 0; j < 3; j++) + org[j] += dist[j] * len; + d -= model_length; + } + } + } + + /* + * ================= CL_AddExplosions ================= + */ + static void AddExplosions() { + entity_t ent; + int i; + explosion_t[] ex; + float frac; + int f; + + //memset (&ent, 0, sizeof(ent)); Pointer! + ent = null; + ex = cl_explosions; + for (i = 0; i < MAX_EXPLOSIONS; i++) { + if (ex[i].type == ex_free) + continue; + frac = (Globals.cl.time - ex[i].start) / 100.0f; + f = (int) Math.floor(frac); + + ent = ex[i].ent; + + switch (ex[i].type) { + case ex_mflash: + if (f >= ex[i].frames - 1) + ex[i].type = ex_free; + break; + case ex_misc: + if (f >= ex[i].frames - 1) { + ex[i].type = ex_free; + break; + } + ent.alpha = 1.0f - frac / (ex[i].frames - 1); + break; + case ex_flash: + if (f >= 1) { + ex[i].type = ex_free; + break; + } + ent.alpha = 1.0f; + break; + case ex_poly: + if (f >= ex[i].frames - 1) { + ex[i].type = ex_free; + break; + } + + ent.alpha = (16.0f - (float) f) / 16.0f; + + if (f < 10) { + ent.skinnum = (f >> 1); + if (ent.skinnum < 0) + ent.skinnum = 0; + } else { + ent.flags |= Defines.RF_TRANSLUCENT; + if (f < 13) + ent.skinnum = 5; + else + ent.skinnum = 6; + } + break; + case ex_poly2: + if (f >= ex[i].frames - 1) { + ex[i].type = ex_free; + break; + } + + ent.alpha = (5.0f - (float) f) / 5.0f; + ent.skinnum = 0; + ent.flags |= Defines.RF_TRANSLUCENT; + break; + } + + if (ex[i].type == ex_free) + continue; + if (ex[i].light != 0.0f) { + V.AddLight(ent.origin, ex[i].light * ent.alpha, + ex[i].lightcolor[0], ex[i].lightcolor[1], + ex[i].lightcolor[2]); + } + + Math3D.VectorCopy(ent.origin, ent.oldorigin); + + if (f < 0) + f = 0; + ent.frame = ex[i].baseframe + f + 1; + ent.oldframe = ex[i].baseframe + f; + ent.backlerp = 1.0f - Globals.cl.lerpfrac; + + V.AddEntity(ent); + } + } + + /* + * ================= CL_AddLasers ================= + */ + static void AddLasers() { + laser_t[] l; + int i; + + l = cl_lasers; + for (i = 0; i < MAX_LASERS; i++) { + if (l[i].endtime >= Globals.cl.time) + V.AddEntity(l[i].ent); + } + } + + /* PMM - CL_Sustains */ + static void ProcessSustain() { + cl_sustain_t[] s; + int i; + + s = cl_sustains; + for (i = 0; i < MAX_SUSTAINS; i++) { + if (s[i].id != 0) + if ((s[i].endtime >= Globals.cl.time) + && (Globals.cl.time >= s[i].nextthink)) { + s[i].think.think(s[i]); + } else if (s[i].endtime < Globals.cl.time) + s[i].id = 0; + } + } + + /* + * ================= CL_AddTEnts ================= + */ + static void AddTEnts() { + AddBeams(); + // PMM - draw plasma beams + AddPlayerBeams(); + AddExplosions(); + AddLasers(); + // PMM - set up sustain + ProcessSustain(); + } +} \ No newline at end of file -- cgit v1.2.3