1 void W_Grenade_DefaultTouch (void)
\r
3 if (!self.state & 1 && (other.classname == "player" || other.classname == "corpse"))
\r
4 self.think(); // assume my think was an explosion function
\r
6 sound (self, CHAN_IMPACT, "weapons/grenade_bounce.wav", 1, ATTN_NORM);
\r
9 void W_Grenade_DefaultDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
\r
11 self.health = self.health - damage;
\r
12 if (self.health <= 0)
\r
13 self.think(); // assume my think was an explosion function
\r
16 float W_ThrowGrenade(void() GrenadeSpecial)
\r
18 local entity gren, oself;
\r
21 if(self.ammo_shells < 10)
\r
23 sprint(self, "Not enough grenade ammo\n");
\r
24 self.grenade_time = time + 0.3;
\r
27 self.ammo_shells = self.ammo_shells - 10;
\r
29 // sound (self, CHAN_WEAPON, "weapons/grenade_fire.wav", 1, ATTN_NORM);
\r
30 self.punchangle_x = -2;
\r
31 org = self.origin + self.view_ofs + v_forward * 15 + v_right * 5 + v_up * -12;
\r
35 gren.classname = "grenade";
\r
36 gren.movetype = MOVETYPE_BOUNCE;
\r
37 gren.solid = SOLID_BBOX;
\r
38 setorigin(gren, org);
\r
40 gren.takedamage = DAMAGE_YES;
\r
42 //gren.damageforcescale = 4;
\r
43 gren.event_damage = W_Grenade_DefaultDamage;
\r
55 //--------------------------------------------
\r
57 void InflictStunStatus(entity targ, float stuntime)
\r
59 if(targ.classname != "player")
\r
60 return; // only players can be stunned (fixme: turrets? vehicles?)
\r
62 // stun target by increasing attack_finished so he can't attack
\r
63 if(targ.attack_finished < time + stuntime)
\r
64 targ.attack_finished = time + stuntime;
\r
66 // also prevent use of grenades
\r
67 // disabled, since the point of the grenades is being
\r
68 // able to attack when weapon is busy or disabled
\r
69 //if(targ.grenade_time < time + stuntime)
\r
70 // targ.grenade_time = time + stuntime;
\r
73 //--------------------------------------------
\r
75 void ExtinguishFirebomb(entity e)
\r
78 if(e.enemy == world)
\r
80 //bprint("ExtinguishFirebomb failed, no enemy!\n");
\r
83 //bprint(strcat("ExtinguishFirebomb(", e.classname, ") ", e.enemy.classname, "\n"));
\r
93 setmodel(f, "models/sprites/null.spr");
\r
94 setattachment(f, world, "");
\r
99 setmodel(b, "models/sprites/null.spr");
\r
100 setattachment(b, world, "");
\r
102 //b.think = SUB_Remove;
\r
103 //b.nextthink = time + 2;
\r
106 //f.think = SUB_Remove;
\r
107 //f.nextthink = time + 2;
\r
113 void Firebomb_Flame_Check()
\r
115 if(self.owner == world || self.owner.model == "")
\r
117 if(self.owner != world && self.owner.enemy == self)
\r
119 //bprint("Firebomb flame calls ExtinguishFirebomb on owner\n");
\r
121 ExtinguishFirebomb(self.owner);
\r
122 self.owner.enemy = world;
\r
125 //bprint("Firebomb flame resorts to deleting itself!\n");
\r
126 setattachment(self, world, "");
\r
127 setattachment(self.enemy, world, "");
\r
128 setmodel(self, "");
\r
129 setmodel(self.enemy, "");
\r
130 self.think = self.enemy.think = SUB_Remove;
\r
131 self.nextthink = self.enemy.nextthink = time + 1;
\r
134 self.nextthink = time + 0.5;
\r
137 void W_Firebomb_Think ()
\r
140 float flametime, flamedmg, flamerate, flameedge, flameradius, distratio;
\r
142 self.nextthink = time + cvar("g_balance_grenade_firebomb_burnrate");
\r
144 if(self.wait < time || self.enemy == world)
\r
146 //bprint("Firebomb deletes its flame\n");
\r
147 ExtinguishFirebomb(self);
\r
149 setmodel(self, "");
\r
150 self.think = SUB_Remove;
\r
151 self.nextthink = time + 2.2;
\r
155 flameradius = cvar("g_balance_grenade_firebomb_burnradius");
\r
156 flamedmg = cvar("g_balance_grenade_firebomb_flamedmg");
\r
157 flamerate = cvar("g_balance_grenade_firebomb_flamerate");
\r
158 flametime = cvar("g_balance_grenade_firebomb_flametime");
\r
159 flameedge = cvar("g_balance_grenade_firebomb_edgeratio");
\r
161 RadiusDamage (self, self.owner,
\r
162 cvar("g_balance_grenade_firebomb_burndmg"),
\r
163 cvar("g_balance_grenade_firebomb_burndmg")*flameedge,
\r
164 cvar("g_balance_grenade_firebomb_burnradius"), world,
\r
167 head = findradius(self.origin, flameradius);
\r
170 if(head.takedamage == DAMAGE_AIM)//head.classname == "player" || head.classname == "turret")
\r
172 traceline(self.origin, head.origin, TRUE, self);
\r
173 if(trace_fraction >= 1)
\r
175 distratio = 1 - (vlen(head.origin - self.origin) / flameradius);
\r
176 IgniteTarget(head, self.owner,
\r
177 (flametime*flameedge) + (flametime - flameedge)*distratio,
\r
187 /* radius = cvar("g_balance_grenade_firebomb_burnradius");
\r
188 head = findradius(self.origin, radius);
\r
191 //bprint("firebomb see target\n");
\r
192 if((head.takedamage || head.classname == "grenade") && head != self.enemy && head != self)
\r
194 //bprint("firebomb try to burn target\n");
\r
195 // don't harm or spread to allies or pyros
\r
196 if(!(head.classname == "player" && (head.team == self.team || head.class == CLASS_PYRO)) )
\r
198 //bprint("firebomb burn target\n");
\r
199 edgeratio = cvar("g_balance_heat_edgeratio");
\r
200 distratio = ( 1 - (vlen(self.enemy.origin - head.origin) / radius) );
\r
201 flameratio = edgeratio + distratio*(1 - edgeratio);
\r
203 // deal direct damage from the heat radiated by the fire
\r
204 damage = flameratio * cvar("g_balance_grenade_firebomb_burndmg");
\r
205 Damage (head, self, self.owner, damage, DEATH_BURNING, self.enemy.origin, '0 0 0');
\r
207 if(head.takedamage == DAMAGE_AIM)
\r
209 IgniteTarget(head, self.owner,
\r
210 cvar("g_balance_grenade_firebomb_flametime"),
\r
211 cvar("g_balance_grenade_firebomb_flamedmg"),
\r
212 cvar("g_balance_grenade_firebomb_flamerate"), TRUE);
\r
221 void W_Firebomb_Activate (void)
\r
223 // set bomb on fire visually
\r
224 /* CreateFlame(self, self.owner);
\r
225 self.onfire.think = SUB_Null;
\r
226 self.onfire.nextthink = -1;
\r
227 self.onfire.colormod = self.onfire.onfire.colormod = '128 255 128'*(1/255)*1;//'255 128 64'*(1/255)*1;//3;
\r
231 f = self.enemy = spawn();
\r
233 f.classname = f.enemy.classname = "firebomb_flame";
\r
238 f.think = Firebomb_Flame_Check;
\r
239 f.nextthink = time;
\r
241 f.colormod = f.enemy.colormod =
\r
242 stov(cvar_string("g_balance_grenade_firebomb_flamecolor"))*(1/255)
\r
243 *cvar("g_balance_grenade_firebomb_flamec_strength");//0.3;//'128 128 255'*(1/255)*3;//'255 128 64'*(1/255)*1;//3;
\r
244 //f.alpha = f.enemy.alpha = 0.6;
\r
245 f.effects = f.enemy.effects = EF_ADDITIVE;
\r
246 f.scale = f.enemy.scale = 2;
\r
248 setmodel(f, "models/sprites/fire_top.spr32");
\r
249 setmodel(f.enemy, "models/sprites/fire_base.spr32");
\r
251 setorigin(f.enemy, '0 0 -5' * f.scale);
\r
252 setorigin(f, '0 0 2' * f.scale + '0 0 20');
\r
254 setattachment(f, f.owner, "");
\r
255 setattachment(f.enemy, f, "");
\r
257 // burn targets each frame
\r
258 self.wait = time + cvar("g_balance_grenade_firebomb_burntime");
\r
259 self.event_damage = SUB_Null;
\r
260 self.takedamage = 0;
\r
261 self.movetype = MOVETYPE_TOSS;
\r
262 self.angles = '0 0 0';
\r
263 self.touch = SUB_Null;
\r
264 self.think = W_Firebomb_Think;
\r
265 self.nextthink = time;
\r
270 setmodel(self, "models/grenademodel.md3");
\r
271 setsize(self, '-6 -6 -3', '6 6 3');
\r
273 self.classname = "firebomb"; // don't get bounced around like other grenades
\r
275 self.nextthink = time + 3;
\r
276 self.think = W_Firebomb_Activate;
\r
277 self.touch = W_Firebomb_Activate;
\r
278 self.state = 1; // don't explode on contact with player
\r
279 self.velocity = v_forward * cvar("g_balance_grenade_firebomb_speed")
\r
280 + v_up * cvar("g_balance_grenade_frag_firebomb_up");
\r
281 self.avelocity = '-500 0 0';
\r
282 //self.event_damage = SUB_Null;
\r
284 self.colormod = '255 128 0'*(1/255)*2;
\r
287 self.angles = vectoangles (self.velocity);
\r
290 //--------------------------------------------
\r
292 void W_ConcussionGrenade_Explode (void)
\r
295 float radius, spd, spd_up, stuntime, sim_jump_pad;
\r
298 org2 = findbetterlocation (self.origin);
\r
299 te_explosionrgb (org2, (1/255)*'255 128 0');
\r
300 // fixme: need different sound
\r
301 sound (self, CHAN_VOICE, "weapons/grenade_impact.wav", 1, ATTN_NORM);
\r
303 self.event_damage = SUB_Null;
\r
305 radius = cvar("g_balance_grenade_concussion_radius");
\r
306 spd = cvar("g_balance_grenade_concussion_force");
\r
307 spd_up = cvar("g_balance_grenade_concussion_force_up");
\r
308 stuntime = cvar("g_balance_grenade_concussion_stuntime");
\r
309 sim_jump_pad = !cvar("g_balance_grenade_concussion_restrictflight");
\r
311 // extinguish flames in radius (even those not burning a player)
\r
315 head = find(head, classname, "burning");
\r
316 if(head != world && vlen(head.enemy.origin - self.origin) <= radius)
\r
318 traceline(self.origin, head.enemy.origin, TRUE, self);
\r
319 if(trace_fraction >= 1)
\r
321 ExtinguishFlame(head.enemy);
\r
328 // extinguish firebombs
\r
332 head = find(head, classname, "firebomb");
\r
333 if(head != world && vlen(head.origin - self.origin) <= radius)
\r
335 traceline(self.origin, head.origin, TRUE, self);
\r
336 if(trace_fraction >= 1)
\r
338 ExtinguishFirebomb(head);
\r
345 // also extinguish napalm
\r
349 head = find(head, classname, "napalm");
\r
350 if(head != world && vlen(head.origin - self.origin) <= radius)
\r
352 traceline(self.origin, head.origin, TRUE, self);
\r
353 if(trace_fraction >= 1)
\r
355 head.think = SUB_Remove;
\r
356 head.nextthink = time;
\r
366 // throw hapless players
\r
370 head = findfloat(head, movetype, MOVETYPE_WALK);
\r
371 if(head != world && vlen(head.origin - self.origin) <= radius)
\r
373 traceline(self.origin, head.origin, TRUE, self);
\r
374 if(trace_fraction >= 1)
\r
376 if(sim_jump_pad && head.classname == "player" && !head.jump_pad)
\r
378 head.velocity = head.velocity + normalize(head.origin - self.origin) * spd + '0 0 1'*spd_up;
\r
381 InflictStunStatus(head, stuntime);
\r
389 void W_ConcussionGrenade()
\r
391 setmodel(self, "models/grenademodel.md3");
\r
392 setsize(self, '-6 -6 -3', '6 6 3');
\r
394 self.nextthink = time + 1.5 + random()*0.5;
\r
395 self.think = W_ConcussionGrenade_Explode;
\r
396 self.touch = W_Grenade_DefaultTouch;
\r
397 self.state = 1; // don't explode on contact with player
\r
398 self.velocity = v_forward * cvar("g_balance_grenade_concussion_speed")
\r
399 + v_up * cvar("g_balance_grenade_concussion_speed_up");
\r
400 self.avelocity = '100 150 100';
\r
402 self.angles = vectoangles (self.velocity);
\r
405 //--------------------------------------------
\r
407 // touch the player and go *poke*
\r
408 void W_NailGrenade_Spike_Poke (void)
\r
410 if (other == self.owner)
\r
412 else if (pointcontents (self.origin) == CONTENT_SKY)
\r
418 if(other.takedamage)
\r
419 Damage (other, self, self.enemy, self.dmg, WEP_NAMEK, self.origin, normalize(self.velocity) * cvar("g_balance_grenade_nail_spikeforce"));
\r
422 te_spark(self.origin, normalize(self.velocity) * -70 - '0 0 100', 30);
\r
423 te_gunshot(self.origin);
\r
429 void W_NailGrenade_Spike(vector org, vector vel, float damage)
\r
433 spike.enemy = self.owner;
\r
434 spike.owner = self;
\r
435 spike.classname = "spike";
\r
437 // some downward curving
\r
438 spike.movetype = MOVETYPE_BOUNCE;
\r
439 spike.gravity = cvar("g_balance_grenade_nail_spikegrav");
\r
440 spike.solid = SOLID_BBOX;
\r
441 setmodel(spike, "models/plasmatrail.mdl");
\r
442 setsize(spike, '0 0 0', '0 0 0');
\r
443 setorigin(spike, org);
\r
445 spike.dmg = damage;
\r
447 spike.nextthink = time + 3 + random()*0.5;
\r
448 spike.think = SUB_Remove;
\r
449 spike.touch = W_NailGrenade_Spike_Poke;
\r
450 spike.velocity = vel;
\r
451 spike.angles = vectoangles (spike.velocity);
\r
452 spike.scale = 0.75;
\r
455 void W_NailGrenade_Attack (void)
\r
457 float r, num, maxnum, is_odd, spread, starty, incy;
\r
460 r = ceil(random()*3);
\r
462 sound (self, CHAN_IMPACT, "weapons/ric1.wav", 1, ATTN_NORM);
\r
464 sound (self, CHAN_IMPACT, "weapons/ric2.wav", 1, ATTN_NORM);
\r
466 sound (self, CHAN_IMPACT, "weapons/ric3.wav", 1, ATTN_NORM);
\r
469 maxnum = cvar("g_balance_grenade_nail_numspikes");
\r
470 spread = cvar("g_balance_grenade_nail_spread");
\r
472 is_odd = (floor(maxnum / 2) != maxnum / 2); //true if maxnum is an odd number
\r
476 incy = (1 / maxnum) * spread;
\r
477 starty = self.mangle_y - (incy * maxnum/2) + incy*0.5;
\r
481 incy = (1 / maxnum) * spread;
\r
482 starty = self.mangle_y - (incy * maxnum/2) + incy*0.5;
\r
485 ang_z = self.mangle_z;
\r
486 ang_x = self.mangle_x;
\r
489 while(num < maxnum)
\r
492 W_NailGrenade_Spike(self.origin, v_forward*cvar("g_balance_grenade_nail_spikespeed") , cvar("g_balance_grenade_nail_spikedamage"));
\r
493 W_NailGrenade_Spike(self.origin, v_forward*cvar("g_balance_grenade_nail_spikespeed") * -1, cvar("g_balance_grenade_nail_spikedamage"));
\r
495 ang_y = ang_y + incy;
\r
498 self.count = self.count - 1;
\r
502 // change shooting angle and fire again
\r
503 self.mangle_y = self.mangle_y + cvar("g_balance_grenade_nail_anglechange");
\r
504 self.think = W_NailGrenade_Attack;
\r
505 self.nextthink = time + cvar("g_balance_grenade_nail_cluster_rate");
\r
509 // fall to ground & disappear
\r
512 self.touch = SUB_Remove;
\r
513 self.think = self.touch;
\r
514 self.nextthink = time + 3;
\r
515 self.movetype = MOVETYPE_TOSS;
\r
516 self.solid = SOLID_BBOX;
\r
517 self.velocity = '0 0 20';
\r
518 self.avelocity = '300 200 100';
\r
519 setorigin(self, self.origin);
\r
523 void W_NailGrenade_Activate (void)
\r
525 self.velocity = '0 0 0';
\r
526 self.think = W_NailGrenade_Attack;
\r
527 self.nextthink = time + 0.3;
\r
528 // self.origin = self.dest1;
\r
530 self.count = cvar("g_balance_grenade_nail_numclusters");
\r
534 void W_NailGrenade_Deploy (void)
\r
536 float thtime, dheight, spd;
\r
539 self.touch = SUB_Null;
\r
541 dheight = cvar("g_balance_grenade_nail_deployheight");
\r
542 thtime = cvar("g_balance_grenade_nail_deploytime");
\r
543 spd = dheight / thtime;
\r
545 // GRRR! Quake's floor fetish is driving me crazy.
\r
546 // The ONLY way I've found to get the grenade off the floor once it's on
\r
547 // is to delete it and spawn a new entity in its place.
\r
551 self.owner = oldself.owner;
\r
552 self.angles_y = oldself.angles_y;
\r
553 self.angles_x = self.angles_z = 0; // point upright
\r
554 self.mangle = oldself.mangle;
\r
556 setmodel(self, oldself.model);
\r
557 setsize(self, '0 0 0', '0 0 0');
\r
558 setorigin(self, oldself.origin);
\r
559 self.flags = self.flags - (self.flags & FL_ONGROUND);
\r
560 self.oldorigin = self.origin;
\r
562 //self.flags = self.flags - (self.flags & FL_ONGROUND);
\r
563 self.movetype = MOVETYPE_FLY;
\r
564 self.solid = SOLID_NOT;
\r
565 self.velocity = '0 0 1' * spd;
\r
566 self.nextthink = time + thtime;
\r
567 self.think = W_NailGrenade_Activate;
\r
569 self.dest1 = self.origin + '0 0 1'*dheight;
\r
570 traceline(self.origin, self.dest1, TRUE, self);
\r
571 self.dest1 = trace_endpos;
\r
576 void W_NailGrenade_Touch (void)
\r
578 sound (self, CHAN_IMPACT, "weapons/grenade_bounce.wav", 1, ATTN_NORM);
\r
579 traceline(self.origin, self.origin - '0 0 10', TRUE, self);
\r
580 if(self.flags & FL_ONGROUND || trace_fraction < 1)
\r
581 W_NailGrenade_Deploy();
\r
584 void W_NailGrenade()
\r
586 setmodel(self, "models/grenademodel.md3");
\r
587 setsize(self, '-6 -6 -3', '6 6 3');
\r
589 self.takedamage = DAMAGE_NO;
\r
590 self.event_damage = SUB_Null;
\r
592 self.nextthink = time + 2.5;
\r
593 self.think = W_NailGrenade_Activate;
\r
594 self.touch = W_NailGrenade_Touch;
\r
595 self.state = 1; // don't explode on contact with player
\r
596 self.velocity = v_forward * cvar("g_balance_grenade_nail_speed")
\r
597 + v_up * cvar("g_balance_grenade_nail_speed_up");
\r
598 self.avelocity = '100 150 100';
\r
600 self.angles = vectoangles (self.velocity);
\r
602 // decide on a direction to fire in
\r
603 self.mangle_y = self.angles_y;// + 45;
\r
608 //--------------------------------------------
\r
610 void W_MirvGrenade_Explode (void)
\r
613 org2 = findbetterlocation (self.origin);
\r
614 te_explosion (org2);
\r
615 effect (org2, "models/sprites/grenadeexplosion.spr32", 0, 20, 30);
\r
616 sound (self, CHAN_BODY, "weapons/grenade_impact.wav", 1, ATTN_NORM);
\r
618 self.event_damage = SUB_Null;
\r
619 RadiusDamage (self, self.owner, cvar("g_balance_grenade_mirv_damage"), cvar("g_balance_grenade_mirv_edgedamage"), cvar("g_balance_grenade_mirv_radius"), world, cvar("g_balance_grenade_mirv_force"), WEP_GRENADE_MIRV);
\r
624 void W_MirvBomb(vector org, vector vel)
\r
628 gren.owner = self.owner;
\r
629 gren.classname = "grenade";
\r
630 gren.movetype = MOVETYPE_BOUNCE;
\r
631 gren.solid = SOLID_BBOX;
\r
632 setmodel(gren, "models/grenademodel.md3");
\r
633 //setsize(self, '-6 -6 -3', '6 6 3');
\r
634 setsize(gren, '0 0 0', '0 0 0');
\r
635 setorigin(gren, org);
\r
637 gren.nextthink = time + 2 + crandom()*0.15;
\r
638 gren.think = W_MirvGrenade_Explode;
\r
639 gren.touch = W_Grenade_DefaultTouch;
\r
640 gren.state = 1; // don't explode on contact
\r
641 gren.takedamage = DAMAGE_YES;
\r
643 gren.damageforcescale = 4;
\r
644 gren.event_damage = W_Grenade_DefaultDamage;
\r
645 gren.velocity = vel;
\r
646 gren.avelocity = '100 150 100' * (1 + crandom()*0.5);
\r
647 gren.angles = vectoangles (gren.velocity);
\r
651 void W_MirvGrenade_Split (void)
\r
653 float num, maxnum, spread;
\r
655 sound (self, CHAN_IMPACT, "weapons/grenade_bounce.wav", 1, ATTN_NORM);
\r
657 if(self.flags & FL_ONGROUND)
\r
659 //traceline(self.origin, self.origin - '0 0 5', TRUE, self);
\r
660 //dir = normalize(self.velocity) + trace_plane_normal + '0 0 1';
\r
661 //dir = normalize(dir * (1/3));
\r
662 dir = normalize(self.velocity)*0.2 + normalize('0 0 1');
\r
663 dir = normalize(dir);
\r
667 dir = normalize(self.velocity);
\r
670 spread = cvar("g_balance_grenade_mirv_spread");
\r
672 maxnum = cvar("g_balance_grenade_mirv_count");
\r
673 for (num = 0; num < maxnum; num = num + 1)
\r
675 vel_x = dir_x + crandom()*spread;
\r
676 vel_y = dir_y + crandom()*spread;
\r
677 vel_z = dir_z + crandom()*spread;
\r
678 vel = normalize(vel) * cvar("g_balance_grenade_mirv_speed2");
\r
679 W_MirvBomb(self.origin, vel);
\r
684 void W_MirvGrenade()
\r
686 setmodel(self, "models/grenademodel.md3");
\r
687 setsize(self, '-6 -6 -3', '6 6 3');
\r
689 self.nextthink = time + 2.5;
\r
690 self.think = W_MirvGrenade_Split;
\r
691 self.touch = W_MirvGrenade_Split;
\r
692 self.velocity = v_forward * cvar("g_balance_grenade_mirv_speed")
\r
693 + v_up * cvar("g_balance_grenade_mirv_speed_up");
\r
694 self.avelocity = '100 150 100';
\r
696 self.angles = vectoangles (self.velocity);
\r
700 //--------------------------------------------
\r
702 void W_FragGrenade_Explode (void)
\r
705 org2 = findbetterlocation (self.origin);
\r
706 te_explosion (org2);
\r
707 effect (org2, "models/sprites/grenadeexplosion.spr32", 0, 20, 30);
\r
708 sound (self, CHAN_BODY, "weapons/rocket_impact.wav", 1, ATTN_NORM);
\r
709 sound (self, CHAN_VOICE, "weapons/grenade_impact.wav", 1, ATTN_NORM);
\r
711 self.event_damage = SUB_Null;
\r
712 RadiusDamage (self, self.owner, cvar("g_balance_grenade_frag_damage"), cvar("g_balance_grenade_frag_edgedamage"), cvar("g_balance_grenade_frag_radius"), world, cvar("g_balance_grenade_frag_force"), WEP_GRENADE_FRAG);
\r
717 void W_FragGrenade()
\r
719 setmodel(self, "models/grenademodel.md3");
\r
720 setsize(self, '-6 -6 -3', '6 6 3');
\r
722 self.nextthink = time + 2;//1.5 + random()*0.5;
\r
723 self.think = W_FragGrenade_Explode;
\r
724 self.touch = W_Grenade_DefaultTouch;
\r
725 self.state = 1; // don't explode on contact with player
\r
726 self.velocity = v_forward * cvar("g_balance_grenade_frag_speed")
\r
727 + v_up * cvar("g_balance_grenade_frag_speed_up");
\r
728 self.avelocity = '100 150 100';
\r
730 self.angles = vectoangles (self.velocity);
\r
733 //--------------------------------------------
\r
735 void PoisonGrenadeGib(entity gib, string mdlname, vector org, vector v, float destroyontouch)
\r
738 e = TossGib(gib, mdlname, org, v, destroyontouch);
\r
739 e.colormod = 5 * '0 1 0'; // bright green
\r
742 e.velocity = e.velocity * e.gravity;// * 0.8;
\r
745 void W_PoisonGrenade_Explode (void)
\r
750 org2 = findbetterlocation (self.origin);
\r
751 org1 = org2 + '0 0 5';
\r
752 te_explosionrgb (org2, (1/255)*'0 255 0');
\r
753 sound (trace_ent, CHAN_VOICE, "misc/gib.wav", 1, ATTN_NORM);
\r
754 PoisonGrenadeGib (world, "models/gibs/gib5.md3", org1, '-500 0 450',1);
\r
755 PoisonGrenadeGib (world, "models/gibs/gib6.md3", org1, '0 500 450',1);
\r
756 PoisonGrenadeGib (world, "models/gibs/gib6.md3", org1, '0 -500 450',1);
\r
757 PoisonGrenadeGib (world, "models/gibs/gib6.md3", org1, '500 0 450',1);
\r
758 PoisonGrenadeGib (world, "models/gibs/chunk.mdl", org1, '0 0 450',1);
\r
761 head = findradius(self.origin, cvar("g_balance_grenade_poison_radius"));
\r
764 if(head.classname == "player") // only players can be poisoned
\r
766 traceline(self.origin, head.origin, TRUE, self);
\r
767 if(trace_fraction >= 1)
\r
769 PoisonTarget(head, cvar("g_balance_grenade_poison_damage"), cvar("g_balance_grenade_poison_duration"), TRUE);
\r
770 //bprint(strcat(head.netname, " is poisoned for ", ftos(head.poison_damage), " damage\n"));
\r
779 void W_PoisonGrenade()
\r
781 setmodel(self, "models/grenademodel.md3");
\r
782 setsize(self, '-6 -6 -3', '6 6 3');
\r
784 self.nextthink = time + 1.5 + random()*0.5;
\r
785 self.think = W_PoisonGrenade_Explode;
\r
786 self.touch = W_Grenade_DefaultTouch;
\r
787 self.state = 1; // don't explode on contact with player
\r
788 self.velocity = v_forward * cvar("g_balance_grenade_poison_speed")
\r
789 + v_up * cvar("g_balance_grenade_poison_speed_up");
\r
790 self.avelocity = '100 150 100';
\r
792 self.angles = vectoangles (self.velocity);
\r
795 //--------------------------------------------
\r
797 void W_ArmorGrenade_Explode (void)
\r
802 org2 = findbetterlocation (self.origin);
\r
803 te_explosion (org2);
\r
804 effect (org2, "models/sprites/grenadeexplosion.spr32", 0, 20, 30);
\r
805 sound (self, CHAN_BODY, "weapons/grenade_impact.wav", 1, ATTN_NORM);
\r
807 head = findradius(self.origin, cvar("g_balance_grenade_armor_radius"));
\r
810 if(head.classname == "player") // only players are affected
\r
812 traceline(self.origin, head.origin, TRUE, self);
\r
813 if(trace_fraction >= 1)
\r
815 head.armorvalue = 0; // wipe out target's armor
\r
824 void W_ArmorGrenade()
\r
826 setmodel(self, "models/grenademodel.md3");
\r
827 setsize(self, '-6 -6 -3', '6 6 3');
\r
829 self.nextthink = time + 1.5 + random()*0.5;
\r
830 self.think = W_ArmorGrenade_Explode;
\r
831 self.touch = W_Grenade_DefaultTouch;
\r
832 self.state = 1; // don't explode on contact with player
\r
833 self.velocity = v_forward * cvar("g_balance_grenade_armor_speed")
\r
834 + v_up * cvar("g_balance_grenade_armor_speed_up");
\r
835 self.avelocity = '100 150 100';
\r
837 self.angles = vectoangles (self.velocity);
\r
840 //--------------------------------------------
\r