fteqw/quakec/basemod/proj.qc

185 lines
4.2 KiB
Plaintext

// Generic projectile spawning code (PRJ) ---
// projectile effect defines
#define PE_NONE 0
#define PE_SPIKE 1
#define PE_SUPERSPIKE 2
#define PE_WIZSPIKE 3
#define PE_KNIGHTSPIKE 4
#define PE_GUNSHOT 5
#define PE_EXPLOSION 6
#define PE_EXPLOSIONGROUND 7
#define PE_LASER 8
// functions used only by this QC file
float() _PRJ_Bounce =
{
if (other.takedamage == DAMAGE_AIM)
return 0; // explode
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
if (self.velocity == '0 0 0')
self.avelocity = '0 0 0';
return 1; // keep bouncing
};
void() _PRJ_Touch =
{
local entity ignore;
// check validity of projectile
if (other == self.owner)
return; // don't explode on owner
if (self.voided) {
return;
}
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
// handle custom touch
if (other != self) // didn't expire
if (self.proj_touch) // is valid function
if (self.proj_touch())
return;
// void projectile
self.voided = 1;
// do projectile damage
ignore = self;
if (other.health && self.damage_direct)
{
T_Damage (other, self, self.owner, self.damage_direct, self.mod_direct);
ignore = other;
}
if (self.radius_exp)
T_RadiusDamage (self, self.owner, self.damage_exp, self.radius_exp, other, self.mod_exp);
// run projectile effect
switch (self.proj_effect)
{
case PE_SPIKE:
if (ignore != self) // hit something
spawn_touchblood (self.damage_direct);
else if (other != self) // didn't expire
TE_spike(self.origin);
break;
case PE_SUPERSPIKE:
if (ignore != self) // hit something
spawn_touchblood (self.damage_direct);
else if (other != self) // didn't expire
TE_superspike(self.origin);
break;
case PE_WIZSPIKE:
if (ignore != self) // hit something
spawn_touchblood (self.damage_direct);
else if (other != self) // didn't expire
TE_wizspike(self.origin);
break;
case PE_KNIGHTSPIKE:
if (ignore != self) // hit something
spawn_touchblood (self.damage_direct);
else if (other != self) // didn't expire
TE_knightspike(self.origin);
break;
case PE_LASER:
if (other != self)
sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
self.origin = self.origin - 8 * normalize(self.velocity);
case PE_GUNSHOT:
if (ignore != self) // hit something
spawn_touchblood (self.damage_direct);
else if (other != self) // didn't expire
TE_gunshot(self.origin);
break;
case PE_EXPLOSION:
self.origin = self.origin - 8 * normalize(self.velocity);
case PE_EXPLOSIONGROUND:
TE_explosion(self.origin);
break;
}
remove(self);
};
void() _PRJ_Expire =
{
other = self;
_PRJ_Touch();
};
void() _PRJ_Think =
{
if (self.expire_time > time)
{
_PRJ_Expire();
return;
}
newmis.proj_think();
newmis.nextthink = time + newmis.proj_think_time;
};
// functions used by outside QC files
// set bouncy projectile function
void() PRJ_SetBouncyProjectile =
{
newmis.proj_touch = _PRJ_Bounce;
newmis.movetype = MOVETYPE_BOUNCE;
newmis.avelocity = '300 300 300';
};
// set radius damage function
void(INTEGER damg, INTEGER damgrad, INTEGER damgmod) PRJ_SetRadiusDamage =
{
newmis.damage_exp = damg;
newmis.radius_exp = damgrad;
newmis.mod_exp = damgmod;
};
// extra think function, should always be called ONCE after the main spawn function
void(void() thinkfunc, float thinkres) PRJ_SetThink =
{
newmis.think = _PRJ_Think;
newmis.nextthink = time + thinkres;
newmis.proj_think = thinkfunc;
newmis.proj_think_time = thinkres;
};
// main spawning function
void(entity parent, string modl, vector org, vector vel, INTEGER effect, INTEGER damg, INTEGER damgmod, float expiretime) PRJ_FireProjectile =
{
newmis = spawn ();
newmis.owner = parent;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
// newmis.classname = class;
newmis.velocity = vel;
newmis.damage_direct = damg;
newmis.mod_direct = damgmod;
newmis.proj_effect = effect;
newmis.touch = _PRJ_Touch;
newmis.expire_time = time + expiretime;
newmis.think = _PRJ_Expire;
newmis.nextthink = time + expiretime;
newmis.angles = vectoangles(newmis.velocity);
setmodel (newmis, modl);
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
setorigin (newmis, org);
};