WEAPON_GAUSS: More work towards the visual stuff this weapon offers by

fixing beams and things.
This commit is contained in:
Marco Cawthorne 2021-08-29 17:45:33 +02:00
parent 3ae7cda228
commit 24d7388580
9 changed files with 244 additions and 149 deletions

View file

@ -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();

View file

@ -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");
}

20
src/shared/events.h Normal file
View file

@ -0,0 +1,20 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
};

169
src/shared/fx_gaussbeam.qc Executable file
View file

@ -0,0 +1,169 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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
}

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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
}

View file

@ -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
}