1
0
Fork 0
forked from fte/fteqw

generic projectile code

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1066 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
TimeServ 2005-05-31 08:10:07 +00:00
parent 57cac0ac70
commit 99854ae8ec
10 changed files with 330 additions and 409 deletions

View file

@ -13,11 +13,11 @@ Suicide backpack/quad/ring drop
Condense bprint, sprint, centerprints
te_explode sprite
NQ/QW cross compatibility
Track oldbutton presses/weaponstate
Generic projectile spawning
Todo -
Track oldbutton presses/weaponstate
Samelevel 4 (exit acts as a spawnpoint teleporter)
Generic projectile spawning
Effects/decal system
Fix weird deathmatch modes, cvar checking
Add monsters back
@ -31,4 +31,4 @@ Clean up backpack pickup prints?
Decal system based on visibility from players?
CSQC?
Don't use newmis/spawn projectiles in front?
sv_gravity change?
sv_gravity change?

View file

@ -494,7 +494,6 @@ called each time a player enters a new level
*/
void() PutClientInServer =
{
dprint("putclientinserver called\n");
local entity spot;
self.classname = "player";

View file

@ -1,8 +1,7 @@
void() T_MissileTouch;
void() info_player_start;
void(entity targ, entity attacker, INTEGER mod) ClientObituary;
void(entity inflictor, entity attacker, float damage, entity ignore, INTEGER mod) T_RadiusDamage;
void(entity inflictor, entity attacker, float damage, float radius, entity ignore, INTEGER mod) T_RadiusDamage;
/*SERVER
void() monster_death_use;
@ -284,13 +283,13 @@ void(entity targ, entity inflictor, entity attacker, float damage, INTEGER mod)
T_RadiusDamage
============
*/
void(entity inflictor, entity attacker, float damage, entity ignore, INTEGER mod) T_RadiusDamage =
void(entity inflictor, entity attacker, float damage, float radius, entity ignore, INTEGER mod) T_RadiusDamage =
{
local float points;
local entity head;
local vector org;
head = findradius(inflictor.origin, damage+40);
head = findradius(inflictor.origin, radius);
while (head)
{

View file

@ -289,7 +289,6 @@ void end_sys_fields; // flag for structure dumping
#define MOVETYPE_NOCLIP 8
#define MOVETYPE_FLYMISSILE 9 // fly with extra size against monsters
#define MOVETYPE_BOUNCE 10
#define MOVETYPE_BOUNCEMISSILE 11 // bounce with extra size
// edict.solid values
#define SOLID_NOT 0 // no interaction with other objects
@ -533,7 +532,6 @@ float AS_MISSILE = 4;
//
// player only fields
//
.float voided;
.float walkframe;
// Zoid Additions
@ -643,6 +641,19 @@ entity newmis;
float pausetime; // time to pause for monsters
entity movetarget; // target entity to move to
};
struct { // fields used with generic projectiles
float damage_direct; // damage done with a direct hit
float damage_exp; // damage done from radius damage
float radius_exp; // radius of radius damage
INTEGER mod_direct; // mod type for direct hit
INTEGER mod_exp; // mod type for radius damage
float expire_time; // time when projectile dies
void() proj_think; // extra think function used with projectile
float proj_think_time; // interval between thinks
INTEGER proj_effect; // effect used with projectile
INTEGER voided; // projectile has been voided
float() proj_touch; // extra touch function used with projectile
};
// fields used with ambient sounds?
/*
struct {

View file

@ -230,39 +230,6 @@ void(vector org) TE_lightningblood =
#endif
};
// view kicks
void(entity ent) VK_smallkick =
{
#ifdef NETQUAKE
self.punchangle_x = -2;
#else
msg_entity = ent;
WriteByte (MSG_ONE, SVC_SMALLKICK);
#endif
}
void(entity ent) VK_bigkick =
{
#ifdef NETQUAKE
self.punchangle_x = -4;
#else
msg_entity = ent;
WriteByte (MSG_ONE, SVC_BIGKICK);
#endif
}
// muzzle flash
void() muzzleflash =
{
#ifdef NETQUAKE
self.effects |= EF_MUZZLEFLASH;
#else
WriteByte (MSG_MULTICAST, SVC_MUZZLEFLASH);
WriteEntity (MSG_MULTICAST, self);
multicast (self.origin, MULTICAST_PVS);
#endif
};
// function pointers for TE calls
var void(vector org, float damage) SpawnBlood = _SpawnBlood;
var void(vector org) TE_explosion = _TE_explosion;
@ -305,3 +272,48 @@ void() EFF_SetEffects =
if (eng_support & ENG_TEBLOOD)
SpawnBlood = _SpawnBlood_TEBlood; // use TE_Blood builtin instead
};
// view kicks
void(entity ent) VK_smallkick =
{
#ifdef NETQUAKE
self.punchangle_x = -2;
#else
msg_entity = ent;
WriteByte (MSG_ONE, SVC_SMALLKICK);
#endif
}
void(entity ent) VK_bigkick =
{
#ifdef NETQUAKE
self.punchangle_x = -4;
#else
msg_entity = ent;
WriteByte (MSG_ONE, SVC_BIGKICK);
#endif
}
// muzzle flash
void() muzzleflash =
{
#ifdef NETQUAKE
self.effects |= EF_MUZZLEFLASH;
#else
WriteByte (MSG_MULTICAST, SVC_MUZZLEFLASH);
WriteEntity (MSG_MULTICAST, self);
multicast (self.origin, MULTICAST_PVS);
#endif
};
// touch blood functions
void(float damage) spawn_touchblood =
{
local vector vel;
vel = normalize (self.velocity);
vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
vel = vel + 2*trace_plane_normal;
vel = vel * 0.4;
SpawnBlood (self.origin + vel, damage);
};

View file

@ -217,7 +217,7 @@ void() barrel_explode =
self.takedamage = DAMAGE_NO;
self.classname = "explo_box";
// did say self.owner, self.enemy should be set by Killed function
T_RadiusDamage (self, self.enemy, 160, self, MOD_EXPLOBOX);
T_RadiusDamage (self, self.enemy, 160, 200, self, MOD_EXPLOBOX);
TE_explosion(self.origin + '0 0 32');
remove (self);
};
@ -292,75 +292,45 @@ void() misc_explobox2 =
float SPAWNFLAG_SUPERSPIKE = 1;
float SPAWNFLAG_LASER = 2;
void() Laser_Touch =
{
local vector org;
if (other == self.owner)
return; // don't explode on owner
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
org = self.origin - 8*normalize(self.velocity);
if (other.health)
{
SpawnBlood (org, 15);
T_Damage (other, self, self.owner, 15, MOD_LASER);
}
else
{
TE_gunshot(org);
}
remove(self);
};
void(vector org, vector vec) LaunchLaser =
{
if (self.classname == "monster_enforcer")
sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
vec = normalize(vec);
newmis = spawn();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLY;
newmis.solid = SOLID_BBOX;
newmis.effects = EF_DIMLIGHT;
setmodel (newmis, "progs/laser.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, org);
newmis.velocity = vec * 600;
newmis.angles = vectoangles(newmis.velocity);
newmis.nextthink = time + 5;
newmis.think = SUB_Remove;
newmis.touch = Laser_Touch;
};
void() spikeshooter_use =
{
if (self.spawnflags & SPAWNFLAG_LASER)
{
sound (self, CHAN_VOICE, "enforcer/enfire.wav", 1, ATTN_NORM);
LaunchLaser (self.origin, self.movedir);
PRJ_FireProjectile(self,
"progs/laser.mdl",
self.origin,
self.movedir * 600,
PE_LASER,
15,
MOD_LASER,
5);
}
else
{
sound (self, CHAN_VOICE, "weapons/spike2.wav", 1, ATTN_NORM);
launch_spike (self.origin, self.movedir);
newmis.velocity = self.movedir * 500;
if (self.spawnflags & SPAWNFLAG_SUPERSPIKE)
newmis.touch = superspike_touch;
{
PRJ_FireProjectile(self,
"progs/s_spike.mdl",
self.origin,
self.movedir * 500,
PE_SUPERSPIKE,
18,
MOD_SUPERSPIKE,
6);
}
else
{
PRJ_FireProjectile(self,
"progs/spike.mdl",
self.origin,
self.movedir * 500,
PE_SPIKE,
9,
MOD_SPIKE,
6);
}
}
};

View file

@ -168,12 +168,12 @@ void() player_axed4 = [$axattd4, player_run ] {};
void() player_nail1 =[$nailatt1, player_nail2 ]
{
if (self.weaponstate == WS_IDLE || intermission_running || self.impulse)
if (self.weaponstate == WS_IDLE || intermission_running)
{player_run ();return;}
};
void() player_nail2 =[$nailatt2, player_nail1 ]
{
if (self.weaponstate == WS_IDLE || intermission_running || self.impulse)
if (self.weaponstate == WS_IDLE || intermission_running)
{player_run ();return;}
};

View file

@ -7,6 +7,7 @@ effects.qc
obituary.qc
combat.qc
items.qc
proj.qc
weapons.qc
world.qc
client.qc

184
quakec/basemod/proj.qc Normal file
View file

@ -0,0 +1,184 @@
// 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);
};

View file

@ -2,7 +2,7 @@
*/
void (entity targ, entity inflictor, entity attacker, float damage, INTEGER mod) T_Damage;
void () player_run;
void(entity bomb, entity attacker, float rad, entity ignore, INTEGER mod) T_RadiusDamage;
void(entity inflictor, entity attacker, float damage, float radius, entity ignore, INTEGER mod) T_RadiusDamage;
void(vector org, float damage) SpawnBlood;
void() SuperDamageSound;
@ -66,20 +66,6 @@ void() W_FireAxe =
//============================================================================
vector() wall_velocity =
{
local vector vel;
vel = normalize (self.velocity);
vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
vel = vel + 2*trace_plane_normal;
vel = vel * 200;
return vel;
};
/*
================
SpawnMeatSpray
@ -110,19 +96,6 @@ void(vector org, vector vel) SpawnMeatSpray =
setorigin (missile, org);
};
/*
================
spawn_touchblood
================
*/
void(float damage) spawn_touchblood =
{
local vector vel;
vel = wall_velocity () * 0.2;
SpawnBlood (self.origin + vel*0.01, damage);
};
/*
==============================================================================
@ -307,61 +280,6 @@ ROCKETS
==============================================================================
*/
void() T_MissileTouch =
{
local float damg;
// if (deathmatch == 4)
// {
// if ( ((other.weapon == 32) || (other.weapon == 16)))
// {
// if (random() < 0.1)
// {
// if (other != world)
// {
// // bprint (PRINT_HIGH, "Got here\n");
// other.deathtype = "blaze";
// T_Damage (other, self, self.owner, 1000 );
// T_RadiusDamage (self, self.owner, 1000, other);
// }
// }
// }
// }
if (other == self.owner)
return; // don't explode on owner
if (self.voided) {
return;
}
self.voided = 1;
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
damg = 100 + random()*20;
if (other.health)
T_Damage (other, self, self.owner, damg, MOD_ROCKET);
// don't do radius damage to the other, because all the damage
// was done in the impact
T_RadiusDamage (self, self.owner, 120, other, MOD_ROCKETRADIUS);
// sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
self.origin = self.origin - 8 * normalize(self.velocity);
TE_explosion(self.origin);
remove(self);
};
/*
================
W_FireRocket
@ -375,30 +293,15 @@ void() W_FireRocket =
sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
VK_smallkick(self);
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
// set newmis speed
makevectors (self.v_angle);
newmis.velocity = aim(self, 1000);
newmis.velocity = newmis.velocity * 1000;
newmis.angles = vectoangles(newmis.velocity);
newmis.touch = T_MissileTouch;
newmis.voided = 0;
// set newmis duration
newmis.nextthink = time + 5;
newmis.think = SUB_Remove;
newmis.classname = "rocket";
setmodel (newmis, "progs/missile.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
PRJ_FireProjectile(self,
"progs/missile.mdl",
self.origin + v_forward*8 + '0 0 16',
aim(self, 1000) * 1000,
PE_EXPLOSION,
100+random()*20,
MOD_ROCKET,
5);
PRJ_SetRadiusDamage(120, 160, MOD_ROCKETRADIUS);
};
/*
@ -454,6 +357,7 @@ void() W_FireLightning =
{
local vector org;
local float cells;
local INTEGER expmod;
if (self.ammo_cells < 1)
{
@ -477,12 +381,12 @@ void() W_FireLightning =
cells = self.ammo_cells;
self.ammo_cells = 0;
W_SetCurrentAmmo ();
expmod = MOD_SHAFTWATER;
if (self.watertype == CONTENT_SLIME)
T_RadiusDamage (self, self, 35*cells, world, MOD_SHAFTSLIME);
expmod = MOD_SHAFTSLIME;
else if (self.watertype == CONTENT_LAVA)
T_RadiusDamage (self, self, 35*cells, world, MOD_SHAFTLAVA);
else
T_RadiusDamage (self, self, 35*cells, world, MOD_SHAFTWATER);
expmod = MOD_SHAFTLAVA;
T_RadiusDamage (self, self, 35*cells, 40+35*cells, world, expmod);
return;
}
@ -505,156 +409,44 @@ void() W_FireLightning =
LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
};
//=============================================================================
void() GrenadeExplode =
{
if (self.voided) {
return;
}
self.voided = 1;
T_RadiusDamage (self, self.owner, 120, world, MOD_GRENADE);
TE_explosion(self.origin);
remove (self);
};
void() GrenadeTouch =
{
if (other == self.owner)
return; // don't explode on owner
if (other.takedamage == DAMAGE_AIM)
{
GrenadeExplode();
return;
}
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
if (self.velocity == '0 0 0')
self.avelocity = '0 0 0';
};
/*
================
W_FireGrenade
================
*/
void() W_FireGrenade =
{
{
local vector vel;
if (deathmatch != 4)
self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
VK_smallkick(self);
newmis = spawn ();
newmis.voided=0;
newmis.owner = self;
newmis.movetype = MOVETYPE_BOUNCE;
newmis.solid = SOLID_BBOX;
newmis.classname = "grenade";
// set newmis speed
makevectors (self.v_angle);
if (self.v_angle_x)
newmis.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
vel = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
else
{
newmis.velocity = aim(self, 10000);
newmis.velocity = newmis.velocity * 600;
newmis.velocity_z = 200;
vel = aim(self, 10000) * 600;
vel_z = 200;
}
newmis.avelocity = '300 300 300';
VK_smallkick(self);
PRJ_FireProjectile(self, "progs/grenade.mdl", self.origin, vel, PE_EXPLOSIONGROUND, 0, 0, 2.5);
PRJ_SetRadiusDamage(120, 160, MOD_GRENADE);
PRJ_SetBouncyProjectile();
newmis.angles = vectoangles(newmis.velocity);
newmis.touch = GrenadeTouch;
// set newmis duration
if (deathmatch == 4)
{
newmis.nextthink = time + 2.5;
self.attack_finished = time + 1.1;
T_Damage (self, self, self.owner, 10, MOD_GRENADE);
}
else
newmis.nextthink = time + 2.5;
newmis.think = GrenadeExplode;
setmodel (newmis, "progs/grenade.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, self.origin);
};
//=============================================================================
void() spike_touch;
void() superspike_touch;
/*
===============
launch_spike
Used for both the player and the ogre
===============
*/
void(vector org, vector dir) launch_spike =
{
newmis = spawn ();
newmis.voided=0;
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
newmis.angles = vectoangles(dir);
newmis.touch = spike_touch;
newmis.classname = "spike";
newmis.think = SUB_Remove;
newmis.nextthink = time + 6;
setmodel (newmis, "progs/spike.mdl");
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
setorigin (newmis, org);
newmis.velocity = dir * 1000;
};
void() W_FireSuperSpikes =
{
local vector dir;
sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
if (deathmatch != 4)
self.currentammo = self.ammo_nails = self.ammo_nails - 2;
dir = aim (self, 1000);
launch_spike (self.origin + '0 0 16', dir);
newmis.touch = superspike_touch;
setmodel (newmis, "progs/s_spike.mdl");
setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
VK_smallkick(self);
};
void(float ox) W_FireSpikes =
{
local vector dir;
makevectors (self.v_angle);
if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
{
W_FireSuperSpikes ();
return;
}
if (self.ammo_nails < 1)
{
self.weapon = W_BestWeapon ();
@ -665,87 +457,41 @@ void(float ox) W_FireSpikes =
sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
if (deathmatch != 4)
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
dir = aim (self, 1000);
launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
VK_smallkick(self);
PRJ_FireProjectile(self,
"progs/spike.mdl",
self.origin + '0 0 16' + v_right*ox,
aim(self, 1000) * 1000,
PE_SPIKE,
9,
MOD_SPIKE,
6);
};
void() spike_touch =
void() W_FireSuperSpikes =
{
if (other == self.owner)
return;
if (self.voided) {
return;
}
self.voided = 1;
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
if (pointcontents(self.origin) == CONTENT_SKY)
if (self.ammo_nails < 2)
{
remove(self);
W_FireSpikes(0);
return;
}
// hit something that bleeds
if (other.takedamage)
{
spawn_touchblood (9);
T_Damage (other, self, self.owner, 9, MOD_SPIKE);
}
else
{
if (self.classname == "wizspike")
TE_wizspike(self.origin);
else if (self.classname == "knightspike")
TE_knightspike(self.origin);
else
TE_spike(self.origin);
}
remove(self);
sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
if (deathmatch != 4)
self.currentammo = self.ammo_nails = self.ammo_nails - 2;
VK_smallkick(self);
PRJ_FireProjectile(self,
"progs/s_spike.mdl",
self.origin + '0 0 16',
aim(self, 1000) * 1000,
PE_SUPERSPIKE,
18,
MOD_SUPERSPIKE,
6);
};
void() superspike_touch =
{
if (other == self.owner)
return;
if (self.voided) {
return;
}
self.voided = 1;
if (other.solid == SOLID_TRIGGER)
return; // trigger field, do nothing
if (pointcontents(self.origin) == CONTENT_SKY)
{
remove(self);
return;
}
// hit something that bleeds
if (other.takedamage)
{
spawn_touchblood (18);
T_Damage (other, self, self.owner, 18, MOD_SUPERSPIKE);
}
else
{
TE_superspike(self.origin);
}
remove(self);
};
/*
===============================================================================
@ -1017,7 +763,7 @@ void() W_Attack =
r = 0.1;
break;
case IT_SUPER_NAILGUN:
W_FireSpikes(0);
W_FireSuperSpikes();
r = 0.1;
break;
case IT_GRENADE_LAUNCHER:
@ -1403,4 +1149,3 @@ void() SuperDamageSound =
return;
};