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:
parent
57cac0ac70
commit
99854ae8ec
10 changed files with 330 additions and 409 deletions
|
@ -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?
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;}
|
||||
};
|
||||
|
||||
|
|
|
@ -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
184
quakec/basemod/proj.qc
Normal 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);
|
||||
};
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue