From 24d73885807f230aa960495b0451e28ae99986f7 Mon Sep 17 00:00:00 2001 From: Marco Hladik Date: Sun, 29 Aug 2021 17:45:33 +0200 Subject: [PATCH] WEAPON_GAUSS: More work towards the visual stuff this weapon offers by fixing beams and things. --- src/client/game_event.qc | 3 + src/client/init.qc | 1 + src/shared/events.h | 20 +++ src/shared/fx_gaussbeam.qc | 169 ++++++++++++++++++++++ src/shared/include.src | 2 + src/shared/items.h | 16 +- src/shared/w_gauss.qc | 160 +++----------------- zpak001.pk3dir/particles/weapon_gauss.cfg | 15 ++ zpak001.pk3dir/sound/fx_valve.sndshd | 7 + 9 files changed, 244 insertions(+), 149 deletions(-) create mode 100644 src/shared/events.h create mode 100755 src/shared/fx_gaussbeam.qc create mode 100644 zpak001.pk3dir/particles/weapon_gauss.cfg diff --git a/src/client/game_event.qc b/src/client/game_event.qc index 233d752..d6c445c 100644 --- a/src/client/game_event.qc +++ b/src/client/game_event.qc @@ -91,6 +91,9 @@ ClientGame_EventParse(float fHeader) FX_Impact(iType, vOrigin, vNormal); break; + case EV_GAUSSBEAM: + FX_GaussBeam_Parse(); + break; case EV_CHAT: float fSender = readbyte(); float fTeam = readbyte(); diff --git a/src/client/init.qc b/src/client/init.qc index d364ded..5f6089d 100644 --- a/src/client/init.qc +++ b/src/client/init.qc @@ -49,6 +49,7 @@ ClientGame_RendererRestart(string rstr) FX_GibHuman_Init(); FX_Spark_Init(); FX_Impact_Init(); + FX_GaussBeam_Init(); BEAM_TRIPMINE = particleeffectnum("weapon_tripmine.beam"); } diff --git a/src/shared/events.h b/src/shared/events.h new file mode 100644 index 0000000..095279f --- /dev/null +++ b/src/shared/events.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +enum +{ + EV_GAUSSBEAM = EV_SEPARATOR +}; diff --git a/src/shared/fx_gaussbeam.qc b/src/shared/fx_gaussbeam.qc new file mode 100755 index 0000000..802b2da --- /dev/null +++ b/src/shared/fx_gaussbeam.qc @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016-2020 Marco Hladik + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef CLIENT +var float TRAIL_GAUSSBEAM; + +void FX_GaussBeam(vector, vector, int, entity); + +void +FX_GaussBeam_Init(void) +{ + TRAIL_GAUSSBEAM = particleeffectnum("weapon_gauss.beam"); + precache_model("sprites/yelflare1.spr"); + precache_model("sprites/yelflare2.spr"); + Sound_Precache("fx.gaussbeam"); +} + +void +FX_GaussBeam_Parse(void) +{ + vector pos, angle; + int beams; + entity eowner; + + pos[0] = readcoord(); + pos[1] = readcoord(); + pos[2] = readcoord(); + + angle[0] = readcoord(); + angle[1] = readcoord(); + angle[2] = readcoord(); + beams = (int)readbyte(); + + eowner = findfloat(world, ::entnum, readentitynum()); + + FX_GaussBeam(pos, angle, beams, eowner); + print(sprintf("Parsed: %v %v %i %s\n", pos, angle, beams, eowner.classname)); +} + +void +FX_GaussBeam_Piece(vector vecPos, vector vecFlyDir) +{ + static float FX_GaussBeam_Piece_Fade(void) { + dynamiclight_add(self.origin, 256 * self.alpha, [1.0,0.5,0]); + + self.alpha -= frametime * 0.25; + + if (self.alpha <= 0.0f) { + remove(self); + } else { + addentity(self); + } + + return (PREDRAW_NEXT); + } + static float FX_GaussBeam_SubPiece_Fade(void) { + self.alpha -= frametime * 0.25; + + if (self.alpha <= 0.0f) { + remove(self); + } else { + addentity(self); + } + + return (PREDRAW_NEXT); + } + + entity piece = spawn(); + setorigin(piece, vecPos); + setmodel(piece, "sprites/yelflare1.spr"); + piece.movetype = MOVETYPE_NONE; + piece.solid = SOLID_NOT; + piece.colormod = [1.0,0.5,0.0]; + piece.drawmask = MASK_ENGINE; + piece.velocity = vecFlyDir; + piece.alpha = 1.0f; + piece.predraw = FX_GaussBeam_Piece_Fade; + piece.effects = EF_ADDITIVE; + + float r = random(); + + Sound_PlayAt(vecPos, "fx.gaussbeam"); + + for (int i = 0; i < 4; i++) { + entity sub = spawn(); + setorigin(sub, vecPos); + setmodel(sub, "sprites/yelflare2.spr"); + setsize(sub,[-2,-2,-2], [2,2,2]); + sub.movetype = MOVETYPE_BOUNCE; + sub.solid = SOLID_NOT; + sub.colormod = [1.0,0.5,0.0]; + sub.drawmask = MASK_ENGINE; + sub.velocity[0] = random()*100; + sub.velocity[1] = random()*100; + sub.velocity[2] = random()*100; + sub.alpha = 1.0f; + sub.gravity = 0.1f; + sub.predraw = FX_GaussBeam_SubPiece_Fade; + sub.effects = EF_ADDITIVE; + } +} +#endif + +void +FX_GaussBeam(vector vecPos, vector vecAngle, int numBeams, entity eOwner) +{ +#ifdef SERVER + WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET); + WriteByte(MSG_MULTICAST, EV_GAUSSBEAM); + WriteCoord(MSG_MULTICAST, vecPos[0]); + WriteCoord(MSG_MULTICAST, vecPos[1]); + WriteCoord(MSG_MULTICAST, vecPos[2]); + WriteFloat(MSG_MULTICAST, vecAngle[0]); + WriteFloat(MSG_MULTICAST, vecAngle[1]); + WriteFloat(MSG_MULTICAST, vecAngle[2]); + WriteByte(MSG_MULTICAST, numBeams); + WriteEntity(MSG_MULTICAST, eOwner); + + msg_entity = self; + multicast(vecPos, MULTICAST_PVS); +#else + vector vecSrc; + vector vecEndPos; + vector vecDir; + makevectors(vecAngle); + vecDir = v_forward; + vecSrc = vecPos; + vecEndPos = vecSrc + v_forward * 1024; + traceline(vecSrc, vecEndPos, FALSE, eOwner); + trailparticles(TRAIL_GAUSSBEAM, eOwner, vecSrc + (v_right * 8) + (v_up * -12), trace_endpos); + FX_GaussBeam_Piece(trace_endpos, vecDir * -1); + + vecDir = v_forward; + while (numBeams > 0) { + float n; + vector r; + n = -dotproduct(trace_plane_normal, vecDir); + r = 2 * trace_plane_normal * n + vecDir; + vecDir = r; + vecSrc = trace_endpos + (vecDir * 1); + vecEndPos = trace_endpos + (vecDir * 8192); + traceline(vecSrc, vecEndPos, FALSE, eOwner); + trailparticles(TRAIL_GAUSSBEAM, eOwner, vecSrc, trace_endpos); + FX_GaussBeam_Piece(trace_endpos, vecDir); + numBeams--; + + if (serverkeyfloat("*bspversion") == BSPVER_HL) + if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, trace_endpos)) != "sky") { + Decals_Place(trace_endpos, "{gaussshot1"); + } else { + break; + } + } +#endif +} + diff --git a/src/shared/include.src b/src/shared/include.src index ab6228a..e788976 100644 --- a/src/shared/include.src +++ b/src/shared/include.src @@ -1,5 +1,6 @@ #includelist entities.h +events.h flags.h player.qc ../../../base/src/shared/weapon_common.h @@ -9,6 +10,7 @@ pmove.qc pmove_water.qc fx_blood.qc +fx_gaussbeam.qc fx_breakmodel.qc fx_explosion.qc fx_gibhuman.qc diff --git a/src/shared/items.h b/src/shared/items.h index f6e6b37..e57f61a 100644 --- a/src/shared/items.h +++ b/src/shared/items.h @@ -15,21 +15,21 @@ */ #define ITEM_CROWBAR 0x00000001i -#define ITEM_GLOCK 0x00000002i -#define ITEM_PYTHON 0x00000004i -#define ITEM_MP5 0x00000008i +#define ITEM_GLOCK 0x00000002i +#define ITEM_PYTHON 0x00000004i +#define ITEM_MP5 0x00000008i #define ITEM_CROSSBOW 0x00000010i #define ITEM_SHOTGUN 0x00000020i -#define ITEM_RPG 0x00000040i -#define ITEM_GAUSS 0x00000080i +#define ITEM_RPG 0x00000040i +#define ITEM_GAUSS 0x00000080i -#define ITEM_EGON 0x00000100i +#define ITEM_EGON 0x00000100i #define ITEM_HORNETGUN 0x00000200i #define ITEM_HANDGRENADE 0x00000400i #define ITEM_TRIPMINE 0x00000800i #define ITEM_SATCHEL 0x00001000i -#define ITEM_SNARK 0x00002000i -#define ITEM_SUIT 0x00004000i +#define ITEM_SNARK 0x00002000i +#define ITEM_SUIT 0x00004000i #define ITEM_LONGJUMP 0x00008000i #define ITEM_UNUSED17 0x00010000i diff --git a/src/shared/w_gauss.qc b/src/shared/w_gauss.qc index 750dcc5..5e8ff3b 100644 --- a/src/shared/w_gauss.qc +++ b/src/shared/w_gauss.qc @@ -23,88 +23,8 @@ Gauss Weapon */ -#ifdef CLIENT -#define FXGAUSS_BEAMCOLOR [1,0.5,0] -class FXGauss:CBaseFX -{ - int m_iBeams; - vector m_vecStart; - vector m_vecAngle; - - void(void) FXGauss; - virtual void(void) Draw; -}; - -void -FXGauss::Draw(void) -{ - player pl = (player)self; - int iLoop = 6; - vector src, endpos; - vector gunpos = gettaginfo(pSeat->m_eViewModel, 33); - - if (alpha <= 0.0f) { - return; - } - - src = m_vecStart; - makevectors(input_angles); - endpos = src + v_forward * 1024; - traceline(src, endpos, FALSE, pl); - - /* drawing the first bit */ - vector fsize = [3,3]; - makevectors(view_angles); - R_BeginPolygon("sprites/xbeam1.spr_0.tga", 1, 0); - R_PolygonVertex(gunpos + v_right * fsize[0] - v_up * fsize[1], - [1,1], FXGAUSS_BEAMCOLOR, alpha); - R_PolygonVertex(gunpos - v_right * fsize[0] - v_up * fsize[1], - [0,1], FXGAUSS_BEAMCOLOR, alpha); - R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], - [0,0], FXGAUSS_BEAMCOLOR, alpha); - R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], - [1,0], FXGAUSS_BEAMCOLOR, alpha); - R_EndPolygon(); - - if (m_iBeams == 0) { - alpha -= clframetime * 3; - return; - } - - // reflection equation: - vector x = v_forward; - while (iLoop > 0) { - float n; - vector r; - n = -dotproduct(trace_plane_normal, x); - r = 2 * trace_plane_normal * n + x; - x = r; - src = trace_endpos + (x * 1); - endpos = trace_endpos + (x * 8192); - traceline(src, endpos, FALSE, pl); - - makevectors(view_angles); - R_BeginPolygon("sprites/xbeam1.spr_0.tga", 1, 0); - R_PolygonVertex(src + v_right * fsize[0] - v_up * fsize[1], - [1,1], FXGAUSS_BEAMCOLOR, alpha); - R_PolygonVertex(src - v_right * fsize[0] - v_up * fsize[1], - [0,1], FXGAUSS_BEAMCOLOR, alpha); - R_PolygonVertex(trace_endpos - v_right * fsize[0] + v_up * fsize[1], - [0,0], FXGAUSS_BEAMCOLOR, alpha); - R_PolygonVertex(trace_endpos + v_right * fsize[0] + v_up * fsize[1], - [1,0], FXGAUSS_BEAMCOLOR, alpha); - R_EndPolygon(); - - iLoop--; - } - alpha -= clframetime * 3; -} - -void -FXGauss::FXGauss(void) -{ - CBaseFX::CBaseFX(); -} +#ifdef SERVER +var float TRAIL_GAUSSBEAM; #endif enum @@ -175,14 +95,6 @@ void w_gauss_draw(void) pl.mode_tempstate = 0; Weapons_SetModel("models/v_gauss.mdl"); Weapons_ViewAnimation(GAUSS_DRAW); - - /* link the FX class */ -#ifdef CLIENT - entity eold = self; - self = pSeat->m_pWeaponFX; - spawnfunc_FXGauss(); - self = eold; -#endif } void w_gauss_holster(void) @@ -200,17 +112,20 @@ void w_gauss_fire(int one) vector src = Weapons_GetCameraPos(); vector endpos = src + v_forward * 1024; traceline(src, endpos, FALSE, pl); + sound(pl, CHAN_WEAPON, "weapons/gauss2.wav", 1, ATTN_NORM); int iDamage = one ? 20 : 200; - if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, trace_endpos)) == "sky") { - return; - } + if (serverkeyfloat("*bspversion") == BSPVER_HL) + if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, trace_endpos)) == "sky") { + return; + } if (trace_ent.takedamage == DAMAGE_YES) { Damage_Apply(trace_ent, self, iDamage, WEAPON_GAUSS, DMG_ELECTRO); sound(trace_ent, CHAN_ITEM, sprintf("weapons/electro%d.wav", random(0,3)+4), 1, ATTN_NORM); } + if (one) { return; } else { @@ -233,18 +148,11 @@ void w_gauss_fire(int one) src = trace_endpos + (dir * 1); endpos = trace_endpos + (dir * 8192); traceline(src, endpos, FALSE, pl); - te_beam(world, src, trace_endpos); iLoop--; if (trace_ent.takedamage == DAMAGE_YES) { Damage_Apply(trace_ent, self, iDamage, WEAPON_GAUSS, DMG_ELECTRO); sound(trace_ent, CHAN_ITEM, sprintf("weapons/electro%d.wav", random(0,3)+4), 1, ATTN_NORM); } - - if (getsurfacetexture(trace_ent, getsurfacenearpoint(trace_ent, trace_endpos)) != "sky") { - Decals_Place(trace_endpos, "{gaussshot1"); - } else { - break; - } } } #endif @@ -257,28 +165,15 @@ void w_gauss_primary(void) } /* Ammo check */ -#ifdef CLIENT - if (pl.a_ammo2 < 2) { - return; - } -#else if (pl.ammo_uranium < 2) { return; } -#endif Weapons_ViewAnimation(GAUSS_FIRE2); -#ifdef CLIENT - FXGauss p = (FXGauss)pSeat->m_pWeaponFX; - p.m_iBeams = 0; - p.m_vecAngle = input_angles; - p.m_vecStart = pl.origin + pl.view_ofs; - p.alpha = 1.0f; - pl.a_ammo2 -= 2; Weapons_ViewPunchAngle([-2,0,0]); -#else - pl.ammo_uranium -= 2; +#ifdef SERVER w_gauss_fire(1); + FX_GaussBeam(Weapons_GetCameraPos(), input_angles, 0, pl); #endif if (self.flags & FL_CROUCHING) @@ -289,6 +184,7 @@ void w_gauss_primary(void) pl.w_attack_next = 0.2f; pl.w_idle_next = 2.5f; } + void w_gauss_secondary(void) { player pl = (player)self; @@ -304,29 +200,15 @@ void w_gauss_secondary(void) pl.w_attack_next = 0.1f; /* Ammo check */ -#ifdef CLIENT - if (pl.a_ammo2 <= 0) { - if (pl.mode_tempstate > 0) { - w_gauss_release(); + if (pl.ammo_uranium <= 0) { + if (pl.mode_tempstate > 0) { + w_gauss_release(); } - return; - } -#else - if (pl.ammo_uranium <= 0) { - if (pl.mode_tempstate > 0) { - w_gauss_release(); - } - return; - } -#endif + return; + } -#ifdef CLIENT - if (pl.ammo_gauss_volume < 255) - pl.a_ammo2--; -#else if (pl.ammo_gauss_volume < 255) pl.ammo_uranium--; -#endif /* Set pitch sound shift */ pl.ammo_gauss_volume += 16; @@ -371,16 +253,12 @@ void w_gauss_release(void) else Animation_PlayerTop(pl, ANIM_SHOOTGAUSS, 0.43f); -#ifdef CLIENT - FXGauss p = (FXGauss)pSeat->m_pWeaponFX; - p.m_iBeams = 1; - p.m_vecAngle = input_angles; - p.m_vecStart = pl.origin + pl.view_ofs; - p.alpha = 1.0f; - soundupdate(pl, CHAN_WEAPON, "", -1, ATTN_NORM, 0, 0, 0); Weapons_ViewPunchAngle([-5,0,0]); +#ifdef CLIENT + soundupdate(pl, CHAN_WEAPON, "", -1, ATTN_NORM, 0, 0, 0); #else w_gauss_fire(0); + FX_GaussBeam(Weapons_GetCameraPos(), input_angles, 6, pl); #endif pl.w_attack_next = 1.5f; pl.w_idle_next = 4.0f; diff --git a/zpak001.pk3dir/particles/weapon_gauss.cfg b/zpak001.pk3dir/particles/weapon_gauss.cfg new file mode 100644 index 0000000..5286bf8 --- /dev/null +++ b/zpak001.pk3dir/particles/weapon_gauss.cfg @@ -0,0 +1,15 @@ +r_part beam +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + scale 2 + scaledelta 0.25 + rgbf 1 1 1 + alpha 1.0 + blend add + step 4 + randomvel 0 + type beam + die 0.25 + rgbf 1.0 0.5 0.0 +} diff --git a/zpak001.pk3dir/sound/fx_valve.sndshd b/zpak001.pk3dir/sound/fx_valve.sndshd index 3e85fe7..4481e08 100644 --- a/zpak001.pk3dir/sound/fx_valve.sndshd +++ b/zpak001.pk3dir/sound/fx_valve.sndshd @@ -4,4 +4,11 @@ fx.explosion sample weapons/explode4.wav sample weapons/explode5.wav shakes 1.5 +} + +fx.gaussbeam +{ + sample weapons/electro4.wav + sample weapons/electro5.wav + sample weapons/electro6.wav }