REGISTER_WEAPON(MINE_LAYER, w_minelayer, IT_ROCKETS, 4, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_HIGH, "minelayer", "minelayer", "Mine Layer");
#else
#ifdef SVQC
-.float minelayer_detonate;
-.float mine_number, mine_time;
+void W_Mine_Think (void);
+.float minelayer_detonate, minelayer_mines;
+.float mine_time;
void spawnfunc_weapon_minelayer (void)
{
weapon_defaultspawnfunc(WEP_MINE_LAYER);
}
-void W_Mine_RespawnEntity ()
+void W_Mine_Stick ()
{
+ spamsound (self, CHAN_PROJECTILE, "weapons/mine_stick.wav", VOL_BASE, ATTN_NORM);
+
// in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
entity newmine;
setsize(newmine, '-4 -4 -4', '4 4 4');
setorigin(newmine, self.origin);
setmodel(newmine, "models/mine.md3");
- newmine.angles = vectoangles(-trace_plane_normal);
+ newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
newmine.takedamage = self.takedamage;
newmine.damageforcescale = self.damageforcescale;
newmine.health = self.health;
newmine.event_damage = self.event_damage;
- newmine.movetype = MOVETYPE_NONE;
+ newmine.movetype = MOVETYPE_NONE; // lock the mine in place
newmine.projectiledeathtype = self.projectiledeathtype;
- newmine.mine_number = self.mine_number;
newmine.mine_time = self.mine_time;
newmine.touch = SUB_Null;
- newmine.think = self.think;
+ newmine.think = W_Mine_Think;
newmine.nextthink = time;
newmine.cnt = self.cnt;
newmine.flags = self.flags;
remove (self);
}
-void W_Mine_RemoteExplode()
+void W_Mine_RemoteExplode ()
{
if(self.owner.deadflag == DEAD_NO)
if((self.spawnshieldtime >= 0)
}
}
-void W_Mine_ProximityExplode()
+void W_Mine_ProximityExplode ()
{
// make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
if(cvar("g_balance_minelayer_protection"))
{
other = world;
self.projectiledeathtype |= HITTYPE_BOUNCE;
- W_Mine_Explode ();
+ W_Mine_Explode();
+ return;
+ }
+
+ // a player's mines shall explode if he disconnects or dies
+ // TODO: Do this on team change too
+ if(self.owner.classname != "player" || self.owner.deadflag != DEAD_NO)
+ {
+ other = world;
+ self.projectiledeathtype |= HITTYPE_BOUNCE;
+ W_Mine_Explode();
return;
}
- // set the mine for detonation when a foe gets too close
- head = findradius(self.origin, cvar("g_balance_minelayer_detectionradius"));
+ // set the mine for detonation when a foe gets close enough
+ head = findradius(self.origin, cvar("g_balance_minelayer_proximityradius"));
while(head)
{
if(head.classname == "player" && head.deadflag == DEAD_NO)
{
PROJECTILE_TOUCH;
if(!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))
- {
- spamsound (self, CHAN_PROJECTILE, "weapons/mine_stick.wav", VOL_BASE, ATTN_NORM);
- self.movetype = MOVETYPE_NONE; // lock the mine in place
-
- W_Mine_RespawnEntity();
- }
+ W_Mine_Stick();
else if(self.movetype != MOVETYPE_NONE) // don't unstick a locked mine when someone touches it
self.velocity = '0 0 0';
}
void W_Mine_Attack (void)
{
- local entity mine;
- local entity flash;
+ entity mine;
+ entity flash;
// scan how many mines we placed, and return if we reached our limit
if(cvar("g_balance_minelayer_limit"))
{
- self.mine_number = 0;
+ self.minelayer_mines = 0;
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
- self.mine_number += 1;
+ self.minelayer_mines += 1;
- if(self.mine_number >= cvar("g_balance_minelayer_limit"))
+ if(self.minelayer_mines >= cvar("g_balance_minelayer_limit"))
{
// the refire delay keeps this message from being spammed
sprint(self, strcat("You cannot place more than ^2", cvar_string("g_balance_minelayer_limit"), " ^7mines at a time\n") );
W_AttachToShotorg(flash, '5 0 0');
// common properties
+
+ other = mine; MUTATOR_CALLHOOK(EditProjectile);
}
void spawnfunc_weapon_minelayer (void); // defined in t_items.qc
if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
{
// decide whether to detonate mines
- local entity mine, targetlist, targ;
- local float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
- local float selfdamage, teamdamage, enemydamage;
+ entity targetlist, targ;
+ float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
+ float selfdamage, teamdamage, enemydamage;
edgedamage = cvar("g_balance_minelayer_edgedamage");
coredamage = cvar("g_balance_minelayer_damage");
edgeradius = cvar("g_balance_minelayer_radius");
}
mine = find(mine, classname, "mine");
}
- local float desirabledamage;
+ float desirabledamage;
desirabledamage = enemydamage;
if (teamplay != 1 && time > self.invincible_finished && time > self.spawnshieldtime)
desirabledamage = desirabledamage - selfdamage * cvar("g_balance_selfdamagepercent");
targ = targ.chain;
}
}else{
- local float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
+ float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
//As the distance gets larger, a correct detonation gets near imposible
//Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player
if(v_forward * normalize(mine.origin - self.enemy.origin)< 0.1)