quakec/source/server/weapons/flamethrower.qc

196 lines
No EOL
4 KiB
C++

/*
server/weapons/flamethrower.qc
Core logic for the Ray Gun special weapon.
Modified from Unofficial Patch implementation.
Copyright (C) 2021-2023 NZ:P Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
//
// Flame_LingerThink()
// Play particle effect, remove after expire time.
//
void() Flame_LingerThink =
{
#ifdef FTE
te_flamejet(self.origin, v_up*8, 5);
#else
particle (self.origin, v_up*8, 0, 0);
#endif // FTE
if (self.ltime < time)
remove(self);
self.nextthink = time + 0.1;
}
//
// Flame_Linger(org, whodunit)
// Spawns in the lingering Flame particle effects.
//
void(vector org, entity whodunit) Flame_Linger =
{
entity linger = spawn();
setorigin(linger, org);
linger.owner = whodunit.owner;
linger.think = Flame_LingerThink;
linger.nextthink = time + 0.1;
linger.ltime = time + 5;
}
//
// Flame_Touch
// Something makes contact with the Flames.
//
void() Flame_Touch =
{
if (other == world) {
Flame_Linger(self.origin, self);
remove(self);
} else {
if (other.onfire || other.owner.onfire)
return;
if (other.classname == "ai_zombie_head" || other.classname == "ai_zombie_larm"
|| other.classname == "ai_zombie_rarm") {
other.owner.onfire = true;
other.owner.ltime = time + 2;
addmoney(self.owner, 10, true);
} else if (other.classname == "ai_zombie" || other.classname == "ai_dog") {
other.onfire = true;
other.firer = self.owner;
other.ltime = time + 2;
addmoney(self.owner, 10, true);
}
}
}
//
// Flame_DropDissapate()
// Fallen Flame touches a brush, have it linger.
//
void() Flame_DropCatch =
{
if (other == world) {
Flame_Linger(self.origin + '0 0 5', self);
remove(self);
}
}
//
// Flame_DropDissapate()
// Droplets did not make it to the ground in time.
//
void() Flame_DropDissapate =
{
remove(self);
}
//
// Flame_Drop()
// Some bits of the flame should fall to the ground, and make it
// dangerous to contact.
//
void() Flame_Drop =
{
entity drop = spawn();
drop.owner = self.owner;
setmodel(drop, "models/sprites/flamer.spr");
setsize(drop, '0 0 0', '0 0 0');
setorigin(drop, self.origin);
drop.touch = Flame_DropCatch;
drop.think = Flame_DropDissapate;
drop.nextthink = time + 0.8;
drop.solid = SOLID_TRIGGER;
drop.movetype = MOVETYPE_BOUNCE;
drop.velocity = v_up*-55;
}
//
// Flame_Buildup()
// This is the Flames beginning to combus before falling
// to the ground.
//
void() Flame_Buildup =
{
self.frame++;
if (self.frame > 11) {
if (random() > 0.75)
Flame_Drop();
remove(self);
}
self.nextthink = time + 0.05;
}
//
// W_FireFlame()
// Called by weapon_core for the Flamethrower firetype. Sets up the
// beam/missile and prepares it for impact and force forward.
//
void() W_FireFlame =
{
entity flamespr;
vector rand_angle;
flamespr = spawn();
flamespr.owner = self;
flamespr.movetype = MOVETYPE_FLYMISSILE;
flamespr.solid = SOLID_TRIGGER;
flamespr.classname = "flamethrower_sprite";
flamespr.state = 0;
flamespr.finaldest = self.v_angle;
// Randomize the output a tad.
rand_angle = self.v_angle;
rand_angle_x += random()*10;
rand_angle_y += random()*10;
makevectors(rand_angle);
flamespr.velocity = aim(self, 1000);
flamespr.velocity *= 600;
flamespr.owner = self;
flamespr.think = Flame_Buildup;
flamespr.nextthink = time + 0.01;
flamespr.touch = Flame_Touch;
setmodel(flamespr, "models/sprites/flamer.spr");
setorigin(flamespr, self.origin + self.view_ofs - v_up*5 + v_forward*10);
setsize(flamespr, '0 0 0', '0 0 0');
}