game-source/klik/weapons/w_lightning_gun.qc

229 lines
5.7 KiB
C++
Raw Normal View History

#include "common.qh"
#include "weapon.qh"
#include "equip.qh"
#include "damage.qh"
#include "misc.qh"
#include "effect.qh"
#define STR_EQUIPID_LIGHTNING_GUN "Lightning Gun"
void() _deathmsg_shaft = {
local string def_name, att_name;
local float r;
def_name = name(self);
att_name = name(self.dmg_attacker);
r = random()*4;
if (r < 1) bprint(PRINT_DEATH, def_name, " accepts ", att_name, "'s shaft.\n");
else if (r < 2) bprint(PRINT_DEATH, att_name, " gives ", def_name, " the shaft.\n");
else if (r < 3) bprint(PRINT_DEATH, def_name, " got smitten by ", att_name, ".\n");
else bprint(PRINT_DEATH, att_name, " fries up some ", def_name, " bacon.\n");
};
void() _deathmsg_discharge = {
local string def_name, att_name;
local float r;
def_name = name(self);
att_name = name(self.dmg_attacker);
if (self.dmg_attacker == self) {
r = random()*2;
if (r < 1) bprint(PRINT_DEATH, def_name, " conducts electricity.\n");
else bprint(PRINT_DEATH, def_name, " tries to become a lightbulb.\n");
} else {
r = random()*3;
if (r < 1) bprint(PRINT_DEATH, def_name, " accepts ", att_name, "'s discharge.\n");
else if (r < 2) bprint(PRINT_DEATH, att_name, " sends ", def_name, " a jolt.\n");
else bprint(PRINT_DEATH, def_name, " conducts electricity with ", att_name, ".\n");
}
};
void(vector p1, vector p2, float d) _w_lightning_gun_trace_damage =
{
local entity e1, e2;
local vector f;
f = p2 - p1;
f = normalize (f);
f_y = f_x = -f_y;
f_z = 0;
f = f*16;
e1 = e2 = world;
ghost_inflictor.classname = "LIGHTNING";
ghost_inflictor.dmg = d;
ghost_inflictor.mass = ghost_inflictor.dmg * 8;
ghost_inflictor.velocity = v_forward * 1000;
damage_attack(ghost_inflictor);
traceline (p1, p2, FALSE, self);
e1 = trace_ent;
damage(trace_ent, self, ghost_inflictor, ghost_inflictor.dmg, _deathmsg_shaft);
traceline (p1 + f, p2 + f, FALSE, self);
e2 = trace_ent;
if (trace_ent != e1)
damage(trace_ent, self, ghost_inflictor, ghost_inflictor.dmg, _deathmsg_shaft);
traceline (p1 - f, p2 - f, FALSE, self);
if (trace_ent != e1 && trace_ent != e2)
damage(trace_ent, self, ghost_inflictor, ghost_inflictor.dmg, _deathmsg_shaft);
};
void(entity ignore, entity attacker, entity inflictor, void() deathmessage)
damage_radius_lightning = {
local entity head;
local vector iorg, org;
local float points;
local float d, m, r;
local float cont;
d = inflictor.dmg;
m = inflictor.mass;
r = inflictor.lip;
iorg = center(inflictor);
for (head = findradius(iorg, r + 40); head; head = head.chain) {
if (head == ignore)
continue;
if (!_damage_radius_can_hit(iorg, head))
continue;
cont = pointcontents(trace_endpos);
if (cont < CONTENT_LAVA || cont > CONTENT_WATER)
continue;
org = center(head);
points = r - (0.5 * vlen(iorg - org));
if (points <= 0)
continue;
inflictor.dmg = (points * d) / r;
inflictor.mass = (points * m) / r;
damage(head, attacker, inflictor, inflictor.dmg, deathmessage);
}
};
void() _w_lightning_gun_beam =
{
local vector org;
local float cells;
org = shootorigin(self);
// explode if under water
if (self.waterlevel > 1)
{
self.mdl_func(MDL_FUNC_IDLE, 0);
cells = self.ammo_cells;
self.ammo_cells = 0;
ghost_inflictor.classname = "DISCHARGE";
ghost_inflictor.origin = self.origin;
ghost_inflictor.velocity = '0 0 0';
ghost_inflictor.dmg = 35*cells;
ghost_inflictor.mass = ghost_inflictor.dmg * 8;
ghost_inflictor.lip = ghost_inflictor.dmg;
ghost_inflictor.speed = 1000;
damage_radius_lightning(world, self, ghost_inflictor, _deathmsg_discharge);
return;
}
if (self.t_width < time) {
sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
self.t_width = time + 0.6;
}
makevectors(self.v_angle);
traceline (org, org + v_forward*600, TRUE, self);
effect_lightning2(self, org, trace_endpos);
effect_smallkick(self);
_w_lightning_gun_trace_damage(self.origin, trace_endpos, 30);
};
//============================================================================
void() _w_lightning_gun_think = {
self.weaponframe++;
if (self.weaponframe == 5)
self.weaponframe = 1;
/* FIXME: Use short circuit logic here when compiler supports */
if (!self.button0 || self.impulse || self.weaponframe < 1 || self.weaponframe > 5) {
self.weaponframe = 0;
self.w_think = NOTHING_function;
self.mdl_func(MDL_FUNC_IDLE, 0);
return;
}
if (!util_weapon_use_ammo(ammo_cells, 1)) {
self.weaponframe = 0;
self.w_think = NOTHING_function;
self.mdl_func(MDL_FUNC_IDLE, 0);
return;
}
_w_lightning_gun_beam();
self.attack_finished = time + 0.2;
};
/* WEAPON 8 lightning_gun */
float(float action)
w_lightning_gun = {
if (action == WEAPON_AMMO) {
self.items |= IT_CELLS;
return self.ammo_cells;
} else if (action == WEAPON_WEIGHT) {
local vector point;
local float cont;
point = self.origin;
point_z = self.origin_z + (self.mins_z + self.maxs_z) * 0.5;
cont = pointcontents(point);
if (cont >= CONTENT_LAVA && cont <= CONTENT_WATER)
return -60;
return 60;
} else if (action == WEAPON_SELECTABLE) {
if (!equip_query(self, EQUIPID_LIGHTNING_GUN))
return 0;
if (self.ammo_cells >= 1)
return 1;
return -1;
} else if (action == WEAPON_SELECT) {
self.weaponmodel = "progs/v_light.mdl";
self.weaponframe = 0;
self.mdl_mod = (self.mdl_mod & ~MDL_MOD_WEP_MASK) | MDL_MOD_WEP_LIGHTNING_GUN;
weaponprint(STR_EQUIPID_LIGHTNING_GUN);
} else if (action == WEAPON_FIRE) {
sound(self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
self.w_think = _w_lightning_gun_think;
self.w_think();
self.w_thought = TRUE;
} else if (action == WEAPON_INIT) {
precache_model("progs/v_light.mdl");
precache_sound("weapons/lstart.wav");
precache_sound("weapons/lhit.wav");
}
return 0;
};