]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/weapons.qc
gibbing sound added
[divverent/nexuiz.git] / qcsrc / weapons.qc
1 float TE_SMOKE =77;
2 void (vector vec) WriteVec =
3 {
4                 WriteCoord (MSG_BROADCAST, vec_x);
5                 WriteCoord (MSG_BROADCAST, vec_y);
6                 WriteCoord (MSG_BROADCAST, vec_z);
7 }
8 void (vector org, vector dir, float counts) W_Smoke =
9 {
10                 WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
11                 WriteByte (MSG_BROADCAST, TE_SMOKE);
12                 WriteVec (org);
13                 WriteVec (dir);
14                 WriteByte (MSG_BROADCAST, counts);
15 }
16
17 // increments sprite frame, loops when end is hit.. simple
18 void animate_sprite (float startframe, float frame_count)
19 {
20         if ((self.frame - startframe) >= (frame_count - 1 ))
21                 self.frame = startframe;
22         else
23                 self.frame = self.frame + 1;
24 }
25
26 void W_UpdateAmmo (void)
27 {
28         self.items = self.items - (self.items & (IT_NAILS | IT_SHELLS | IT_ROCKETS | IT_CELLS));
29
30         if (self.weapon == IT_LASER)
31                 self.currentammo = 1;
32         else if (self.weapon == IT_UZI)
33         {
34                 self.currentammo = self.ammo_nails;
35                 self.items = self.items | IT_NAILS;
36         }
37         else if (self.weapon == IT_SHOTGUN)
38         {
39                 self.currentammo = self.ammo_shells;
40                 self.items = self.items | IT_SHELLS;
41         }
42         else if (self.weapon == IT_GRENADE_LAUNCHER || self.weapon == IT_HAGAR || self.weapon == IT_ROCKET_LAUNCHER)
43         {
44                 self.currentammo = self.ammo_rockets;
45                 self.items = self.items | IT_ROCKETS;
46         }
47         else if (self.weapon == IT_ELECTRO || self.weapon == IT_NEX || self.weapon == IT_CRYLINK)
48         {
49                 self.currentammo = self.ammo_cells;
50                 self.items = self.items | IT_CELLS;
51         }
52 }
53
54 void W_UpdateWeapon (void)
55 {
56         if (self.weapon == IT_LASER)
57                 self.weaponmodel = "models/weapons/w_laser.zym";
58         else if (self.weapon == IT_UZI)
59                 self.weaponmodel = "models/weapons/w_uzi.md3";
60         else if (self.weapon == IT_SHOTGUN)
61                 self.weaponmodel = "models/weapons/w_shotgun.zym";
62         else if (self.weapon == IT_GRENADE_LAUNCHER)
63                 self.weaponmodel = "models/weapons/w_gl.zym";
64         else if (self.weapon == IT_ELECTRO)
65                 self.weaponmodel = "models/weapons/w_electro.zym";
66         else if (self.weapon == IT_CRYLINK)
67                 self.weaponmodel = "models/weapons/w_crylink.zym";
68         else if (self.weapon == IT_NEX)
69                 self.weaponmodel = "models/weapons/w_nex.zym";
70         else if (self.weapon == IT_HAGAR)
71                 self.weaponmodel = "models/weapons/w_hagar.zym";
72         else if (self.weapon == IT_ROCKET_LAUNCHER)
73                 self.weaponmodel = "models/weapons/w_rl.zym";
74         else
75                 objerror ("Illegal weapon - please register your guns please!");
76 }
77
78 float W_GetBestWeapon (void)
79 {
80         if ((self.items & IT_ROCKET_LAUNCHER) && self.ammo_rockets)
81                 return IT_ROCKET_LAUNCHER;
82         else if ((self.items & IT_HAGAR) && self.ammo_rockets)
83                 return IT_HAGAR;
84         else if ((self.items & IT_NEX) && self.ammo_cells)
85                 return IT_NEX;
86         else if ((self.items & IT_CRYLINK) && self.ammo_cells)
87                 return IT_CRYLINK;
88         else if ((self.items & IT_ELECTRO) && self.ammo_cells)
89                 return IT_ELECTRO;
90         else if ((self.items & IT_GRENADE_LAUNCHER) && self.ammo_rockets)
91                 return IT_GRENADE_LAUNCHER;
92         else if ((self.items & IT_SHOTGUN) && self.ammo_shells)
93                 return IT_SHOTGUN;
94         else if ((self.items & IT_UZI) && self.ammo_nails)
95                 return IT_UZI;
96         else
97                 return IT_LASER;
98 }
99
100 void W_GiveWeapon (entity e, float wep) // FIXME - make it 'smarter'
101 {
102         entity oldself;
103
104         if (!wep)
105                 return;
106
107         if (!(e.items & wep))
108         {
109                 e.items = e.items | wep;
110                 e.weapon = wep;
111         }
112
113         oldself = self;
114         self = e;
115
116         W_UpdateWeapon ();
117         W_UpdateAmmo ();
118
119         self = oldself;
120 }
121
122 void W_SwitchWeapon (float wep)
123 {
124         float           nextwep;
125         var float       noammo = FALSE;
126
127         if (wep == 1)
128                 nextwep = IT_LASER;
129         else if (wep == 2)
130         {
131                 nextwep = IT_UZI;
132                 if (!self.ammo_nails)
133                         noammo = TRUE;
134         }
135         else if (wep == 3)
136         {
137                 nextwep = IT_SHOTGUN;
138                 if (!self.ammo_shells)
139                         noammo = TRUE;
140         }
141         else if (wep == 4)
142         {
143                 nextwep = IT_GRENADE_LAUNCHER;
144                 if (!self.ammo_rockets)
145                         noammo = TRUE;
146         }
147         else if (wep == 5)
148         {
149                 nextwep = IT_ELECTRO;
150                 if (!self.ammo_cells)
151                         noammo = TRUE;
152         }
153         else if (wep == 6)
154         {
155                 nextwep = IT_CRYLINK;
156                 if (!self.ammo_cells)
157                         noammo = TRUE;
158         }
159         else if (wep == 7)
160         {
161                 nextwep = IT_NEX;
162                 if (!self.ammo_cells)
163                         noammo = TRUE;
164         }
165         else if (wep == 8)
166         {
167                 nextwep = IT_HAGAR;
168                 if (!self.ammo_rockets)
169                         noammo = TRUE;
170         }
171         else if (wep == 9)
172         {
173                 nextwep = IT_ROCKET_LAUNCHER;
174                 if (!self.ammo_rockets)
175                         noammo = TRUE;
176         }
177
178
179         if (!(self.items & nextwep))
180         {
181                 sprint (self, "You don't own that weapon\n");
182                 return;
183         }
184         else if (noammo)
185         {
186                 sprint (self, "You don't have any ammo for that weapon\n");
187                 return;
188         }
189
190         self.weapon = nextwep;
191         W_UpdateWeapon ();
192         W_UpdateAmmo ();
193         self.attack_finished = time + 0.2;
194         if (self.viewzoom != 1)
195                 self.viewzoom = 1;
196 }
197
198 void W_NextWeapon (void)
199 {
200         float   noammo;
201
202         while (TRUE)
203         {
204                 noammo = FALSE;
205
206                 if (self.weapon == IT_ROCKET_LAUNCHER)
207                         self.weapon = IT_LASER;
208                 else if (self.weapon == IT_LASER)
209                 {
210                         self.weapon = IT_UZI;
211                         if (!self.ammo_nails)
212                                 noammo = TRUE;
213                 }
214                 else if (self.weapon == IT_UZI)
215                 {
216                         self.weapon = IT_SHOTGUN;
217                         if (!self.ammo_shells)
218                                 noammo = TRUE;
219                 }
220                 else if (self.weapon == IT_SHOTGUN)
221                 {
222                         self.weapon = IT_GRENADE_LAUNCHER;
223                         if (!self.ammo_rockets)
224                                 noammo = TRUE;
225                 }
226                 else if (self.weapon == IT_GRENADE_LAUNCHER)
227                 {
228                         self.weapon = IT_ELECTRO;
229                         if (!self.ammo_cells)
230                                 noammo = TRUE;
231                 }
232                 else if (self.weapon == IT_ELECTRO)
233                 {
234                         self.weapon = IT_CRYLINK;
235                         if (!self.ammo_cells)
236                         noammo = TRUE;
237                 }
238                 else if (self.weapon == IT_CRYLINK)
239                 {
240                         self.weapon = IT_NEX;
241                         if (!self.ammo_cells)
242                         noammo = TRUE;
243                 }
244                 else if (self.weapon == IT_NEX)
245                 {
246                         self.weapon = IT_HAGAR;
247                         if (!self.ammo_rockets)
248                         noammo = TRUE;
249                 }
250                 else if (self.weapon == IT_HAGAR)
251                 {
252                         self.weapon = IT_ROCKET_LAUNCHER;
253                         if (!self.ammo_rockets)
254                                 noammo = TRUE;
255                 }
256
257                 if ((self.items & self.weapon) && !noammo)
258                 {
259                         W_UpdateWeapon ();
260                         W_UpdateAmmo ();
261                         return;
262                 }
263         }
264 }
265
266 void W_PreviousWeapon (void)
267 {
268         float   noammo;
269
270         while (TRUE)
271         {
272                 noammo = FALSE;
273
274                 if (self.weapon == IT_UZI)
275                         self.weapon = IT_LASER;
276                 else if (self.weapon == IT_SHOTGUN)
277                 {
278                         self.weapon = IT_UZI;
279                         if (!self.ammo_nails)
280                                 noammo = TRUE;
281                 }
282                 else if (self.weapon == IT_GRENADE_LAUNCHER)
283                 {
284                         self.weapon = IT_SHOTGUN;
285                         if (!self.ammo_shells)
286                                 noammo = TRUE;
287                 }
288                 else if (self.weapon == IT_ELECTRO)
289                 {
290                         self.weapon = IT_GRENADE_LAUNCHER;
291                         if (!self.ammo_rockets)
292                                 noammo = TRUE;
293                 }
294                 else if (self.weapon == IT_CRYLINK)
295                 {
296                         self.weapon = IT_ELECTRO;
297                         if (!self.ammo_cells)
298                                 noammo = TRUE;
299                 }
300                 else if (self.weapon == IT_NEX)
301                 {
302                         self.weapon = IT_CRYLINK;
303                         if (!self.ammo_cells)
304                                 noammo = TRUE;
305                 }
306                 else if (self.weapon == IT_HAGAR)
307                 {
308                         self.weapon = IT_NEX;
309                         if (!self.ammo_cells)
310                                 noammo = TRUE;
311                 }
312                 else if (self.weapon == IT_ROCKET_LAUNCHER)
313                 {
314                         self.weapon = IT_HAGAR;
315                         if (!self.ammo_rockets)
316                                 noammo = TRUE;
317                 }
318                 else if (self.weapon == IT_LASER)
319                 {
320                         self.weapon = IT_ROCKET_LAUNCHER;
321                         if (!self.ammo_rockets)
322                                 noammo = TRUE;
323                 }
324
325                 if ((self.items & self.weapon) && !noammo)
326                 {
327                         W_UpdateWeapon ();
328                         W_UpdateAmmo ();
329                         return;
330                 }
331         }
332 }
333
334 float W_CheckAmmo (void)
335 {
336         W_UpdateAmmo ();
337         if (self.weapon == IT_LASER)
338                 return TRUE;
339         else if (self.currentammo)
340                 return TRUE;
341
342         self.weapon = W_GetBestWeapon ();
343         W_UpdateWeapon ();
344
345         return FALSE;
346 }
347
348 /*
349 void FireRailgunBullet (vector src, float bdamage, vector dir, float spread, float deathtype)
350 {
351         vector  v, lastpos;
352         entity  saveself, last;
353         vector  org;
354         org = self.origin + self.view_ofs;
355         if (bdamage < 1)
356                 return;
357
358         last = self;
359         lastpos = src;
360
361         while (bdamage > 0)
362         {
363                 traceline_hitcorpse (self, org, org + v_forward * 4096 + v_right * crandom () * spread + v_up * crandom () * spread, FALSE, self);
364                 last = trace_ent;
365                 lastpos = trace_endpos;
366                 if (trace_fraction != 1.0)
367                 {
368                         if (pointcontents(trace_endpos - dir*4) == CONTENT_SKY)
369                                 return;
370
371                         if (trace_ent.takedamage || trace_ent.classname == "case")
372                         {
373                                 if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
374                                         te_blood (trace_endpos, dir * bdamage * 16, bdamage);
375                                 Damage (trace_ent, self, self, bdamage, deathtype, trace_endpos, dir * bdamage);
376                         }
377                 }
378                 if (last.solid == SOLID_BSP)
379                         bdamage = 0;
380         }
381 }
382 */
383
384 void FireRailgunBullet (vector src, float damage, vector dir, float dtype)
385 {
386         vector  org;
387
388         makevectors (self.v_angle);
389
390         // use traceline_hitcorpse to make sure it can hit gibs and corpses too
391         org = self.origin + self.view_ofs;
392         traceline_hitcorpse (self, org, org + v_forward * 4096 + v_right + v_up, FALSE, self);
393         
394         if ((trace_fraction != 1.0) && (trace_ent != self) && (pointcontents (trace_endpos) != CONTENT_SKY))
395         {
396                 if (trace_ent.classname == "case")
397                 {
398                         Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * damage);
399                 }
400                 else if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
401                 {
402                         te_blood (trace_endpos, dir * damage * 16, damage);
403                         Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * damage);
404                 }
405         }
406 }
407
408
409 void fireBullet (vector dir, float spread, float damage, float dtype)
410 {
411         vector  org;
412
413         makevectors (self.v_angle);
414
415         // use traceline_hitcorpse to make sure it can hit gibs and corpses too
416         org = self.origin + self.view_ofs;
417         traceline_hitcorpse (self, org, org + v_forward * 4096 + v_right * crandom () * spread + v_up * crandom () * spread, FALSE, self);
418
419         // FIXME - causes excessive 'tinking'. Hopefully remove "tink1.wav" from the ricochets with csqc
420         if ((trace_fraction != 1.0) && (trace_ent != self) && (pointcontents (trace_endpos) != CONTENT_SKY))
421         {
422                 if (trace_ent == world)
423                         te_gunshot (trace_endpos);
424                 else if (trace_ent.classname == "case")
425                 {
426 //                      te_gunshot (trace_endpos);
427                         Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * damage);
428                 }
429                 else if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
430                 {
431                         te_blood (trace_endpos, dir * damage * 16, damage);
432                         Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * damage);
433                         sound (trace_ent, CHAN_IMPACT, "misc/enemyimpact.wav", 1, ATTN_NORM);
434                 }
435         }
436 }
437
438 void W_Laser_Touch (void)
439 {
440         vector  dir;
441
442         if (other == self.owner)
443                 return;
444         else if (pointcontents (self.origin) == CONTENT_SKY)
445         {
446                 remove (self);
447                 return;
448         }
449
450         dir = normalize (self.owner.origin - self.origin);
451
452         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
453         WriteByte (MSG_BROADCAST, TE_FLAMEJET);
454         WriteCoord (MSG_BROADCAST, self.origin_x);
455         WriteCoord (MSG_BROADCAST, self.origin_y);
456         WriteCoord (MSG_BROADCAST, self.origin_z);
457         WriteCoord (MSG_BROADCAST, 0);          // SeienAbunae: groan... Useless clutter
458         WriteCoord (MSG_BROADCAST, 0);
459         WriteCoord (MSG_BROADCAST, 0);
460         WriteByte (MSG_BROADCAST, 155);
461
462         self.event_damage = SUB_Null;
463         RadiusDamage (self, self.owner, 15, 7, 50, world, 200, IT_LASER);
464         sound (self, CHAN_IMPACT, "weapons/laserimpact.wav", 1, ATTN_NORM);
465
466         remove (self);
467 }
468
469 void W_Laser_Attack (void)
470 {
471         entity  missile;
472
473         sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", 1, ATTN_NORM);
474
475         missile = spawn ();
476         missile.owner = self;
477         missile.classname = "spike";
478
479         missile.movetype = MOVETYPE_FLY;
480         missile.solid = SOLID_BBOX;
481
482         setmodel (missile, "models/bullet.mdl");
483         setsize (missile, '0 0 0', '0 0 0');
484         setorigin (missile, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
485
486         makevectors (self.v_angle);
487         missile.velocity = v_forward * 1000;
488         missile.velocity = missile.velocity + v_right * ( crandom() * 45 );
489         missile.velocity = missile.velocity + v_up * ( crandom() * 25 );
490         missile.angles = vectoangles (missile.velocity);
491         missile.glow_color = 250; // 244, 250
492         missile.glow_size = 30;
493         missile.touch = W_Laser_Touch;
494         missile.think = SUB_Remove;
495         missile.nextthink = time + 9;
496
497         self.punchangle_x = random () - 0.5;
498         self.punchangle_y = random () - 0.5;
499         self.punchangle_z = random () - 0.5;
500
501         self.attack_finished = time + 0.2;
502 }
503
504 void W_Laser_Attack2 (void)
505 {
506         entity  missile;
507
508         sound (self, CHAN_WEAPON, "weapons/lasergun_fire.wav", 1, ATTN_NORM);
509
510         missile = spawn ();
511         missile.owner = self;
512         missile.classname = "spike";
513
514         missile.movetype = MOVETYPE_FLY;
515         missile.solid = SOLID_BBOX;
516
517         setmodel (missile, "models/bullet.mdl");
518         setsize (missile, '0 0 0', '0 0 0');
519         setorigin (missile, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
520
521         makevectors (self.v_angle);
522         missile.velocity = v_forward * 4000;
523         missile.angles = vectoangles (missile.velocity);
524         missile.glow_color = 250; // 244, 250
525         missile.glow_size = 30;
526         missile.touch = W_Laser_Touch;
527         missile.think = SUB_Remove;
528         missile.nextthink = time + 2;
529
530         self.punchangle_x = random () - 0.5;
531         self.punchangle_y = random () - 0.5;
532         self.punchangle_z = random () - 0.5;
533
534         self.attack_finished = time + 0.4;
535 }
536
537 void W_Uzi_Attack (void)
538 {
539         sound (self, CHAN_WEAPON, "weapons/uzi_fire.wav", 1, ATTN_NORM);
540
541         fireBullet (v_forward, 100, 6, IT_UZI);
542
543         //self.punchangle = (randomvec() + '-1 0 0') * 2;
544         //self.punchangle_z = 0; // don't want roll
545
546         self.attack_finished = time + 0.075;
547         self.ammo_nails = self.ammo_nails - 1;
548
549         vector  org; // casing code
550         org = self.origin + self.view_ofs + (v_right * 6) - (v_up * 1) + (v_forward * 20);
551         SpawnCasing (org, v_forward, ((random () * 50 + 50) * v_right) - ((random () * 25 + 25) * v_forward) - ((random () * 5 + 10) * v_up), 1);
552         //W_Smoke(org, v_forward, 12);
553 }
554
555 void W_Uzi_Attack2 (void)
556 {
557         float   sc;
558         float   bullets;
559
560         sound (self, CHAN_WEAPON, "weapons/shotgun_fire.wav", 1, ATTN_NORM);
561
562         bullets = 5;
563         if (bullets > self.ammo_nails)
564                 bullets = self.ammo_nails;
565
566         for (sc = bullets; sc > 0; sc = sc - 1)
567                 fireBullet (v_forward, 400, 8, IT_SHOTGUN);
568
569         //self.punchangle_x = -2;
570
571         self.ammo_nails = self.ammo_nails - bullets;
572         self.attack_finished = time + 0.4;
573
574         vector  org; // casing code
575         org = self.origin + self.view_ofs + (v_right * 6) - (v_up * 4) + (v_forward * 15);
576         SpawnCasing (org, v_forward, ((random () * 50 + 50) * v_right) - ((random () * 25 + 25) * v_forward) - ((random () * 5 + 10) * v_up), 2);
577 }
578
579 void W_Shotgun_Attack (void)
580 {
581         float   sc;
582         float   bullets;
583
584         sound (self, CHAN_WEAPON, "weapons/shotgun_fire.wav", 1, ATTN_NORM);
585
586         bullets = 10;
587
588         for (sc = bullets; sc > 0; sc = sc - 1)
589                 fireBullet (v_forward, 150, 8, IT_SHOTGUN);
590
591         self.ammo_shells = self.ammo_shells - 1;
592         self.attack_finished = time + 0.7;
593
594         vector  org; // casing code
595         org = self.origin + self.view_ofs + (v_right * 6) - (v_up * 4) + (v_forward * 15);
596         SpawnCasing (org, v_forward, ((random () * 50 + 50) * v_right) - ((random () * 25 + 25) * v_forward) - ((random () * 5 + 10) * v_up), 2);
597 }
598
599 void W_Shotgun_Attack2 (void)
600 {
601
602 }
603
604 void W_Grenade_Explode (entity ignore)
605 {
606         ImpactEffect (self, IT_GRENADE_LAUNCHER);
607
608         self.event_damage = SUB_Null;
609         RadiusDamage (self, self.owner, 65, 35, 140, world, 400, IT_GRENADE_LAUNCHER);
610
611         remove (self);
612 }
613
614 void W_Grenade_FuseExplode (void)
615 {
616         W_Grenade_Explode (world);
617 }
618
619 void W_Grenade_Touch (void)
620 {
621         // I decided to take this out to add more skill to using the grenade launcher, so the user always has to trigger it.
622         // I increased the power of the grenade launcher because of this.
623         //if (other.classname == "player" || other.classname == "corpse")
624         //      W_Grenade_Explode (other);
625         //else
626         sound (self, CHAN_BODY, "weapons/grenade_bounce.wav", 1, ATTN_NORM);
627 }
628
629 void W_Grenade_Damage (vector hitloc, float damage, entity inflictor, entity attacker, float deathtype)
630 {
631         self.health = self.health - damage;
632         if (self.health <= 0)
633                 W_Grenade_FuseExplode();
634 }
635
636 void W_Grenade_Attack (void)
637 {
638         entity  gren;
639
640         sound (self, CHAN_WEAPON, "weapons/grenade_fire.wav", 1, ATTN_NORM);
641
642         self.punchangle_x = -4;
643
644         gren = spawn ();
645         gren.owner = self;
646         gren.classname = "grenade";
647
648         gren.movetype = MOVETYPE_BOUNCE;
649         gren.solid = SOLID_BBOX;
650
651         gren.takedamage = DAMAGE_YES;
652         gren.damageforcescale = 4;
653         gren.health = 10;
654         gren.event_damage = W_Grenade_Damage;
655
656         setmodel (gren, "models/grenademodel.md3");
657         setsize (gren, '-6 -6 -3', '6 6 3');
658
659         makevectors (self.v_angle);
660         setorigin (gren, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
661
662         gren.velocity = v_forward * 900 + v_up * 200;
663         gren.angles = vectoangles (gren.velocity);
664         gren.avelocity = '150 1500 150';
665
666         gren.touch = W_Grenade_Touch;
667         gren.think = W_Grenade_FuseExplode;
668         gren.nextthink = time + 5;
669
670         self.attack_finished = time + 0.8;
671         self.ammo_rockets = self.ammo_rockets - 1;
672 }
673
674 void W_Grenade_Attack2 (void)
675 {
676         entity  proj;
677         proj = findradius (self.origin, 50000);
678         while (proj)
679         {
680                 if (proj.classname == "grenade" && proj.owner == self)
681                 {
682                         proj.nextthink = time;
683                 }
684                 proj = proj.chain;
685         }
686
687         self.attack_finished = time;
688 }
689
690 void W_Electro_Touch (void)
691 {
692         vector dir;
693         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
694         WriteByte (MSG_BROADCAST, 79);
695         WriteCoord (MSG_BROADCAST, self.origin_x);
696         WriteCoord (MSG_BROADCAST, self.origin_y);
697         WriteCoord (MSG_BROADCAST, self.origin_z);
698         WriteCoord (MSG_BROADCAST, 0);          // SeienAbunae: groan... Useless clutter
699         WriteCoord (MSG_BROADCAST, 0);
700         WriteCoord (MSG_BROADCAST, 0);
701         WriteByte (MSG_BROADCAST, 155);
702         self.event_damage = SUB_Null;
703         RadiusDamage (self, self.owner, 50, 10, 70, world, 50, IT_ELECTRO);
704         sound (self, CHAN_IMPACT, "weapons/plasmahit.wav", 1, ATTN_NORM);
705         remove (self);
706 }
707
708 void W_Electro_Attack (float postion)
709 {
710         entity  proj;
711
712         sound (self, CHAN_WEAPON, "weapons/electro_fire.wav", 1, ATTN_NORM);
713
714         proj = spawn ();
715         proj.owner = self;
716         proj.classname = "spike";
717
718         proj.movetype = MOVETYPE_FLY; 
719         proj.solid = SOLID_BBOX;
720         proj.effects = 1;
721         
722         makevectors (self.v_angle);
723
724         vector org;
725         org = self.origin + self.view_ofs + v_forward * 18 + v_right * 7 + v_up * -9;
726         te_smallflash(org);
727
728         setmodel (proj, "models/bullet.mdl");
729         setsize (proj, '0 0 0', '0 0 0');
730         if (postion == 0)
731         setorigin (proj, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -14);
732         if (postion == 1)
733         setorigin (proj, self.origin + self.view_ofs + v_forward * 18 + v_right * 10 + v_up * -12);
734         if (postion == 2)
735         setorigin (proj, self.origin + self.view_ofs + v_forward * 18 + v_right * 15 + v_up * -14);
736
737         proj.velocity = v_forward * 2500;
738         proj.touch = W_Electro_Touch;
739         proj.think = SUB_Remove;
740         proj.nextthink = time + 9;
741
742         proj.effects = proj.effects | EF_ADDITIVE;
743
744         self.attack_finished = time + 0.4;
745         self.ammo_cells = self.ammo_cells - 1;
746 }
747
748 void W_Plasma_Explode (entity ignore)
749 {
750         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
751         WriteByte (MSG_BROADCAST, 79);
752         WriteCoord (MSG_BROADCAST, self.origin_x);
753         WriteCoord (MSG_BROADCAST, self.origin_y);
754         WriteCoord (MSG_BROADCAST, self.origin_z);
755         WriteCoord (MSG_BROADCAST, 0);          // SeienAbunae: groan... Useless clutter
756         WriteCoord (MSG_BROADCAST, 0);
757         WriteCoord (MSG_BROADCAST, 0);
758         WriteByte (MSG_BROADCAST, 155);
759
760         te_customflash (self.origin, 5000, 10, '0 0 1');
761
762         self.event_damage = SUB_Null;
763         RadiusDamage (self, self.owner, 100, 50, 100, world, 50, IT_ELECTRO);
764         sound (self, CHAN_IMPACT, "weapons/plasmahit.wav", 1, ATTN_NORM);
765
766         remove (self);
767 }
768
769 void W_Plasma_FuseExplode (void)
770 {
771         W_Plasma_Explode (world);
772 }
773
774 void W_Plasma_Touch (void)
775 {
776         if (other.classname == "player" || other.classname == "corpse")
777                 W_Plasma_Explode (other);
778         else
779                 sound (self, CHAN_BODY, "weapons/grenade_bounce.wav", 1, ATTN_NORM);
780 }
781
782 void W_Plasma_Damage (vector hitloc, float damage, entity inflictor, entity attacker, float deathtype)
783 {
784         self.health = self.health - damage;
785         if (self.health <= 0)
786                 W_Plasma_FuseExplode ();
787 }
788
789 void W_Electro_Attack2 (float postion)
790 {
791         entity  Plasma;
792
793         sound (self, CHAN_WEAPON, "weapons/electro_fire.wav", 1, ATTN_NORM);
794
795         self.punchangle_x = -4;
796
797         Plasma = spawn ();
798         Plasma.owner = self;
799         Plasma.classname = "grenade";
800         Plasma.effects = 1;
801
802         Plasma.movetype = MOVETYPE_BOUNCE;
803         Plasma.solid = SOLID_BBOX;
804         
805         vector org;
806         org = self.origin + self.view_ofs + v_forward * 18 + v_right * 7 + v_up * -9;
807         te_smallflash(org);
808
809         Plasma.takedamage = DAMAGE_YES;
810         Plasma.damageforcescale = 4;
811         Plasma.health = 5;
812         Plasma.event_damage = W_Plasma_Damage;
813
814         setmodel (Plasma, "models/bullet.mdl");
815         setsize (Plasma, '-6 -6 -3', '6 6 3');
816
817         makevectors (self.v_angle);
818
819         if (postion == 0)
820         setorigin (Plasma, self.origin + self.view_ofs + v_forward * 18 + v_right * 0 + v_up * -14);
821         if (postion == 1)
822         setorigin (Plasma, self.origin + self.view_ofs + v_forward * 18 + v_right * 10 + v_up * -12);
823         if (postion == 2)
824         setorigin (Plasma, self.origin + self.view_ofs + v_forward * 18 + v_right * 20 + v_up * -14);
825
826         Plasma.velocity = v_forward * 900 + v_up * 200;
827         Plasma.angles = vectoangles (Plasma.velocity);
828         Plasma.avelocity = '150 1500 150';
829
830         Plasma.touch = W_Plasma_Touch;
831         Plasma.think = W_Plasma_FuseExplode;
832         Plasma.nextthink = time + 2;
833
834         Plasma.effects = Plasma.effects | EF_ADDITIVE;
835
836         self.attack_finished = time + 1;
837         self.ammo_cells = self.ammo_cells - 2;
838
839 }
840
841 void W_Crylink_Touch (void)
842 {
843         vector dir;
844         self.event_damage = SUB_Null;
845         te_smallflash(self.origin);
846         RadiusDamage (self, self.owner, 20, 0, 3, world, 50, IT_CRYLINK);
847         remove (self);
848 }
849
850 void W_Crylink_Attack (void)
851 {
852         vector  org;
853
854         sound (self, CHAN_WEAPON, "weapons/crylink.wav", 1, ATTN_NORM);
855         org = self.origin + self.view_ofs + v_forward * 18 + v_right * 7 + v_up * -9;
856         makevectors (self.v_angle);
857
858         FireRailgunBullet (org, 25, v_forward, IT_CRYLINK);
859
860         traceline (org, self.origin + self.view_ofs + (v_forward * 4096), FALSE, self);
861
862         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
863         WriteByte (MSG_BROADCAST, 76);
864         WriteCoord (MSG_BROADCAST, org_x);
865         WriteCoord (MSG_BROADCAST, org_y);
866         WriteCoord (MSG_BROADCAST, org_z);
867         WriteCoord (MSG_BROADCAST, trace_endpos_x);
868         WriteCoord (MSG_BROADCAST, trace_endpos_y);
869         WriteCoord (MSG_BROADCAST, trace_endpos_z);
870         WriteCoord (MSG_BROADCAST, self.v_angle_x);
871         WriteCoord (MSG_BROADCAST, self.v_angle_y);
872         WriteCoord (MSG_BROADCAST, self.v_angle_z);
873
874         te_gunshot (trace_endpos);
875
876         self.ammo_cells = self.ammo_cells - 0.25;
877         self.attack_finished = time + 0.165;
878 }
879
880 void W_Crylink_Attack2 (void)
881 {
882
883         entity  proj;
884
885         //sound (self, CHAN_WEAPON, "weapons/electro_fire.wav", 1, ATTN_NORM);
886
887         proj = spawn ();
888         proj.owner = self;
889         proj.classname = "spike";
890
891         proj.movetype = MOVETYPE_FLY; 
892         proj.solid = SOLID_BBOX;
893         
894         makevectors (self.v_angle);
895
896         setmodel (proj, "models/sprites/bubbles.spr");
897         setsize (proj, '0 0 0', '0 0 0');
898         setorigin (proj, self.origin + self.view_ofs + v_forward * 10 + v_right * 5 + v_up * -14);
899
900         proj.velocity = v_forward * 1000;
901         proj.velocity = proj.velocity + v_right * ( crandom() * 50 );
902         proj.velocity = proj.velocity + v_up * ( crandom() * 50 );
903         proj.touch = W_Crylink_Touch;
904         proj.think = SUB_Remove;
905         proj.nextthink = time + 9;
906
907         proj.glow_color = 10;
908         proj.glow_size = 30;
909
910         self.attack_finished = time + 0.20;
911         self.ammo_cells = self.ammo_cells - 0.2;
912 }
913
914 void W_Nex_Attack (void)
915 {
916         vector  org;
917         vector  dir;
918         entity  explosion;
919
920         sound (self, CHAN_WEAPON, "weapons/nexfire.wav", 1, ATTN_NORM);
921         //self.effects = EF_MUZZLEFLASH;
922         self.punchangle_x = -4;
923
924         makevectors (self.v_angle);
925
926         org = self.origin + self.view_ofs + v_forward * 18 + v_right * 8 + v_up * -5;
927
928         traceline (org, self.origin + self.view_ofs + (v_forward * 4096), FALSE, self);
929
930         te_smallflash(org);
931
932         FireRailgunBullet (org, 80, v_forward, IT_NEX);
933
934         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
935         WriteByte (MSG_BROADCAST, 76);
936         WriteCoord (MSG_BROADCAST, org_x);
937         WriteCoord (MSG_BROADCAST, org_y);
938         WriteCoord (MSG_BROADCAST, org_z);
939         WriteCoord (MSG_BROADCAST, trace_endpos_x);
940         WriteCoord (MSG_BROADCAST, trace_endpos_y);
941         WriteCoord (MSG_BROADCAST, trace_endpos_z);
942         WriteCoord (MSG_BROADCAST, self.v_angle_x);
943         WriteCoord (MSG_BROADCAST, self.v_angle_y);
944         WriteCoord (MSG_BROADCAST, self.v_angle_z);
945
946         te_plasmaburn (trace_endpos);
947
948         dir = trace_plane_normal * 100;
949         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
950         WriteByte (MSG_BROADCAST, TE_FLAMEJET);
951         WriteCoord (MSG_BROADCAST, trace_endpos_x);
952         WriteCoord (MSG_BROADCAST, trace_endpos_y);
953         WriteCoord (MSG_BROADCAST, trace_endpos_z);
954         WriteCoord (MSG_BROADCAST, dir_x);
955         WriteCoord (MSG_BROADCAST, dir_y);
956         WriteCoord (MSG_BROADCAST, dir_z);
957         WriteByte (MSG_BROADCAST, 255);
958
959         explosion = spawn ();
960         setorigin (explosion, trace_endpos);
961         RadiusDamage (explosion, self, 10, 0, 50, world, 300, IT_ROCKET_LAUNCHER);
962         remove (explosion);
963
964         PointSound (trace_endpos, "weapons/neximpact.wav", 1, ATTN_NORM);
965
966         self.attack_finished = time + 1;
967         self.ammo_cells = self.ammo_cells - 1;
968 }
969
970 void W_Nex_Attack2 (void)
971 {
972
973 }
974
975 void() W_Drunkmissile = 
976 {
977         self.velocity = ((self.velocity + ((v_right * 61.000) * crandom ())) + ((v_up * 61.000) * crandom ()));
978         self.nextthink = time + 0.1;
979         self.think = W_Drunkmissile;
980 };
981
982
983 void W_Hagar_Explode (void)
984 {
985         ImpactEffect (self, IT_HAGAR);
986
987         self.event_damage = SUB_Null;
988         RadiusDamage (self, self.owner, 20, 10, 50, world, 90, IT_HAGAR);
989
990         remove (self);
991 }
992
993 void W_Hagar_Fireball (void)
994 {
995         self.effects = self.effects | EF_FLAME;
996 }
997
998 void W_Hagar_Touch (void)
999 {
1000         if (other == self.owner)
1001                 return;
1002         else if (pointcontents (self.origin) == CONTENT_SKY)
1003         {
1004                 remove (self);
1005                 return;
1006         }
1007
1008         W_Hagar_Explode ();
1009 }
1010
1011 void W_Hagar_Damage (vector hitloc, float damage, entity inflictor, entity attacker, float deathtype)
1012 {
1013         self.health = self.health - damage;
1014         if (self.health <= 0)
1015                 W_Hagar_Explode();
1016 }
1017
1018 void W_Hagar_Attack (void)
1019 {
1020         entity  missile;
1021         vector  org;
1022
1023         sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", 1, ATTN_NORM);
1024
1025         missile = spawn ();
1026         missile.owner = self;
1027         missile.classname = "missile";
1028
1029         missile.takedamage = DAMAGE_YES;
1030         missile.damageforcescale = 4;
1031         missile.health = 10;
1032         missile.event_damage = W_Hagar_Damage;
1033
1034         missile.movetype = MOVETYPE_FLY;
1035         missile.solid = SOLID_BBOX;
1036         setmodel (missile, "models/hagarmissile.mdl");
1037         setsize (missile, '0 0 0', '0 0 0');
1038
1039         makevectors (self.v_angle);
1040
1041         setorigin (missile, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
1042
1043         missile.velocity = v_forward * 2000;
1044         missile.velocity = missile.velocity + v_right * ( crandom() * 70 );
1045         missile.velocity = missile.velocity + v_up * ( crandom() * 30 );
1046         missile.angles = vectoangles (missile.velocity);
1047         setorigin (missile, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
1048
1049         missile.touch = W_Hagar_Touch;
1050         missile.think = W_Hagar_Explode;
1051         missile.nextthink = time + 10;
1052
1053         self.attack_finished = time + 0.2;
1054         self.ammo_rockets = self.ammo_rockets - 0.25;
1055 }
1056
1057 void W_Hagar_Attack2 (void)
1058 {
1059         entity  missile;
1060
1061         sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", 1, ATTN_NORM);
1062
1063         missile = spawn ();
1064         missile.owner = self;
1065         missile.classname = "missile";
1066
1067         missile.movetype = MOVETYPE_TOSS;
1068         missile.solid = SOLID_BBOX;
1069
1070         missile.takedamage = DAMAGE_YES;
1071         missile.damageforcescale = 4;
1072         missile.health = 5;
1073         missile.event_damage = W_Hagar_Damage;
1074
1075         setmodel (missile, "models/bullet.mdl");
1076         setsize (missile, '-6 -6 -3', '6 6 3');
1077
1078         makevectors (self.v_angle);
1079         setorigin (missile, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
1080
1081         missile.velocity = v_forward * 1400 + v_up * 100;
1082         missile.angles = vectoangles (missile.velocity);
1083         missile.avelocity = '150 1500 150';
1084
1085         missile.touch = W_Hagar_Touch;
1086         missile.think = W_Hagar_Fireball;
1087         missile.nextthink = time + 0.05;
1088
1089         self.attack_finished = time + 0.2;
1090         self.ammo_rockets = self.ammo_rockets - 0.25;
1091 }
1092
1093 void W_Hagar_Attack3 (void)
1094 {
1095         entity  missile;
1096         vector  org;
1097
1098         sound (self, CHAN_WEAPON, "weapons/hagar_fire.wav", 1, ATTN_NORM);
1099
1100         missile = spawn ();
1101         missile.owner = self;
1102         missile.classname = "missile";
1103
1104         missile.takedamage = DAMAGE_YES;
1105         missile.damageforcescale = 4;
1106         missile.health = 10;
1107         missile.event_damage = W_Hagar_Damage;
1108
1109         missile.movetype = MOVETYPE_FLY;
1110         missile.solid = SOLID_BBOX;
1111         setmodel (missile, "models/hagarmissile.mdl");
1112         setsize (missile, '0 0 0', '0 0 0');
1113
1114         makevectors (self.v_angle);
1115
1116         setorigin (missile, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
1117
1118         missile.velocity = v_forward * 1000;
1119         missile.angles = vectoangles (missile.velocity);
1120         setorigin (missile, self.origin + self.view_ofs + v_forward * 18 + v_right * 5 + v_up * -12);
1121
1122         missile.touch = W_Hagar_Touch;
1123         missile.think = W_Drunkmissile;
1124         missile.nextthink = time + 0.01;
1125
1126         self.attack_finished = time + 0.2;
1127         self.ammo_rockets = self.ammo_rockets - 0.25;
1128 }
1129
1130 void W_Rocket_Explode (entity ignore)
1131 {
1132         ImpactEffect (self, IT_ROCKET_LAUNCHER);
1133
1134         self.event_damage = SUB_Null;
1135         RadiusDamage (self, self.owner, 130, 50, 170, ignore, 600, IT_ROCKET_LAUNCHER);
1136
1137         remove (self);
1138 }
1139
1140 void W_Rocket_Think (void)
1141 {
1142         W_Rocket_Explode (world);
1143 }
1144
1145 void W_Rocket_Touch (void)
1146 {
1147         if (other == self.owner)
1148                 return;
1149         else if (pointcontents (self.origin) == CONTENT_SKY)
1150         {
1151                 remove (self);
1152                 return;
1153         }
1154         else
1155                 W_Rocket_Explode (world);
1156 }
1157
1158 void W_Rocket_Damage (vector hitloc, float damage, entity inflictor, entity attacker, float deathtype)
1159 {
1160         self.health = self.health - damage;
1161         if (self.health <= 0)
1162                 W_Rocket_Explode(world);
1163 }
1164
1165 void W_Rocket_Attack (void)
1166 {
1167         entity  missile;
1168         vector  org;
1169
1170         sound (self, CHAN_WEAPON, "weapons/rocket_fire.wav", 1, ATTN_NORM);
1171
1172         missile = spawn ();
1173         missile.owner = self;
1174         missile.classname = "missile";
1175
1176         missile.takedamage = DAMAGE_YES;
1177         missile.damageforcescale = 4;
1178         missile.health = 10;
1179         missile.event_damage = W_Rocket_Damage;
1180
1181         missile.movetype = MOVETYPE_FLY;
1182         missile.solid = SOLID_BBOX;
1183         setmodel (missile, "models/rocketmissile.mdl");
1184         setsize (missile, '0 0 0', '0 0 0');
1185
1186         makevectors (self.v_angle);
1187
1188         org = self.origin + self.view_ofs + v_forward * 20 + v_right * 4 + v_up * -15;
1189
1190         setorigin (missile, org);
1191         missile.velocity = v_forward * 1200;
1192         missile.angles = vectoangles (missile.velocity);
1193
1194         missile.touch = W_Rocket_Touch ;
1195         missile.think = W_Rocket_Think;
1196         missile.nextthink = time + 9;
1197
1198         self.attack_finished = time + 1.5;
1199         self.ammo_rockets = self.ammo_rockets - 1;
1200
1201 }
1202
1203 void W_Rocket_Attack2 (void)
1204 {
1205         entity  proj;
1206         proj = findradius (self.origin, 50000);
1207         while (proj)
1208         {
1209                 if (proj.classname == "missile" && proj.owner == self)
1210                 {
1211                         proj.nextthink = time;
1212                 }
1213                 proj = proj.chain;
1214         }
1215
1216         self.attack_finished = time;
1217 }
1218
1219
1220 void W_Attack (void)
1221 {
1222         if (self.deadflag != DEAD_NO)
1223         {
1224                 if (self.death_time < time)
1225                         PutClientInServer();
1226
1227                 return;
1228         }
1229
1230         if (!W_CheckAmmo ())
1231                 return;
1232
1233         if (self.weapon == IT_LASER)
1234                 W_Laser_Attack ();
1235         else if (self.weapon == IT_UZI)
1236                 W_Uzi_Attack ();
1237         else if (self.weapon == IT_SHOTGUN)
1238                 W_Shotgun_Attack ();
1239         else if (self.weapon == IT_GRENADE_LAUNCHER)
1240                 W_Grenade_Attack ();
1241         else if (self.weapon == IT_ELECTRO)
1242                 {
1243                 W_Electro_Attack (self.electrocount);
1244                 self.electrocount = self.electrocount + 1;
1245                 if (self.electrocount == 3)
1246                         self.electrocount = 0;
1247                 }
1248         else if (self.weapon == IT_CRYLINK)
1249                 W_Crylink_Attack ();
1250         else if (self.weapon == IT_NEX)
1251                 W_Nex_Attack ();
1252         else if (self.weapon == IT_HAGAR)
1253                 W_Hagar_Attack ();
1254         else if (self.weapon == IT_ROCKET_LAUNCHER)
1255                 W_Rocket_Attack ();
1256
1257         W_UpdateAmmo ();
1258 }
1259
1260 void W_SecondaryAttack (void)
1261 {
1262         if (self.deadflag != DEAD_NO)
1263         {
1264                 if (self.death_time < time)
1265                         PutClientInServer();
1266
1267                 return;
1268         }
1269
1270         if (!W_CheckAmmo ())
1271                 return;
1272
1273         if (self.weapon == IT_LASER)
1274                 W_Laser_Attack2 ();
1275         else if (self.weapon == IT_UZI)
1276                 W_Uzi_Attack2 ();
1277         else if (self.weapon == IT_SHOTGUN)
1278                 W_Shotgun_Attack2 ();
1279         else if (self.weapon == IT_GRENADE_LAUNCHER)
1280                 W_Grenade_Attack2 ();
1281         else if (self.weapon == IT_ELECTRO) {
1282                 W_Electro_Attack2 (self.electrocount);
1283                 self.electrocount = self.electrocount + 1;
1284                 if (self.electrocount == 3)
1285                         self.electrocount = 0;
1286                 }
1287         else if (self.weapon == IT_CRYLINK)
1288                 W_Crylink_Attack2 ();
1289         else if (self.weapon == IT_NEX)
1290                 W_Nex_Attack2 ();
1291         else if (self.weapon == IT_HAGAR)
1292                 W_Hagar_Attack2 ();
1293         else if (self.weapon == IT_ROCKET_LAUNCHER)
1294                 W_Rocket_Attack2 ();
1295
1296         W_UpdateAmmo ();
1297 }
1298
1299 void W_ThirdAttack (void)
1300 {
1301         if (self.deadflag != DEAD_NO)
1302         {
1303                 if (self.death_time < time)
1304                         PutClientInServer();
1305
1306                 return;
1307         }
1308
1309         if (!W_CheckAmmo ())
1310                 return;
1311
1312         if (self.weapon == IT_HAGAR)
1313                 W_Hagar_Attack3 ();
1314
1315         W_UpdateAmmo ();
1316 }