home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-29 | 81.8 KB | 3,228 lines |
- /*
-
- The Mark I SuperScream Grenade Machine v1.0
- by Klaus Breuer (sz0759@rzmail.uni-erlangen.de)
-
- This patch adds a lot of new ammo for the grenade launcher, my favourite
- weapon: 12 new grenades!
-
- See ImpulseCommands() at the end of this file for a list of
- all possible grenades. Also check ClientConnect() in CLIENT.QC.
-
- I wasn't able to add a new variable to the player object (anybody who
- can tell me how to do that?), so I used the self.button1 (which isn't
- used by the game) to remember which ammo type is selected.
-
- A lot of these ammo types are way too powerful - you might want to
- disable them or tone them down (cause them to use more ammo, cause
- damage to the user, etc). I just use them for fun and messing about :)
-
- To disable any ammo type, you'll need to look at these functions:
- ImpulseCommands() // Selecting ammo type
- ShowGrenadeType() // Identify currently loaded ammo
- W_FireGrenade() // Select which grenade to fire
- ClientConnect() // Show info on available ammo (in CLIENT.QC)
-
-
- Notes:
-
- * I purposely made each ammo type totally self-contained, so you can
- easily port them to your own code.
- * I tried to document a lot so you can easily make changes.
- * This is mostly my own code, but quite a few ideas/code bits were
- from other people. Sorry, I forgot which ones (thought too late of
- making a list), so if you recognize your work, drop me a mail.
-
- */
- void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
- void () player_run;
- void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
- void(vector org, vector vel, float damage) SpawnBlood;
- void() SuperDamageSound;
-
-
- // called by worldspawn
- void() W_Precache =
- {
- precache_sound ("weapons/r_exp3.wav"); // new rocket explosion
- precache_sound ("weapons/rocket1i.wav"); // spike gun
- precache_sound ("weapons/sgun1.wav");
- precache_sound ("weapons/guncock.wav"); // player shotgun
- precache_sound ("weapons/ric1.wav"); // ricochet (used in c code)
- precache_sound ("weapons/ric2.wav"); // ricochet (used in c code)
- precache_sound ("weapons/ric3.wav"); // ricochet (used in c code)
- precache_sound ("weapons/spike2.wav"); // super spikes
- precache_sound ("weapons/tink1.wav"); // spikes tink (used in c code)
- precache_sound ("weapons/grenade.wav"); // grenade launcher
- precache_sound ("weapons/bounce.wav"); // grenade bounce
- precache_sound ("weapons/shotgn2.wav"); // super shotgun
-
- precache_sound ("talk/scum.wav"); // Duke: Scumsucker
-
- };
-
- float() crandom =
- {
- return 2*(random() - 0.5);
- };
-
- /*
- ================
- W_FireAxe
- ================
- */
- void() W_FireAxe =
- {
- local vector source;
- local vector org;
-
- source = self.origin + '0 0 16';
- traceline (source, source + v_forward*64, FALSE, self);
- if (trace_fraction == 1.0)
- return;
-
- org = trace_endpos - v_forward*4;
-
- if (trace_ent.takedamage)
- {
- trace_ent.axhitme = 1;
- SpawnBlood (org, '0 0 0', 20);
- T_Damage (trace_ent, self, self, 20);
- }
- else
- { // hit wall
- sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_GUNSHOT);
- WriteCoord (MSG_BROADCAST, org_x);
- WriteCoord (MSG_BROADCAST, org_y);
- WriteCoord (MSG_BROADCAST, org_z);
- }
- };
-
-
- //============================================================================
-
-
- 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
- ================
- */
- void(vector org, vector vel) SpawnMeatSpray =
- {
- local entity missile, mpuff;
- local vector org;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_NOT;
-
- makevectors (self.angles);
-
- missile.velocity = vel;
- missile.velocity_z = missile.velocity_z + 250 + 50*random();
-
- missile.avelocity = '3000 1000 2000';
-
- // set missile duration
- missile.nextthink = time + 1;
- missile.think = SUB_Remove;
-
- setmodel (missile, "progs/zom_gib.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, org);
- };
-
- /*
- ================
- SpawnBlood
- ================
- */
- void(vector org, vector vel, float damage) SpawnBlood =
- {
- particle (org, vel*0.1, 73, damage*2);
- };
-
- /*
- ================
- spawn_touchblood
- ================
- */
- void(float damage) spawn_touchblood =
- {
- local vector vel;
-
- vel = wall_velocity () * 0.2;
- SpawnBlood (self.origin + vel*0.01, vel, damage);
- };
-
-
- /*
- ================
- SpawnChunk
- ================
- */
- void(vector org, vector vel) SpawnChunk =
- {
- particle (org, vel*0.02, 0, 10);
- };
-
- /*
- ==============================================================================
-
- MULTI-DAMAGE
-
- Collects multiple small damages into a single damage
-
- ==============================================================================
- */
-
- entity multi_ent;
- float multi_damage;
-
- void() ClearMultiDamage =
- {
- multi_ent = world;
- multi_damage = 0;
- };
-
- void() ApplyMultiDamage =
- {
- if (!multi_ent)
- return;
- T_Damage (multi_ent, self, self, multi_damage);
- };
-
- void(entity hit, float damage) AddMultiDamage =
- {
- if (!hit)
- return;
-
- if (hit != multi_ent)
- {
- ApplyMultiDamage ();
- multi_damage = damage;
- multi_ent = hit;
- }
- else
- multi_damage = multi_damage + damage;
- };
-
- /*
- ==============================================================================
-
- BULLETS
-
- ==============================================================================
- */
-
- /*
- ================
- TraceAttack
- ================
- */
- void(float damage, vector dir) TraceAttack =
- {
- local vector vel, org;
-
- vel = normalize(dir + v_up*crandom() + v_right*crandom());
- vel = vel + 2*trace_plane_normal;
- vel = vel * 200;
-
- org = trace_endpos - dir*4;
-
- if (trace_ent.takedamage)
- {
- SpawnBlood (org, vel*0.2, damage);
- AddMultiDamage (trace_ent, damage);
- }
- else
- {
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_GUNSHOT);
- WriteCoord (MSG_BROADCAST, org_x);
- WriteCoord (MSG_BROADCAST, org_y);
- WriteCoord (MSG_BROADCAST, org_z);
- }
- };
-
- /*
- ================
- FireBullets
-
- Used by shotgun, super shotgun, and enemy soldier firing
- Go to the trouble of combining multiple pellets into a single damage call.
- ================
- */
- void(float shotcount, vector dir, vector spread) FireBullets =
- {
- local vector direction;
- local vector src;
-
- makevectors(self.v_angle);
-
- src = self.origin + v_forward*10;
- src_z = self.absmin_z + self.size_z * 0.7;
-
- ClearMultiDamage ();
- while (shotcount > 0)
- {
- direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
-
- traceline (src, src + direction*2048, FALSE, self);
- if (trace_fraction != 1.0)
- TraceAttack (4, direction);
-
- shotcount = shotcount - 1;
- }
- ApplyMultiDamage ();
- };
-
- /*
- ================
- W_FireShotgun
- ================
- */
- void() W_FireShotgun =
- {
- local vector dir;
-
- sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- self.currentammo = self.ammo_shells = self.ammo_shells - 1;
- dir = aim (self, 100000);
- FireBullets (6, dir, '0.04 0.04 0');
- };
-
-
- /*
- ================
- W_FireSuperShotgun
- ================
- */
- void() W_FireSuperShotgun =
- {
- local vector dir;
-
- if (self.currentammo == 1)
- {
- W_FireShotgun ();
- return;
- }
-
- sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -4;
-
- self.currentammo = self.ammo_shells = self.ammo_shells - 2;
- dir = aim (self, 100000);
- FireBullets (14, dir, '0.14 0.08 0');
- };
-
-
- /*
- ==============================================================================
-
- ROCKETS
-
- ==============================================================================
- */
-
- void() s_explode1 = [0, s_explode2] {};
- void() s_explode2 = [1, s_explode3] {};
- void() s_explode3 = [2, s_explode4] {};
- void() s_explode4 = [3, s_explode5] {};
- void() s_explode5 = [4, s_explode6] {};
- void() s_explode6 = [5, SUB_Remove] {};
-
- void() BecomeExplosion =
- {
- self.movetype = MOVETYPE_NONE;
- self.velocity = '0 0 0';
- self.touch = SUB_Null;
- setmodel (self, "progs/s_explod.spr");
- self.solid = SOLID_NOT;
- s_explode1 ();
- };
-
- void() T_MissileTouch =
- {
- local float damg;
-
- if (other == self.owner)
- return; // don't explode on owner
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
-
- damg = 100 + random()*20;
-
- if (other.health)
- {
- if (other.classname == "monster_shambler")
- damg = damg * 0.5; // mostly immune
- T_Damage (other, self, self.owner, damg );
- }
-
- // don't do radius damage to the other, because all the damage
- // was done in the impact
- T_RadiusDamage (self, self.owner, 120, other);
-
- // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
- self.origin = self.origin - 8*normalize(self.velocity);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
-
- BecomeExplosion ();
- };
-
-
-
- /*
- ================
- W_FireRocket
- ================
- */
- void() W_FireRocket =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 1000;
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = T_MissileTouch;
-
- // set missile duration
- missile.nextthink = time + 5;
- missile.think = SUB_Remove;
-
- setmodel (missile, "progs/missile.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward*8 + '0 0 16');
- };
-
- /*
- ===============================================================================
-
- LIGHTNING
-
- ===============================================================================
- */
-
- /*
- =================
- LightningDamage
- =================
- */
- void(vector p1, vector p2, entity from, float damage) LightningDamage =
- {
- local entity e1, e2;
- local vector f;
-
- f = p2 - p1;
- normalize (f);
- f_x = 0 - f_y;
- f_y = f_x;
- f_z = 0;
- f = f*16;
-
- e1 = e2 = world;
-
- traceline (p1, p2, FALSE, self);
- if (trace_ent.takedamage)
- {
- particle (trace_endpos, '0 0 100', 225, damage*4);
- T_Damage (trace_ent, from, from, damage);
- if (self.classname == "player")
- {
- if (other.classname == "player")
- trace_ent.velocity_z = trace_ent.velocity_z + 400;
- }
- }
- e1 = trace_ent;
-
- traceline (p1 + f, p2 + f, FALSE, self);
- if (trace_ent != e1 && trace_ent.takedamage)
- {
- particle (trace_endpos, '0 0 100', 225, damage*4);
- T_Damage (trace_ent, from, from, damage);
- }
- e2 = trace_ent;
-
- traceline (p1 - f, p2 - f, FALSE, self);
- if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
- {
- particle (trace_endpos, '0 0 100', 225, damage*4);
- T_Damage (trace_ent, from, from, damage);
- }
- };
-
-
- void() W_FireLightning =
- {
- local vector org;
-
- if (self.ammo_cells < 1)
- {
- self.weapon = W_BestWeapon ();
- W_SetCurrentAmmo ();
- return;
- }
-
- // explode if under water
- if (self.waterlevel > 1)
- {
- T_RadiusDamage (self, self, 35*self.ammo_cells, world);
- self.ammo_cells = 0;
- W_SetCurrentAmmo ();
- return;
- }
-
- if (self.t_width < time)
- {
- sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
- self.t_width = time + 0.6;
- }
- self.punchangle_x = -2;
-
- self.currentammo = self.ammo_cells = self.ammo_cells - 1;
-
- org = self.origin + '0 0 16';
-
- traceline (org, org + v_forward*600, TRUE, self);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
- WriteEntity (MSG_BROADCAST, self);
- WriteCoord (MSG_BROADCAST, org_x);
- WriteCoord (MSG_BROADCAST, org_y);
- WriteCoord (MSG_BROADCAST, org_z);
- WriteCoord (MSG_BROADCAST, trace_endpos_x);
- WriteCoord (MSG_BROADCAST, trace_endpos_y);
- WriteCoord (MSG_BROADCAST, trace_endpos_z);
-
- LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
- };
-
-
-
- //=============================================================================
-
- 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.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;
- local entity old;
-
- sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
- self.attack_finished = time + 0.2;
- 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);
- self.punchangle_x = -2;
- };
-
- void(float ox) W_FireSpikes =
- {
- local vector dir;
- local entity old;
-
- 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 ();
- W_SetCurrentAmmo ();
- return;
- }
-
- sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
- self.attack_finished = time + 0.2;
- self.currentammo = self.ammo_nails = self.ammo_nails - 1;
- dir = aim (self, 1000);
- launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
-
- self.punchangle_x = -2;
- };
-
-
-
- .float hit_z;
- void() spike_touch =
- {
- local float rand;
- if (other == self.owner)
- return;
-
- 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 (9);
- T_Damage (other, self, self.owner, 9);
- }
- else
- {
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
-
- if (self.classname == "wizspike")
- WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
- else if (self.classname == "knightspike")
- WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
- else
- WriteByte (MSG_BROADCAST, TE_SPIKE);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
- }
-
- remove(self);
-
- };
-
- void() superspike_touch =
- {
- local float rand;
- if (other == self.owner)
- return;
-
- 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);
- }
- else
- {
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
- }
-
- remove(self);
-
- };
-
- //=============================================================================
-
- /*
- ============
- The standard bouncing grenade
- Well-known and -loved.
- ============
- */
- void() GrenadeExplode =
- {
- T_RadiusDamage (self, self.owner, 120, world);
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_EXPLOSION);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
-
- BecomeExplosion ();
- };
-
- 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_FireNormalGrenade
- ================
- */
- void() W_FireNormalGrenade =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
-
- // set missile speed
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = GrenadeTouch;
-
- // set missile duration
- missile.nextthink = time + 2.5;
- missile.think = GrenadeExplode;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
-
- /*
- =====================
- Nail Bomb Grenade
-
- As seen in 'Eraser', it bounces to a stop, waits a few moments,
- pops up and explodes in a downward shower of nails.
- =====================
- */
-
- void(vector org) launch_burst_spike =
- {
- newmis = spawn ();
- newmis.owner = self;
- newmis.movetype = MOVETYPE_FLYMISSILE;
- newmis.solid = SOLID_BBOX;
-
- newmis.velocity_x=(random()*2 - 1)*2000; //Highspeed, random direction
- newmis.velocity_y=(random()*2 - 1)*2000;
- newmis.velocity_z=(random() - 1)*2000;
-
- newmis.touch = superspike_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);
-
- };
-
- void() NailBombBurst = // Explode in a shower of nails
- {
- local float nnum = 0;
-
- // Bompf...
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- // Turn into a fireball...
-
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); // Light
- WriteByte (MSG_BROADCAST, TE_EXPLOSION); // Pixel-explosion
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
-
- self.movetype = MOVETYPE_NONE;
- self.velocity = '0 0 0';
- self.touch = SUB_Null;
- setmodel (self, "progs/s_explod.spr");
- self.solid = SOLID_NOT;
-
- // Throw lots of spikes in random directions
- while (nnum < 50)
- {
- launch_burst_spike (self.origin);
- nnum = nnum + 1;
- }
-
- // Disappear
- remove(self);
-
- };
-
- void() NailBombThink =
- // If enough time has passed, hop up and explode
- {
- self.nextthink = time + 0.5;
- self.think = NailBombThink;
-
- if (self.wait < time)
- {
- self.velocity_x=0;
- self.velocity_y=0;
- self.velocity_z=750;
- if (self.flags & FL_ONGROUND) self.flags = self.flags - FL_ONGROUND;
- self.nextthink = time + 0.2;
- self.think = NailBombBurst;
- }
- };
-
- void() NailBombTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
- if (other.takedamage == DAMAGE_AIM)
- return;
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- void() W_FireNailBomb =
- {
- local entity missile, mpuff;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
- missile.wait = time + 2 + 5*random(); //blow up after a few seconds
-
- // set missile speed
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = NailBombTouch;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
- missile.nextthink = time + 1; // Gets live real quick
- missile.think = NailBombThink;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- ======================
- Bouncing cluster bomb
-
- The grenade bursts into 5 sub-munitions, which hop about.
- If they reach near a target, they jump towards it and explode.
- They'll explode on their own sooner or later.
- PS: This lovely is what got me started - it's slightly modified (grenades
- hopped for ever) from the CBP Grenade, designed by:
- John Spickes jspickes@eng.umd.edu {JDS}
- Josh Spickes spickesj@wam.umd.edu
- Allen Seger
- Thanks, guys.
- =======================
- */
-
- void() BCGrenadeThink =
- // Hop about, looking for a victim
- {
- local entity head;
- local vector dir;
- if(self.flags & FL_ONGROUND) {
- // Don't detect targets if I'm not on the ground
- head = findradius(self.origin, 300);
- while(head) {
- if (head.takedamage) {
- if (self.avelocity == '0 0 0')
- self.avelocity = '300 300 300';
- self.origin_z = self.origin_z + 1;
- dir = normalize(head.origin - self.origin);
- self.velocity = dir*200 + '0 0 500';
- if (self.flags & FL_ONGROUND)
- self.flags = self.flags - FL_ONGROUND;
-
- self.nextthink = time + random()*1.5;
- self.think = GrenadeExplode;
- return;
- }
- head = head.chain;
- }
- }
- self.nextthink = time + 0.5;
- self.think = BCGrenadeThink;
- if(self.wait < time) // Time to jump
- {
- if (random() < 0.3) self.think = GrenadeExplode;
- self.wait = time + 5 + 5*random();
- if (self.avelocity == '0 0 0')
- self.avelocity = '300 300 300';
- self.origin_z = self.origin_z + 1;
- self.velocity_x=(random()*400 - 200);
- self.velocity_y=(random()*400 - 200);
- self.velocity_z = 500;
- if (self.flags & FL_ONGROUND)
- self.flags = self.flags - FL_ONGROUND;
- }
- };
-
- void() BCGrenadeTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
- if (other.takedamage == DAMAGE_AIM)
- return; // Don't explode on target impact
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- void() BCGrenadeDeploy =
- // Spray out 5 submunitions
- {
- local float gnum = 0;
- local entity missile;
-
- while(gnum < 5) {
- missile = spawn ();
- missile.owner = self.owner;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
- missile.wait = time + 5 + 5*random();
- missile.think = BCGrenadeThink;
- missile.nextthink = time + 0.5;
- missile.velocity_z = 500;
- missile.velocity_x = 400*random() - 200;
- missile.velocity_y = 400*random() - 200;
- gnum = gnum + 1;
- missile.avelocity = '300 300 300';
- missile.angles = vectoangles(missile.velocity);
- missile.touch = BCGrenadeTouch;
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- }
- self.think = GrenadeExplode;
- self.nextthink = time + 0.1;
- };
-
- void() W_FireBCGrenade =
- {
- local entity missile, mpuff;
-
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
- missile.wait = time + 5 + 5*random();
-
- // set missile speed
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = BCGrenadeTouch;
-
- // If we have enough for a cluster, fire a cluster, otherwise
- // fire a bouncer.
- if (self.ammo_rockets > 4) {
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
- missile.nextthink = time + 2+(random()*3);
- missile.think = BCGrenadeDeploy;
- }
- else {
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
- missile.think = BCGrenadeThink;
- missile.nextthink = time + 2+(random()*2);
- }
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- =====================
- Ricochet grenade
-
- Flies at high speed and bounces for a fair while before exploding.
- Unless it hits somebody first >:)
- ======================
- */
- void() RicochetTouch =
- {
- 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
-
- self.velocity = self.velocity * 1.2; // Keep your speed
-
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
-
- void() W_FireRicochet =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 1000;
- missile.velocity_z = 200;
- missile.angles = vectoangles(missile.velocity);
-
- missile.nextthink = time + 5 + random()*5;
- missile.think = GrenadeExplode;
- missile.touch = RicochetTouch;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- =====================
- Glue bomb
-
- Flies straight like a missile and sticks to the target, possibly floating
- in the air.
- Then it blows.
- ======================
- */
-
- void() GlueStick =
- {
- if (random() < 0.02) // Check if it blows
- {
- self.think = GrenadeExplode; // Boom
- self.touch = GrenadeExplode;
- }
- else
- {
- self.think = GlueStick; // Keep sticking
- self.touch = GlueStick;
- }
-
- if ((self.enemy != world) && (self.enemy.health > 1))
- {
- self.origin=self.enemy.origin; // stick with the target
- if (self.velocity == '0 0 0') self.avelocity = '0 0 0';
- }
- self.nextthink = time + 0.1;
-
- };
-
- void() GlueTouch =
- {
- if (other == self.owner)
- return; // don't stick to owner
-
- sound (self, CHAN_WEAPON, "misc/outwater.wav", 1, ATTN_NORM);
- self.think = GlueStick;
- self.touch = GlueStick;
- self.nextthink = time + 0.1;
- self.velocity = self.velocity * 0; // Stop right there (floats)
- self.avelocity = '0 0 0';
- self.enemy = other;
- };
-
- void() W_FireGlue =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 1000;
- missile.angles = vectoangles(missile.velocity);
-
- missile.nextthink = time + 5; // Blow after 5s uninterrupted flight
- missile.think = GrenadeExplode;
- missile.touch = GlueTouch;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- =====================
- MG Point Defense
-
- Gets live after a few seconds, turns into a nailgun,
- shooting at everything in sight. Explodes after a while.
- =====================
- */
-
- void(vector org, vector d) MGShoot =
- // Shoot once in direction d
- {
- sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
- launch_spike (org + '0 0 16', d);
- newmis.touch = superspike_touch;
- setmodel (newmis, "progs/spike.mdl");
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- };
-
- void() MGThink =
- // Scan for anything alive
- {
- local entity head;
- local vector dir;
-
- self.nextthink = time + 1; // 1s pause between target searches
- self.think = MGThink;
-
- head = findradius(self.origin, 1500); // Look for opponents
- while(head) // found something
- {
- if (head.takedamage) // can be damaged
- {
- if ((self.owner != head) && (head.classname != "monster_zombie")) // Not owner or zombie
- {
- if ((coop && (head.classname == "player")) != 1) // Not player in coop
- {
- if (visible(head) == 1) // Can see it!
- {
- dir = normalize(head.origin - self.origin); // Get direction
- self.ideal_yaw = vectoyaw(head.origin - self.origin);
- self.angles_y = self.ideal_yaw;
- self.angles_x = 0;
- self.angles_z = 0;
-
- MGShoot (self.origin,dir); // Shoot at it
- }
- }
- }
- }
- head = head.chain; // next
- }
-
- if (self.wait < time) // self-destruct
- {
- self.nextthink = time + 0.2;
- self.think = GrenadeExplode;
- }
- };
-
- void() MGDeploy =
- // Turn into an MG.
- // Since I can't build an MG shape yet, I'm using a standard player head
- {
- setmodel (self, "progs/h_player.mdl");
- self.angles = '0 0 0';
- sound (self, CHAN_WEAPON, "misc/outwater.wav", 1, ATTN_NORM);
-
- self.think = MGThink;
- self.nextthink = time + random()*2;
- self.wait = time + 20 + random()*20; // Active lifespan
- };
-
- void() MGTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
- if (other.takedamage == DAMAGE_AIM)
- return;
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- void() W_FireMG =
- {
- local entity missile, mpuff;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
- missile.wait = time + 2 + 5*random(); //blow up after a few seconds
-
- // set missile speed
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = MGTouch;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
- missile.nextthink = time + 2 + random()*5; // Takes a few seconds to deploy
- missile.think = MGDeploy;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- ===============
- Vampire Bolt
-
- Gives YOU the HP the opponent lost by being hit with this
- ================
- */
- void() VampTouch =
- {
- local float damg;
- local float oldhealth,healthgained;
- local string s;
-
- if (other == self.owner)
- return; // don't explode on owner
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
-
- damg = 5 + random()*15;
-
- if ((other.health) && (other.classname == "player"))
- {
- oldhealth = other.health;
- T_Damage (other, self, self.owner, damg );
- spawn_touchblood(damg);
- if (other.health <= 0) { healthgained = oldhealth; }
- else { healthgained = oldhealth-other.health; }
- T_Heal(self.owner,healthgained,0);
- sprint(self.owner, "You drain ");
- s = ftos(healthgained);
- sprint(self.owner, s);
- sprint(self.owner, " health\n");
- // Tell victim about it
- sprint(other,self.owner.netname);
- sprint(other," drains ");
- sprint(other, s);
- sprint(other, " health from you\n");
- }
-
- remove(self);
- };
-
-
- void() W_FireVamp =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 1000;
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = VampTouch;
-
- // set missile duration
- missile.nextthink = time + 5;
- missile.think = SUB_Remove;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward*8 + '0 0 16');
- };
-
- /*
- ==========
- Medic Bolt
-
- Heals the target by a small amount
- ==========
- */
- void() MedicTouch =
- {
- local string s;
- local float heal_p,oldhealth;
-
- if (other == self.owner)
- return; // don't explode on owner
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
- if (other.classname != "player") { remove(self); return; }
-
- heal_p = 5 + random()*15;
-
- if (other.health)
- {
- oldhealth = other.health;
- T_Heal(other,heal_p,0);
- heal_p = other.health - oldhealth;
- sprint(self.owner, "You heal ");
- s = ftos(heal_p);
- sprint(self.owner, s);
- sprint(self.owner, " health\n");
- sprint(other,self.owner.netname);
- sprint(other," heals ");
- sprint(other, s);
- sprint(other, " health for you\n");
- }
-
- remove(self);
- };
-
- void() W_FireMedic =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 1000;
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = MedicTouch;
-
- // set missile duration
- missile.nextthink = time + 5;
- missile.think = SUB_Remove;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward*8 + '0 0 16');
- };
-
- /*
- ==========
- Armor Piercing
-
- Goes straight through the targets until it hits a wall
- ==========
- */
-
- void() APRemove =
- {
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); // Piiing
- WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
- remove(self);
- };
-
- void() APTouch =
- {
- local float dam;
-
- if (other == self.owner)
- return; // don't explode on owner
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
-
- if (other.takedamage) // damage it
- {
- dam = 50 + random()*20;
- spawn_touchblood(dam);
- T_Damage (other, self, self.owner, dam );
- }
- else
- {
- APRemove; // Disappear against the wall
- }
-
- };
-
- void() W_FireAP =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLY;
- missile.solid = SOLID_TRIGGER;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 1000;
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = APTouch;
-
- // set missile duration
- missile.nextthink = time + 5; // Disappear after 5s
- missile.think = SUB_Remove;
-
- setmodel (missile, "progs/spike.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward*8 + '0 0 16');
- };
-
- /*
- ==============
- Radio Tag Bomb
-
- Is detonated by command only and can be disarmed by command as well.
- If it hits a valid target, it'll stick to it and can be blown at
- any time. Otherwise, it acts like the pipe bomb from Duke3D.
- ==============
- */
-
- void() DetonateRTB =
- // Detonate all owned RTBs in range (10000)
- {
- local entity head;
-
- head = findradius (self.origin, 10000); // Search
- while(head) // Found something
- {
- if((head.classname == "RTB") && (head.owner == self)) // It's a bomb, belonging to us
- {
- head.think = GrenadeExplode; // Tell it to blow up...
- head.nextthink = time; // ...right away
- }
- head = head.chain; // Check next object
- }
- };
-
- void() DisarmRTB =
- // Disarm all owned RTBs in range (10000)
- {
- local entity head;
-
- head = findradius (self.origin, 10000); // Start looking
- while(head) // Found an object
- {
- if((head.classname == "RTB") && (head.owner == self)) // It's our RTB
- {
- sprint (self,"You untagged "); // Notify owner
- if (head.enemy.classname == "player")
- {
- sprint (self,head.enemy.netname);
- sprint (self,"\n");
- sprint (head.enemy,self.netname); // Tell target
- sprint (head.enemy," untagged his RTB\n");
- }
- else // Not a human player; return name of monster
- {
- sprint (self, "a ");
- sprint (self, head.enemy.classname);
- sprint (self,"\n");
- }
- head.movetype = MOVETYPE_NONE; // Remove yourself immediately
- head.velocity = '0 0 0';
- head.touch = SUB_Null;
- head.think = SUB_Remove;
- head.nextthink = time;
- }
- head = head.chain; // Check next
- }
- return;
- };
-
- void() TaggedRTBTouch =
- {
- self.origin = self.enemy.origin; // stick with enemy
- if (self.velocity == '0 0 0') self.avelocity = '0 0 0';
- };
-
- void() RTBTouch =
- {
- if (other == self.owner) return; // don't explode on owner
-
- if (other.takedamage == DAMAGE_AIM)
- {
- if (!self.enemy)
- {
- sound(self, CHAN_WEAPON, "weapons/tink1.wav", 1, ATTN_NORM);
- self.think = GrenadeExplode;
- }
- self.enemy = other;
- self.origin = self.enemy.origin; // Stick to target
- if (self.effects != EF_DIMLIGHT) // We're not glowing yet
- {
- sprint (self.owner, "You tagged "); // Tell owner about it
- if (self.enemy.classname == "player") // Tagged an opponent
- {
- sprint (self.owner, self.enemy.netname);
- sprint (self.owner, "\n");
- sprint (self.enemy, "You have been tagged by "); // tell opponent
- sprint (self.enemy, self.owner.netname);
- sprint (self.enemy, "\n");
- }
- else // Not human player; get name of monster
- {
- sprint (self.owner, "a ");
- sprint (self.owner, self.enemy.classname);
- sprint (self.owner, "\n");
- }
- self.effects = EF_DIMLIGHT; // Start glowing
- self.think = TaggedRTBTouch;
- self.touch = TaggedRTBTouch;
- self.nextthink = time;
- }
- }
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0') self.avelocity = '0 0 0';
- };
-
- void() W_FireRTB =
- {
- local entity missile, mpuff;
-
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "RTB"; // Radio Tag Bomb
- missile.wait = time + 5 + 5*random();
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = RTBTouch;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
- missile.think = GrenadeExplode;
- missile.nextthink = time + 10; // Explode if didn't touch anything after 10s
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- ==========
- Ammo Cache
-
- Grenade turns into backpack which contains 20 of each ammo, if the
- user has as much. Useful for feeding your buddies or building caches.
- ==========
- */
-
- void() AmmoCacheDeploy =
- // Turn into backpack
- {
- self.flags = FL_ITEM;
- self.solid = SOLID_TRIGGER;
- self.movetype = MOVETYPE_TOSS;
-
- self.origin_z = self.origin_z + 20; // Pop up a bit
- self.angles = self.angles * 0; // Stand upright
- setmodel (self, "progs/backpack.mdl");
- setsize(self, '-16 -16 0', '16 16 56');
- sound (self, CHAN_WEAPON, "misc/outwater.wav", 1, ATTN_NORM); // Deploy sound
- self.touch = BackpackTouch;
- self.nextthink = time + 1200; // remove after 20 minutes
- self.think = SUB_Remove;
- };
-
- void() AmmoCacheTouch =
- {
- if (other == self.owner) return; // don't bounce off owner
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
- if (self.velocity == '0 0 0') self.avelocity = '0 0 0';
- };
-
- void() W_FireAmmoCache =
- {
- local entity missile, mpuff;
-
- if ( (self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells) <= 1)
- return; // Not enough ammo
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
- missile.wait = time + 5 + 5*random();
-
- // Load with ammo
- if (self.ammo_shells >= 20)
- {
- missile.ammo_shells = 20;
- self.ammo_shells = self.ammo_shells - 20;
- }
- else
- {
- missile.ammo_shells = self.ammo_shells;
- self.ammo_shells = 0;
- }
-
- if (self.ammo_nails >= 20)
- {
- missile.ammo_nails = 20;
- self.ammo_nails = self.ammo_nails - 20;
- }
- else
- {
- missile.ammo_nails = self.ammo_nails;
- self.ammo_nails = 0;
- }
- if (self.ammo_rockets >= 10)
- {
- missile.ammo_rockets = 10;
- self.ammo_rockets = self.ammo_rockets - 10;
- }
- else
- {
- missile.ammo_rockets = self.ammo_rockets;
- self.ammo_rockets = 0;
- }
-
- if (self.ammo_cells >= 20)
- {
- missile.ammo_cells = 20;
- self.ammo_cells = self.ammo_cells - 20;
- }
- else
- {
- missile.ammo_cells = self.ammo_cells;
- self.ammo_cells = 0;
- }
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = AmmoCacheTouch;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
- missile.think = AmmoCacheDeploy;
- missile.nextthink = time + 2 + random()*5; // Deploy after a few seconds
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- ===============
- Homing Missiles
-
- These are quite smart, flying through the area looking for a target (not you).
- Code is from Iikka Paavolainen (ipaavola@cc.hut.fi), who wrote the
- GeniusMissile patch. This is a VERY impressive piece of code, and I only
- changed little of it (missile search radius much smaller for speed and
- interestng search pattern).
-
- As soon as I have a bit of time, I'll work out exactly what this thing
- does and comment it.
- ===============
- */
-
- void() HomeThink;
- entity() HomeFindTarget;
- float(entity targ) visible;
- float(entity targ) infront;
-
- void() W_FireHomingMissile =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 300;
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = T_MissileTouch;
-
- // set missile duration
- // missile.nextthink = time + 30;
- // missile.think = SUB_Remove;
-
- missile.nextthink = time + 0.2;
- missile.think = HomeThink;
- missile.enemy = world;
- missile.ltime=time;
-
- setmodel (missile, "progs/missile.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward*8 + '0 0 16');
- };
-
- entity() HomeFindTarget =
- {
- local entity head, selected;
- local float dist;
- dist = 100000;
- selected = world;
- head = findradius(self.origin, 1500);
- while(head)
- {
- if( (head.health > 1) && (head != self) && (head != self.owner) && head.classname != "door")
- {
- if ((coop && (head.classname == "player")) != 1) // Not player in coop
- {
- traceline(self.origin,head.origin,TRUE,self);
- if ( (trace_fraction >= 1) && (vlen(head.origin - self.origin) < dist) )
- {
- selected = head;
- dist = vlen(head.origin - self.origin);
- }
- }
- }
- head = head.chain;
- }
- if (selected != world)
- {
- sprint (self.owner,"Homing->");
- if (selected.classname == "player")
- {
- sprint (self.owner,selected.netname);
- sprint (selected,self.owner.netname);
- sprint (selected," has a bogey on you!\n");
- }
- else
- sprint (self.owner,selected.classname);
- sprint (self.owner,"\n");
- }
- return selected;
- };
-
- void() HomeThink =
- {
- local vector dir, vtemp, tm;
- local float r,dist;
- dist=100;
- if(time-self.ltime>=20)
- {
- sprint(self.owner,"Missile self-destructing.\n");
- self.nextthink=time+0.1;
- self.think=SUB_Remove;
- return;
- }
- traceline(self.origin,self.enemy.origin,TRUE,self);
- if ( trace_fraction<1.0 || !(self.enemy) || (self.enemy == world) || (self.enemy.health < 1) )
- self.enemy = HomeFindTarget();
-
- if (self.enemy != world)
- {
- vtemp = self.enemy.origin + '0 0 10';
- dir = normalize(vtemp - self.origin);
- self.velocity = dir * 300;
- self.angles = vectoangles(self.velocity);
- }
- else
- {
- makevectors(self.angles);
- traceline(self.origin,self.origin+v_forward*dist,TRUE,self);
- if(trace_fraction<1.0)
- {
- traceline(self.origin,self.origin+v_right*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity=v_right*300;
- else
- {
- traceline(self.origin,self.origin-v_right*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity='0 0 0'-v_right*300;
- else
- {
- traceline(self.origin,self.origin+v_up*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity=v_up*300;
- else
- {
- traceline(self.origin,self.origin-v_up*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity='0 0 0'-v_up*300;
- else
- {
- traceline(self.origin,self.origin-v_forward*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity='0 0 0'-v_forward*300;
- else
- {
- sprint(self.owner,"Missile in trouble!\n");
- r=random();
- if(r>0.75)
- self.velocity=v_right*300;
- else
- if(r>0.50)
- self.velocity='0 0 0'-v_right*300;
- else
- if(r>0.25)
- self.velocity=v_up*300;
- else
- self.velocity='0 0 0'-v_up*300;
- }
- }
- }
- }
- }
- self.angles=vectoangles(self.velocity);
- }
- }
- self.nextthink = time + 0.2;
- self.think=HomeThink;
- };
-
- /*
- =====================
- Nail Launcher Grenade
-
- Pops up, rotates and fires nails before exploding.
- Code is from TeamFortress 1.0 by Robin Walker, John Cook and Ian Caughley.
- =====================
- */
- void() NailLauncherTouch =
- {
- if (other == self.owner)
- return; // don't explode on owner
-
- // If the Nail Grenade hits a player, it just bounces off
-
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- void() NailLauncherLaunchNail =
- // Fire three nails in random directions, parallel to the ground
- {
- local float i,j;
-
- i = 0;
- while (i < 3)
- {
- j = (random() + 2) * 2;
- current_yaw = anglemod( self.angles_y );
- current_yaw = anglemod(current_yaw + j);
- self.angles_y = current_yaw;
- self.angles_x = 0;
- self.angles_z = 0;
- makevectors(self.angles);
-
- launch_spike(self.origin, v_forward);
-
- i = i + 1;
- }
-
- self.nextthink = time + 0.1;
-
- // Explode?
- if (random() < 0.01)
- self.think = GrenadeExplode;
- };
-
- void() NailLauncherNailEm =
- // Ready to launch nails
- {
- // Rotate and spew Nails
- self.velocity = '0 0 0';
-
- self.nextthink = time + 0.1;
- self.think = NailLauncherLaunchNail;
- };
-
- void() NailLauncherExplode =
- // Pop up and launch nails
- {
- // Raise into the air
- self.movetype = MOVETYPE_NOCLIP;
- self.velocity = '0 0 100';
- self.avelocity = '0 500 0';
- self.nextthink = time + 0.5;
- self.think = NailLauncherNailEm;
- };
-
- void() W_FireNailLauncher =
- {
- local entity missile, mpuff;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "grenade";
- missile.nextthink = time + 2 + 5*random();
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = NailLauncherTouch;
- missile.think = NailLauncherExplode;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- =====
- Flare
-
- Fires a flare which sticks to walls (but not doors and plats).
- Flies until it hits something (does 1pt damage), then flares up.
- After a while it'll die down again.
-
- Cool code is from Steve Bond (wedge@nuc.net).
- =====
- */
-
- void() FlareDim =
- // Make flare go dim again
- {
- // Make the flare get dim by setting .effects bit
- self.effects=EF_DIMLIGHT;
- // Give it 15 seconds before burnout
- self.nextthink = time + 15;
- // After 15 seconds remove the flare from the game
- self.think = SUB_Remove;
- };
-
- void() FlareBright =
- // Flare brightens up
- {
- local vector vel;
- // Make the flare get BRIGHT by setting .effects bit
- self.effects=EF_BRIGHTLIGHT;
- // Give it 10 seconds at maximum intensity
- self.nextthink = time + 10;
- // After 10 seconds, call flare_dim
- self.think = FlareDim;
- // Play a sound for flare ignition
- sound (self, CHAN_WEAPON, "misc/power.wav", 1, ATTN_NORM);
-
- // Set up some red and yellow sparks
- vel = '0 0 150';
- particle (self.origin+vel*0.01,vel,111,150);
- vel = '0 0 120';
- particle (self.origin+vel*0.01,vel,73,200);
- };
-
- void() FlareTouch =
- {
- local float rand;
- if (other == self.owner)
- return;
-
- if (other.classname == "door" || other.classname == "plat")
- {
- remove(self);
- return;
- }
-
- if (other.solid == SOLID_TRIGGER)
- return; // trigger field, do nothing
-
- if (pointcontents(self.origin) == CONTENT_SKY)
- {
- remove(self);
- return;
- }
-
- // has the flare hit something that bleeds?
- if (other.takedamage)
- {
- // If so, spawn some blood
- spawn_touchblood (9);
- // also do one point of damage
- T_Damage (other, self, self.owner, 1);
-
- /*
- Don't remove the flare unless it is still flying. Otherwise, monsters or
- other players can come up and 'pull' your flare out of the wall
- */
- if (self.velocity != '0 0 0')
- remove(self);
- }
- else
- {
- // Write information to the network
- WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
- WriteByte (MSG_BROADCAST, TE_SPIKE);
- WriteCoord (MSG_BROADCAST, self.origin_x);
- WriteCoord (MSG_BROADCAST, self.origin_y);
- WriteCoord (MSG_BROADCAST, self.origin_z);
- }
-
- //Stop the flare, but do not remove it.
- self.movetype = MOVETYPE_NONE;
- // Fix it so that flare only partially embeds itself (thanks, Luke)
- self.origin = self.origin - self.velocity * 0.005;
- self.velocity = '0 0 0';
- self.touch = SUB_Null;
- };
-
- void() W_FireFlare =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLY;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 1000;
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = FlareTouch;
-
- // set missile duration
- missile.nextthink = time + 3; // Flare brightly after 3s
- missile.think = FlareBright;
-
- setmodel (missile, "progs/missile.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward*8 + '0 0 16');
- };
-
- /*
- ======
- Camera
-
- Launches a camera, which pops up and can be rotated via the cursor keys.
- Has to be explicitly removed, but the player can launch several eyes,
- always looking through the latest one.
-
- ======
- */
- void() CameraTouch =
- {
- if (other == self.owner)
- return; // don't react to owner
-
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
- if (self.velocity == '0 0 0')
- self.avelocity = '0 0 0';
- };
-
- void() RemoveCameras =
- {
- local entity head,camtokill;
-
- // First, set the viewport back to the player
- msg_entity = self; // target of message: the player
- WriteByte(MSG_ONE, 5);
- WriteEntity(MSG_ONE, self); // back to player
- WriteByte(MSG_ONE, 10);
- WriteAngle(MSG_ONE, self.angles_x);
- WriteAngle(MSG_ONE, self.angles_y);
- WriteAngle(MSG_ONE, self.angles_z);
- // Now, remove all cameras
- head = findradius(self.origin, 10000); // Look in a big radius
- while(head)
- {
- if ((head.owner == self) && (head.classname == "camera")) // It's a camera of ours
- {
- camtokill = head;
- head = head.chain;
- sound (camtokill, CHAN_WEAPON, "misc/power.wav", 0.3, ATTN_NORM); // Weird sound as it disappears
- remove(camtokill);
- }
- else
- { head = head.chain; } // Check next
- }
- };
-
- void() CameraFilm =
- {
- // Shift the viewpoint to the camera
- msg_entity = self.owner;
- WriteByte(MSG_ONE, 5);
- WriteEntity(MSG_ONE, self);
- WriteByte(MSG_ONE, 10);
- WriteAngle(MSG_ONE, self.angles_x);
- WriteAngle(MSG_ONE, self.angles_y);
- WriteAngle(MSG_ONE, self.angles_z);
- };
-
- void() CameraActivate =
- // Stop the upwards movement and start filming
- {
- self.velocity = '0 0 0'; // Stop rising
- current_yaw = current_yaw * 0; // Place yourself horizontally
- self.angles_y = 0;
- self.angles_x = 0;
- self.angles_z = 0;
- makevectors(self.angles);
-
- self.think = CameraFilm;
- self.nextthink = time + 0.1;
- };
-
- void() CameraDeploy =
- // Grenade releases a pop-up camera
- {
- // Rise into the air
- self.movetype = MOVETYPE_NOCLIP;
- self.velocity = '0 0 100';
- self.think = CameraActivate;
- self.nextthink = time + 0.5;
- // Change into glowing eyes
- setmodel (self, "progs/eyes.mdl");
- self.effects = self.effects | EF_DIMLIGHT; // Weird glow
- };
-
- void() W_FireCamera =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_BOUNCE;
- missile.solid = SOLID_BBOX;
- missile.classname = "camera";
-
- // set missile speed
-
- makevectors (self.v_angle);
-
- if (self.v_angle_x)
- missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
- else
- {
- missile.velocity = aim(self, 10000);
- missile.velocity = missile.velocity * 600;
- missile.velocity_z = 200;
- }
-
- missile.avelocity = '300 300 300';
-
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = CameraTouch;
-
- // set missile duration
- missile.nextthink = time + 2.5;
- missile.think = CameraDeploy;
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin);
- };
-
- /*
- ===========
- Nail Probe
-
- Similar to the homing missile, this slow-moving probe fires
- nails at the enemy.
- The probe self-destructs after 20s or when it runs out of ammo.
-
- This code is a modified Homing Missile, which, in turn, is
- a modified Genius Missile - see comment there for original
- author.
-
- PS: I used to have the life span set to 60s with no ammo limit -
- those things cleared out whole levels without help from me >:)
- ===========
- */
- void() NailHomeThink;
- entity() NailHomeFindTarget;
- float(entity targ) visible;
- float(entity targ) infront;
-
- void() NailProbeTouch =
- {
- if (other == self.owner)
- return; // don't react to owner
-
- sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
- if (self.velocity == '0 0 0') // bounce off
- self.avelocity = '0 0 0';
- };
-
- void(vector org, vector d) NailProbeShoot =
- // Shoot once in direction d
- {
- sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
- launch_spike (org + '0 0 16', d);
- self.ammo_nails = self.ammo_nails - 1; // One more nail gone...
- newmis.touch = spike_touch;
- setmodel (newmis, "progs/spike.mdl");
- setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
- self.nextthink = time + 1; // shoot & think slower for a moment
- };
-
- void() W_FireNailProbe =
- {
- local entity missile, mpuff;
-
- self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
-
- sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
-
- self.punchangle_x = -2;
-
- missile = spawn ();
- missile.owner = self;
- missile.movetype = MOVETYPE_FLY;
- missile.solid = SOLID_BBOX;
-
- // set missile speed
-
- makevectors (self.v_angle);
- missile.velocity = aim(self, 1000);
- missile.velocity = missile.velocity * 100;
- missile.angles = vectoangles(missile.velocity);
-
- missile.touch = NailProbeTouch;
- missile.enemy = world;
- missile.ltime = time;
- missile.ammo_nails = 20; // Missile is armed with 20 nails
-
- setmodel (missile, "progs/grenade.mdl");
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward*8 + '0 0 16');
- missile.effects = self.effects | EF_DIMLIGHT; // Glow a bit
- missile.nextthink = time + 1; // 1s pause
- missile.think = NailHomeThink;
- };
-
- entity() NailHomeFindTarget =
- {
- local entity head, selected;
- local float dist;
- dist = 100000;
- selected = world;
- head = findradius(self.origin, 1500);
- while(head)
- {
- if( (head.health > 1) && (head != self) && (head != self.owner) && head.classname != "door")
- {
- if ((coop && (head.classname == "player")) != 1) // Not player in coop
- {
- if (head.classname != "monster_zombie") // No use shooting zombies...
- {
- traceline(self.origin,head.origin,TRUE,self);
- if ( (trace_fraction >= 1) && (vlen(head.origin - self.origin) < dist) )
- {
- selected = head;
- dist = vlen(head.origin - self.origin);
- }
- }
- }
- }
- head = head.chain;
- }
- if (selected != world)
- {
- sprint (self.owner,"Target->");
- if (selected.classname == "player")
- {
- sprint (self.owner,selected.netname);
- sprint (selected,self.owner.netname);
- sprint (selected," has an eye on you!\n");
- }
- else
- sprint (self.owner,selected.classname);
- sprint (self.owner,"\n");
- }
- return selected;
- };
-
- void() NailHomeThink =
- {
- local vector dir, vtemp, tm, enemydir;
- local float r,dist;
- dist=100;
- if ((time-self.ltime >= 20) && // Life-span is 20s. Feel free to increment
- (self.ammo_nails <= 0)) // No ammo left?
- {
- sprint(self.owner,"Probe self-destructing.\n");
- self.nextthink=time+0.1;
- self.think=GrenadeExplode; // Go out with a bang
- return;
- }
- traceline(self.origin,self.enemy.origin,TRUE,self);
- if ( trace_fraction<1.0 || !(self.enemy) || (self.enemy == world) || (self.enemy.health < 1) )
- self.enemy = HomeFindTarget();
-
- if (self.enemy != world) // Valid target
- {
- enemydir = normalize(self.enemy.origin - self.origin); // Get direction
- NailProbeShoot(self.origin,enemydir);
- }
- else
- {
- makevectors(self.angles);
- traceline(self.origin,self.origin+v_forward*dist,TRUE,self);
- if(trace_fraction<1.0)
- {
- traceline(self.origin,self.origin+v_right*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity=v_right*300;
- else
- {
- traceline(self.origin,self.origin-v_right*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity='0 0 0'-v_right*300;
- else
- {
- traceline(self.origin,self.origin+v_up*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity=v_up*300;
- else
- {
- traceline(self.origin,self.origin-v_up*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity='0 0 0'-v_up*300;
- else
- {
- traceline(self.origin,self.origin-v_forward*dist,TRUE,self);
- if(trace_fraction==1.0)
- self.velocity='0 0 0'-v_forward*300;
- else
- {
- sprint(self.owner,"Probe in trouble!\n");
- r=random();
- if(r>0.75)
- self.velocity=v_right*300;
- else
- if(r>0.50)
- self.velocity='0 0 0'-v_right*300;
- else
- if(r>0.25)
- self.velocity=v_up*300;
- else
- self.velocity='0 0 0'-v_up*300;
- }
- }
- }
- }
- }
- self.angles=vectoangles(self.velocity);
- }
- }
- self.nextthink = time + 0.2;
- self.think=NailHomeThink;
- };
-
-
- void() W_FireGrenade =
- // Choose grenade type to fire according to player.button1
- // The USE button is not used, so we use it as a local variable for each player
- {
- if (self.button1 == 1) { W_FireNailBomb (); return; }
- if (self.button1 == 2) { W_FireNailLauncher (); return; }
- if (self.button1 == 3) { W_FireBCGrenade (); return; }
- if (self.button1 == 4) { W_FireRocket (); return; }
- if (self.button1 == 5) { W_FireRicochet (); return; }
- if (self.button1 == 6) { W_FireGlue (); return; }
- if (self.button1 == 7) { W_FireMG (); return; }
- if (self.button1 == 8) { W_FireVamp (); return; }
- if (self.button1 == 9) { W_FireMedic (); return; }
- if (self.button1 == 10) { W_FireAP (); return; }
- if (self.button1 == 11) { W_FireRTB (); return; }
- if (self.button1 == 12) { W_FireAmmoCache (); return; }
- if (self.button1 == 13) { W_FireHomingMissile (); return; }
- if (self.button1 == 14) { W_FireFlare (); return; }
- if (self.button1 == 15) { W_FireCamera (); return; }
- if (self.button1 == 16) { W_FireNailProbe (); return; }
- W_FireNormalGrenade (); // Firewall
- };
-
- /*
- ===============================================================================
-
- PLAYER WEAPON USE
-
- ===============================================================================
- */
-
- void() W_SetCurrentAmmo =
- {
- player_run (); // get out of any weapon firing states
-
- self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
-
- if (self.weapon == IT_AXE)
- {
- self.currentammo = 0;
- self.weaponmodel = "progs/v_axe.mdl";
- self.weaponframe = 0;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.currentammo = self.ammo_shells;
- self.weaponmodel = "progs/v_shot.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_SHELLS;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.currentammo = self.ammo_shells;
- self.weaponmodel = "progs/v_shot2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_SHELLS;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.currentammo = self.ammo_nails;
- self.weaponmodel = "progs/v_nail.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_NAILS;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.currentammo = self.ammo_nails;
- self.weaponmodel = "progs/v_nail2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_NAILS;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.currentammo = self.ammo_rockets;
- self.weaponmodel = "progs/v_rock.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_ROCKETS;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.currentammo = self.ammo_rockets;
- self.weaponmodel = "progs/v_rock2.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_ROCKETS;
- }
- else if (self.weapon == IT_LIGHTNING)
- {
- self.currentammo = self.ammo_cells;
- self.weaponmodel = "progs/v_light.mdl";
- self.weaponframe = 0;
- self.items = self.items | IT_CELLS;
- }
- else
- {
- self.currentammo = 0;
- self.weaponmodel = "";
- self.weaponframe = 0;
- }
- };
-
- float() W_BestWeapon =
- {
- local float it;
-
- it = self.items;
-
- if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
- return IT_LIGHTNING;
- else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
- return IT_SUPER_NAILGUN;
- else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
- return IT_SUPER_SHOTGUN;
- else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
- return IT_NAILGUN;
- else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
- return IT_SHOTGUN;
-
- /*
- if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
- return IT_ROCKET_LAUNCHER;
- else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
- return IT_GRENADE_LAUNCHER;
-
- */
-
- return IT_AXE;
- };
-
- float() W_CheckNoAmmo =
- {
- if (self.currentammo > 0)
- return TRUE;
-
- if (self.weapon == IT_AXE)
- return TRUE;
-
- self.weapon = W_BestWeapon ();
-
- W_SetCurrentAmmo ();
-
- // drop the weapon down
- return FALSE;
- };
-
- /*
- ============
- W_Attack
-
- An attack impulse can be triggered now
- ============
- */
- void() player_axe1;
- void() player_axeb1;
- void() player_axec1;
- void() player_axed1;
- void() player_shot1;
- void() player_nail1;
- void() player_light1;
- void() player_rocket1;
-
- void() W_Attack =
- {
- local float r;
-
- if (!W_CheckNoAmmo ())
- return;
-
- makevectors (self.v_angle); // calculate forward angle for velocity
- self.show_hostile = time + 1; // wake monsters up
-
- if (self.weapon == IT_AXE)
- {
- sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
- r = random();
- if (r < 0.25)
- player_axe1 ();
- else if (r<0.5)
- player_axeb1 ();
- else if (r<0.75)
- player_axec1 ();
- else
- player_axed1 ();
- self.attack_finished = time + 0.5;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- player_shot1 ();
- W_FireShotgun ();
- self.attack_finished = time + 0.5;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- player_shot1 ();
- W_FireSuperShotgun ();
- self.attack_finished = time + 0.7;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- player_nail1 ();
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- player_nail1 ();
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- player_rocket1();
- W_FireGrenade();
- self.attack_finished = time + 0.6;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- player_rocket1();
- W_FireRocket();
- self.attack_finished = time + 0.8;
- }
- else if (self.weapon == IT_LIGHTNING)
- {
- player_light1();
- self.attack_finished = time + 0.1;
- sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
- }
- };
-
- /*
- ============
- W_ChangeWeapon
-
- ============
- */
- void() W_ChangeWeapon =
- {
- local float it, am, fl;
-
- it = self.items;
- am = 0;
-
- if (self.impulse == 1)
- {
- fl = IT_AXE;
- }
- else if (self.impulse == 2)
- {
- fl = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- am = 1;
- }
- else if (self.impulse == 3)
- {
- fl = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- am = 1;
- }
- else if (self.impulse == 4)
- {
- fl = IT_NAILGUN;
- if (self.ammo_nails < 1)
- am = 1;
- }
- else if (self.impulse == 5)
- {
- fl = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- am = 1;
- }
- else if (self.impulse == 6)
- {
- fl = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.impulse == 7)
- {
- fl = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.impulse == 8)
- {
- fl = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- am = 1;
- }
-
- self.impulse = 0;
-
- if (!(self.items & fl))
- { // don't have the weapon or the ammo
- sprint (self, "no weapon.\n");
- return;
- }
-
- if (am)
- { // don't have the ammo
- sprint (self, "not enough ammo.\n");
- return;
- }
-
- //
- // set weapon, set ammo
- //
- self.weapon = fl;
- W_SetCurrentAmmo ();
- };
-
- /*
- ============
- CheatCommand
- ============
- */
- void() CheatCommand =
- {
- if (deathmatch || coop)
- return;
-
- self.ammo_rockets = 100;
- self.ammo_nails = 200;
- self.ammo_shells = 100;
- self.items = self.items |
- IT_AXE |
- IT_SHOTGUN |
- IT_SUPER_SHOTGUN |
- IT_NAILGUN |
- IT_SUPER_NAILGUN |
- IT_GRENADE_LAUNCHER |
- IT_ROCKET_LAUNCHER |
- IT_KEY1 | IT_KEY2;
-
- self.ammo_cells = 200;
- self.items = self.items | IT_LIGHTNING;
-
- self.weapon = IT_ROCKET_LAUNCHER;
- self.impulse = 0;
- W_SetCurrentAmmo ();
- };
-
- /*
- ============
- CycleWeaponCommand
-
- Go to the next weapon with ammo
- ============
- */
- void() CycleWeaponCommand =
- {
- local float it, am;
-
- it = self.items;
- self.impulse = 0;
-
- while (1)
- {
- am = 0;
-
- if (self.weapon == IT_LIGHTNING)
- {
- self.weapon = IT_AXE;
- }
- else if (self.weapon == IT_AXE)
- {
- self.weapon = IT_SHOTGUN;
- if (self.ammo_shells < 1)
- am = 1;
- }
- else if (self.weapon == IT_SHOTGUN)
- {
- self.weapon = IT_SUPER_SHOTGUN;
- if (self.ammo_shells < 2)
- am = 1;
- }
- else if (self.weapon == IT_SUPER_SHOTGUN)
- {
- self.weapon = IT_NAILGUN;
- if (self.ammo_nails < 1)
- am = 1;
- }
- else if (self.weapon == IT_NAILGUN)
- {
- self.weapon = IT_SUPER_NAILGUN;
- if (self.ammo_nails < 2)
- am = 1;
- }
- else if (self.weapon == IT_SUPER_NAILGUN)
- {
- self.weapon = IT_GRENADE_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.weapon == IT_GRENADE_LAUNCHER)
- {
- self.weapon = IT_ROCKET_LAUNCHER;
- if (self.ammo_rockets < 1)
- am = 1;
- }
- else if (self.weapon == IT_ROCKET_LAUNCHER)
- {
- self.weapon = IT_LIGHTNING;
- if (self.ammo_cells < 1)
- am = 1;
- }
-
- if ( (self.items & self.weapon) && am == 0)
- {
- W_SetCurrentAmmo ();
- return;
- }
- }
-
- };
-
- /*
- ============
- ServerflagsCommand
-
- Just for development
- ============
- */
- void() ServerflagsCommand =
- {
- serverflags = serverflags * 2 + 1;
- };
-
- void() QuadCheat =
- {
- if (deathmatch || coop)
- return;
- self.super_time = 1;
- self.super_damage_finished = time + 30;
- self.items = self.items | IT_QUAD;
- dprint ("quad cheat\n");
- };
-
- void(entity p) ShowGrenadeType =
- // Show which grenade player p got loaded
- {
- if (p.button1 == 0) { sprint (self,"Standard grenade\n"); return; }
- if (p.button1 == 1) { sprint (self,"Nail bomb\n"); return; }
- if (p.button1 == 2) { sprint (self,"Nail launcher\n"); return; }
- if (p.button1 == 3) { sprint (self,"Bouncing cluster bomb\n"); return; }
- if (p.button1 == 4) { sprint (self,"RPG\n"); return; }
- if (p.button1 == 5) { sprint (self,"Ricochet grenade\n"); return; }
- if (p.button1 == 6) { sprint (self,"Glue grenade\n"); return; }
- if (p.button1 == 7) { sprint (self,"MG point defense\n"); return; }
- if (p.button1 == 8) { sprint (self,"Vampire bolt\n"); return; }
- if (p.button1 == 9) { sprint (self,"Medic bolt\n"); return; }
- if (p.button1 == 10) { sprint (self,"Armor piercing\n"); return; }
- if (p.button1 == 11) { sprint (self,"Radio tag bomb\n"); return; }
- if (p.button1 == 12) { sprint (self,"Ammo cache\n"); return; }
- if (p.button1 == 13) { sprint (self,"Homing missile\n"); return; }
- if (p.button1 == 14) { sprint (self,"Flare\n"); return; }
- if (p.button1 == 15) { sprint (self,"Camera\n"); return; }
- if (p.button1 == 16) { sprint (self,"Nail probe\n"); return; }
- sprint (self,"Unknown grenade; using standard\n");
- };
-
- /*
- ============
- ImpulseCommands
-
- ============
- */
- void() ImpulseCommands =
- {
- if (self.impulse >= 1 && self.impulse <= 8)
- W_ChangeWeapon ();
-
- if (self.impulse == 9)
- CheatCommand ();
- if (self.impulse == 10)
- CycleWeaponCommand ();
- if (self.impulse == 11)
- ServerflagsCommand ();
-
- // *** Grenade selection done here
-
- if (self.impulse == 99) // Give launcher & ammo
- {
- self.ammo_rockets = 100;
- self.items = self.items | IT_GRENADE_LAUNCHER;
- }
-
- if (self.impulse == 100) // Next grenade type
- {
- self.button1 = self.button1 + 1;
- if (self.button1 > 20) self.button1 = 0;
- ShowGrenadeType (self);
- }
- if (self.impulse == 101) // Previous grenade type
- {
- self.button1 = self.button1 - 1;
- if (self.button1 < 0) self.button1 = 20;
- ShowGrenadeType (self);
- }
- if (self.impulse == 102) // Show current type
- {
- ShowGrenadeType (self);
- }
- if (self.impulse == 103) // Select Nail Bomb
- {
- self.button1 = 1;
- ShowGrenadeType (self);
- }
- if (self.impulse == 104) // Select Bouncing Cluster Bomb
- {
- self.button1 = 2;
- ShowGrenadeType (self);
- }
- if (self.impulse == 105) // Select RPG
- {
- self.button1 = 3;
- ShowGrenadeType (self);
- }
- if (self.impulse == 106) // Select Ricochet Grenade
- {
- self.button1 = 4;
- ShowGrenadeType (self);
- }
- if (self.impulse == 107) // Select Glue Grenade
- {
- self.button1 = 5;
- ShowGrenadeType (self);
- }
- if (self.impulse == 108) // Select MG Point Defense
- {
- self.button1 = 6;
- ShowGrenadeType (self);
- }
- if (self.impulse == 109) // Select Vampire Bolt
- {
- self.button1 = 7;
- ShowGrenadeType (self);
- }
- if (self.impulse == 110) // Select Medic Bolt
- {
- self.button1 = 8;
- ShowGrenadeType (self);
- }
- if (self.impulse == 111) // Select Armor Piercing
- {
- self.button1 = 9;
- ShowGrenadeType (self);
- }
- if (self.impulse == 112) // Select Radio Tag Bomb
- {
- self.button1 = 10;
- ShowGrenadeType (self);
- }
- if (self.impulse == 113) // Detonate RTB
- {
- DetonateRTB ();
- }
- if (self.impulse == 114) // Disarm RTB
- {
- DisarmRTB ();
- }
- if (self.impulse == 115) // Select Ammo Cache
- {
- self.button1 = 11;
- ShowGrenadeType (self);
- }
- if (self.impulse == 116) // Select Homing Missile
- {
- self.button1 = 12;
- ShowGrenadeType (self);
- }
- if (self.impulse == 117) // Select Nail Launcher
- {
- self.button1 = 13;
- ShowGrenadeType (self);
- }
- if (self.impulse == 118) // Select Flare
- {
- self.button1 = 14;
- ShowGrenadeType (self);
- }
- if (self.impulse == 119) // Select Camera
- {
- self.button1 = 15;
- ShowGrenadeType (self);
- }
- if (self.impulse == 120) // Remove Camera
- {
- RemoveCameras ();
- }
- if (self.impulse == 121) // Nail Probe
- {
- self.button1 = 16;
- ShowGrenadeType (self);
- }
-
- if (self.impulse == 254) // Talk!
- {
- sound (self, CHAN_WEAPON, "talk/scum.wav", 1, ATTN_NORM);
- }
-
-
- if (self.impulse == 255)
- QuadCheat ();
-
- self.impulse = 0;
- };
-
- /*
- ============
- W_WeaponFrame
-
- Called every frame so impulse events can be handled as well as possible
- ============
- */
- void() W_WeaponFrame =
- {
- if (time < self.attack_finished)
- return;
-
- ImpulseCommands ();
-
- // check for attack
- if (self.button0)
- {
- SuperDamageSound ();
- W_Attack ();
- }
- };
-
- /*
- ========
- SuperDamageSound
-
- Plays sound if needed
- ========
- */
- void() SuperDamageSound =
- {
- if (self.super_damage_finished > time)
- {
- if (self.super_sound < time)
- {
- self.super_sound = time + 1;
- sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
- }
- }
- return;
- };
-
-
-