game-source/klik/weapons/w_shotgun.qc
2003-11-05 20:13:41 +00:00

265 lines
6.1 KiB
C++

#include "common.qh"
#include "misc.qh"
#include "weapon.qh"
#include "equip.qh"
#include "damage.qh"
#include "effect.qh"
#define STR_EQUIPID_SHOTGUN "Shotgun"
#define PUFF_RADIUS 60 /* FIXME: Base on spread too! */
void() _deathmsg_shotgun = {
local string def_nname, att_nname;
local float r;
def_nname = name(self);
att_nname = name(self.dmg_attacker);
if (self.dmg_attacker == self) {
r = random()*2;
if (r < 1) bprint(PRINT_DEATH, def_nname, " eats lead.\n");
else bprint(PRINT_DEATH, def_nname, " can't aim a shotgun.\n");
} else {
r = random()*2;
if (r < 1) bprint(PRINT_DEATH, def_nname, " eats a load of ", att_nname, "'s buckshot.\n");
else bprint(PRINT_DEATH, att_nname, " fills ", def_nname, " full of lead.\n");
}
};
void() _deathmsg_super_shotgun = {
local float r;
local string def_nname, att_nname;
def_nname = name(self);
att_nname = name(self.dmg_attacker);
if (self.dmg_attacker == self) {
r = random()*2;
if (r < 1) bprint(PRINT_DEATH, def_nname, " gets 2 shells.\n");
else bprint(PRINT_DEATH, def_nname, " practices hunting with a teleporter.\n");
} else {
r = random()*2;
if (r < 1) bprint(PRINT_DEATH, def_nname, " eats two loads of ", att_nname, "'s buckshot.\n");
else bprint(PRINT_DEATH, att_nname, " makes ", def_nname, " radiation resistant.\n");
}
};
entity(vector org, vector dir, entity ent) spawn_puff_damage = {
local entity inflictor;
inflictor = world;
while ((inflictor = find(inflictor, classname, "PUFF"))) {
if (vlen(inflictor.origin - org) > PUFF_RADIUS)
continue;
if (inflictor.enemy == ent)
break;
}
if (!inflictor) {
inflictor = spawn("PUFF");
inflictor.solid = SOLID_BBOX;
inflictor.movetype = MOVETYPE_FLY;
inflictor.deadflag = DEAD_NONLIVING;
inflictor.velocity = dir;
inflictor.angles = vectoangles(dir);
inflictor.owner = ent;
inflictor.enemy = ent;
inflictor.origin = org; // Don't bother linking.
}
inflictor.count++;
return inflictor;
};
void(float shotcount, vector spread, void() deathmessage) _fire_bullets =
{
local vector dir, direction;
local vector src;
local entity ignore, puff;
local float t_dmg, t_mass;
local float dist_left;
makevectors(self.v_angle);
dir = aim(self, 10000);
src = shootorigin(self);
/* See what a single missile would take.. */
ghost_inflictor.classname = "BULLET";
ghost_inflictor.velocity = dir*10000;
ghost_inflictor.dmg = 4;
ghost_inflictor.mass = ghost_inflictor.dmg;
damage_attack(ghost_inflictor);
t_dmg = ghost_inflictor.dmg;
t_mass = ghost_inflictor.mass;
/* Create the puff damage entities */
tl_proj_begin();
ignore = self;
dist_left = 8192;
do {
for (; shotcount > 0; shotcount--) {
direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
traceline(src, src + direction*dist_left, FALSE, ignore);
puff = spawn_puff_damage(trace_endpos, dir, trace_ent);
puff.health = dist_left;
}
puff = world;
while ((puff = find(puff, classname, "PUFF"))) {
tl_touch(puff.enemy, puff);
if (!tl_issolid(puff.enemy)) {
dist_left = puff.health - (dist_left*trace_fraction);
if (dist_left > 100)
break;
} else {
puff.dmg = t_dmg * puff.count;
puff.mass = t_mass * puff.mass;
if (!damage(puff.enemy, self, puff, puff.dmg, deathmessage))
effect_gun_spark(puff.origin, puff.velocity, puff.count);
}
puff.classname = "REMOVED_PUFF";
safe_remove(puff);
}
if (!puff)
break;
src = puff.origin;
ignore = puff.enemy;
shotcount = puff.count;
makevectors(puff.angles);
dir = v_forward;
remove(puff);
} while (1);
tl_proj_end();
};
void() _w_shotgun_think = {
self.weaponframe++;
if (self.weaponframe < 1 || self.weaponframe > 6) {
self.w_think = NOTHING_function;
self.weaponframe = 0;
}
};
void() _w_shotgun_fire =
{
if (!util_weapon_use_ammo(ammo_shells, 1))
return;
sound(self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
_fire_bullets(6, '0.04 0.04 0', _deathmsg_shotgun);
self.weaponframe = 1;
self.w_think = _w_shotgun_think;
self.mdl_func(MDL_FUNC_FIRE, 0);
effect_smallkick(self);
self.attack_finished = time + 0.5;
};
/* WEAPON 2 shotgun */
float(float action)
w_shotgun = {
if (action == WEAPON_AMMO) {
self.items |= IT_SHELLS;
return self.ammo_shells;
} else if (action == WEAPON_WEIGHT) {
return 20;
} else if (action == WEAPON_SELECTABLE) {
if (!equip_query(self, EQUIPID_SHOTGUN))
return 0;
if (self.ammo_shells >= 1)
return 1;
return -1;
} else if (action == WEAPON_SELECT) {
self.weaponmodel = "progs/v_shot.mdl";
self.weaponframe = 0;
self.mdl_mod = (self.mdl_mod & ~MDL_MOD_WEP_MASK) | MDL_MOD_WEP_SHOTGUN;
weaponprint(STR_EQUIPID_SHOTGUN);
} else if (action == WEAPON_FIRE) {
_w_shotgun_fire();
} else if (action == WEAPON_INIT) {
precache_model("progs/v_shot.mdl");
precache_sound("weapons/guncock.wav");
}
return 0;
};
// ================================================================
#define STR_EQUIPID_SUPER_SHOTGUN "Super Shotgun"
void() _w_super_shotgun_fire =
{
if (self.ammo_shells == 1) {
_w_shotgun_fire();
return;
}
if (!util_weapon_use_ammo(ammo_shells, 2))
return;
sound(self, CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
_fire_bullets(14, '0.14 0.08 0', _deathmsg_super_shotgun);
self.weaponframe = 1;
self.w_think = _w_shotgun_think;
self.mdl_func(MDL_FUNC_FIRE, 0);
effect_smallkick(self);
self.attack_finished = time + 0.7;
};
/* WEAPON 3 super_shotgun */
float(float action)
w_super_shotgun = {
if (action == WEAPON_AMMO) {
self.items |= IT_SHELLS;
return self.ammo_shells;
} else if (action == WEAPON_WEIGHT) {
return 40;
} else if (action == WEAPON_SELECTABLE) {
if (!equip_query(self, EQUIPID_SUPER_SHOTGUN))
return 0;
if (self.ammo_shells >= 2)
return 1;
return -1;
} else if (action == WEAPON_SELECT) {
self.weaponmodel = "progs/v_shot2.mdl";
self.weaponframe = 0;
self.mdl_mod = (self.mdl_mod & ~MDL_MOD_WEP_MASK) | MDL_MOD_WEP_SUPER_SHOTGUN;
weaponprint(STR_EQUIPID_SUPER_SHOTGUN);
} else if (action == WEAPON_FIRE) {
_w_super_shotgun_fire();
} else if (action == WEAPON_INIT) {
precache_model("progs/v_shot2.mdl");
precache_sound("weapons/shotgn2.wav");
}
return 0;
};