|
|
1.1 root 1: /*
2: */
3: void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
4: void () player_run;
5: void(entity bomb, entity attacker, float rad, entity ignore, string dtype) T_RadiusDamage;
6: void(vector org, float damage) SpawnBlood;
7: void() SuperDamageSound;
8:
9:
10: // called by worldspawn
11: void() W_Precache =
12: {
13: precache_sound ("weapons/r_exp3.wav"); // new rocket explosion
14: precache_sound ("weapons/rocket1i.wav"); // spike gun
15: precache_sound ("weapons/sgun1.wav");
16: precache_sound ("weapons/guncock.wav"); // player shotgun
17: precache_sound ("weapons/ric1.wav"); // ricochet (used in c code)
18: precache_sound ("weapons/ric2.wav"); // ricochet (used in c code)
19: precache_sound ("weapons/ric3.wav"); // ricochet (used in c code)
20: precache_sound ("weapons/spike2.wav"); // super spikes
21: precache_sound ("weapons/tink1.wav"); // spikes tink (used in c code)
22: precache_sound ("weapons/grenade.wav"); // grenade launcher
23: precache_sound ("weapons/bounce.wav"); // grenade bounce
24: precache_sound ("weapons/shotgn2.wav"); // super shotgun
25: };
26:
27: float() crandom =
28: {
29: return 2*(random() - 0.5);
30: };
31:
32: /*
33: ================
34: W_FireAxe
35: ================
36: */
37: void() W_FireAxe =
38: {
39: local vector source;
40: local vector org;
41:
42: makevectors (self.v_angle);
43: source = self.origin + '0 0 16';
44: traceline (source, source + v_forward*64, FALSE, self);
45: if (trace_fraction == 1.0)
46: return;
47:
48: org = trace_endpos - v_forward*4;
49:
50: if (trace_ent.takedamage)
51: {
52: trace_ent.axhitme = 1;
53: SpawnBlood (org, 20);
54: if (deathmatch > 3)
55: T_Damage (trace_ent, self, self, 75);
56: else
57: T_Damage (trace_ent, self, self, 20);
58: }
59: else
60: { // hit wall
61: sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
62:
63: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
64: WriteByte (MSG_MULTICAST, TE_GUNSHOT);
65: WriteByte (MSG_MULTICAST, 3);
66: WriteCoord (MSG_MULTICAST, org_x);
67: WriteCoord (MSG_MULTICAST, org_y);
68: WriteCoord (MSG_MULTICAST, org_z);
69: multicast (org, MULTICAST_PVS);
70: }
71: };
72:
73:
74: //============================================================================
75:
76:
77: vector() wall_velocity =
78: {
79: local vector vel;
80:
81: vel = normalize (self.velocity);
82: vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
83: vel = vel + 2*trace_plane_normal;
84: vel = vel * 200;
85:
86: return vel;
87: };
88:
89:
90: /*
91: ================
92: SpawnMeatSpray
93: ================
94: */
95: void(vector org, vector vel) SpawnMeatSpray =
96: {
97: local entity missile;
98: local vector org;
99:
100: missile = spawn ();
101: missile.owner = self;
102: missile.movetype = MOVETYPE_BOUNCE;
103: missile.solid = SOLID_NOT;
104:
105: makevectors (self.angles);
106:
107: missile.velocity = vel;
108: missile.velocity_z = missile.velocity_z + 250 + 50*random();
109:
110: missile.avelocity = '3000 1000 2000';
111:
112: // set missile duration
113: missile.nextthink = time + 1;
114: missile.think = SUB_Remove;
115:
116: setmodel (missile, "progs/zom_gib.mdl");
117: setsize (missile, '0 0 0', '0 0 0');
118: setorigin (missile, org);
119: };
120:
121: /*
122: ================
123: SpawnBlood
124: ================
125: */
126: void(vector org, float damage) SpawnBlood =
127: {
128: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
129: WriteByte (MSG_MULTICAST, TE_BLOOD);
130: WriteByte (MSG_MULTICAST, 1);
131: WriteCoord (MSG_MULTICAST, org_x);
132: WriteCoord (MSG_MULTICAST, org_y);
133: WriteCoord (MSG_MULTICAST, org_z);
134: multicast (org, MULTICAST_PVS);
135: };
136:
137: /*
138: ================
139: spawn_touchblood
140: ================
141: */
142: void(float damage) spawn_touchblood =
143: {
144: local vector vel;
145:
146: vel = wall_velocity () * 0.2;
147: SpawnBlood (self.origin + vel*0.01, damage);
148: };
149:
150: /*
151: ==============================================================================
152:
153: MULTI-DAMAGE
154:
155: Collects multiple small damages into a single damage
156:
157: ==============================================================================
158: */
159:
160: entity multi_ent;
161: float multi_damage;
162:
163: vector blood_org;
164: float blood_count;
165:
166: vector puff_org;
167: float puff_count;
168:
169: void() ClearMultiDamage =
170: {
171: multi_ent = world;
172: multi_damage = 0;
173: blood_count = 0;
174: puff_count = 0;
175: };
176:
177: void() ApplyMultiDamage =
178: {
179: if (!multi_ent)
180: return;
181: T_Damage (multi_ent, self, self, multi_damage);
182: };
183:
184: void(entity hit, float damage) AddMultiDamage =
185: {
186: if (!hit)
187: return;
188:
189: if (hit != multi_ent)
190: {
191: ApplyMultiDamage ();
192: multi_damage = damage;
193: multi_ent = hit;
194: }
195: else
196: multi_damage = multi_damage + damage;
197: };
198:
199: void() Multi_Finish =
200: {
201: if (puff_count)
202: {
203: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
204: WriteByte (MSG_MULTICAST, TE_GUNSHOT);
205: WriteByte (MSG_MULTICAST, puff_count);
206: WriteCoord (MSG_MULTICAST, puff_org_x);
207: WriteCoord (MSG_MULTICAST, puff_org_y);
208: WriteCoord (MSG_MULTICAST, puff_org_z);
209: multicast (puff_org, MULTICAST_PVS);
210: }
211:
212: if (blood_count)
213: {
214: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
215: WriteByte (MSG_MULTICAST, TE_BLOOD);
216: WriteByte (MSG_MULTICAST, blood_count);
217: WriteCoord (MSG_MULTICAST, blood_org_x);
218: WriteCoord (MSG_MULTICAST, blood_org_y);
219: WriteCoord (MSG_MULTICAST, blood_org_z);
220: multicast (puff_org, MULTICAST_PVS);
221: }
222: };
223:
224: /*
225: ==============================================================================
226: BULLETS
227: ==============================================================================
228: */
229:
230: /*
231: ================
232: TraceAttack
233: ================
234: */
235: void(float damage, vector dir) TraceAttack =
236: {
237: local vector vel, org;
238:
239: vel = normalize(dir + v_up*crandom() + v_right*crandom());
240: vel = vel + 2*trace_plane_normal;
241: vel = vel * 200;
242:
243: org = trace_endpos - dir*4;
244:
245: if (trace_ent.takedamage)
246: {
247: blood_count = blood_count + 1;
248: blood_org = org;
249: AddMultiDamage (trace_ent, damage);
250: }
251: else
252: {
253: puff_count = puff_count + 1;
254: }
255: };
256:
257: /*
258: ================
259: FireBullets
260:
261: Used by shotgun, super shotgun, and enemy soldier firing
262: Go to the trouble of combining multiple pellets into a single damage call.
263: ================
264: */
265: void(float shotcount, vector dir, vector spread) FireBullets =
266: {
267: local vector direction;
268: local vector src;
269:
270: makevectors(self.v_angle);
271:
272: src = self.origin + v_forward*10;
273: src_z = self.absmin_z + self.size_z * 0.7;
274:
275: ClearMultiDamage ();
276:
277: traceline (src, src + dir*2048, FALSE, self);
278: puff_org = trace_endpos - dir*4;
279:
280: while (shotcount > 0)
281: {
282: direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
283: traceline (src, src + direction*2048, FALSE, self);
284: if (trace_fraction != 1.0)
285: TraceAttack (4, direction);
286:
287: shotcount = shotcount - 1;
288: }
289: ApplyMultiDamage ();
290: Multi_Finish ();
291: };
292:
293: /*
294: ================
295: W_FireShotgun
296: ================
297: */
298: void() W_FireShotgun =
299: {
300: local vector dir;
301:
302: sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
303:
304: msg_entity = self;
305: WriteByte (MSG_ONE, SVC_SMALLKICK);
306:
307: if (deathmatch != 4 )
308: self.currentammo = self.ammo_shells = self.ammo_shells - 1;
309:
310: dir = aim (self, 100000);
311: FireBullets (6, dir, '0.04 0.04 0');
312: };
313:
314:
315: /*
316: ================
317: W_FireSuperShotgun
318: ================
319: */
320: void() W_FireSuperShotgun =
321: {
322: local vector dir;
323:
324: if (self.currentammo == 1)
325: {
326: W_FireShotgun ();
327: return;
328: }
329:
330: sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
331:
332: msg_entity = self;
333: WriteByte (MSG_ONE, SVC_BIGKICK);
334:
335: if (deathmatch != 4)
336: self.currentammo = self.ammo_shells = self.ammo_shells - 2;
337: dir = aim (self, 100000);
338: FireBullets (14, dir, '0.14 0.08 0');
339: };
340:
341:
342: /*
343: ==============================================================================
344:
345: ROCKETS
346:
347: ==============================================================================
348: */
349:
350: void() T_MissileTouch =
351: {
352: local float damg;
353:
354: // if (deathmatch == 4)
355: // {
356: // if ( ((other.weapon == 32) || (other.weapon == 16)))
357: // {
358: // if (random() < 0.1)
359: // {
360: // if (other != world)
361: // {
362: // // bprint (PRINT_HIGH, "Got here\n");
363: // other.deathtype = "blaze";
364: // T_Damage (other, self, self.owner, 1000 );
365: // T_RadiusDamage (self, self.owner, 1000, other);
366: // }
367: // }
368: // }
369: // }
370:
371: if (other == self.owner)
372: return; // don't explode on owner
373:
374: if (self.voided) {
375: return;
376: }
377: self.voided = 1;
378:
379: if (pointcontents(self.origin) == CONTENT_SKY)
380: {
381: remove(self);
382: return;
383: }
384:
385: damg = 100 + random()*20;
386:
387: if (other.health)
388: {
389: other.deathtype = "rocket";
390: T_Damage (other, self, self.owner, damg );
391: }
392:
393: // don't do radius damage to the other, because all the damage
394: // was done in the impact
395:
396:
397: T_RadiusDamage (self, self.owner, 120, other, "rocket");
398:
399: // sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
400: self.origin = self.origin - 8 * normalize(self.velocity);
401:
402: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
403: WriteByte (MSG_MULTICAST, TE_EXPLOSION);
404: WriteCoord (MSG_MULTICAST, self.origin_x);
405: WriteCoord (MSG_MULTICAST, self.origin_y);
406: WriteCoord (MSG_MULTICAST, self.origin_z);
407: multicast (self.origin, MULTICAST_PHS);
408:
409: remove(self);
410: };
411:
412:
413:
414: /*
415: ================
416: W_FireRocket
417: ================
418: */
419: void() W_FireRocket =
420: {
421: if (deathmatch != 4)
422: self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
423:
424: sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
425:
426: msg_entity = self;
427: WriteByte (MSG_ONE, SVC_SMALLKICK);
428:
429: newmis = spawn ();
430: newmis.owner = self;
431: newmis.movetype = MOVETYPE_FLYMISSILE;
432: newmis.solid = SOLID_BBOX;
433:
434: // set newmis speed
435:
436: makevectors (self.v_angle);
437: newmis.velocity = aim(self, 1000);
438: newmis.velocity = newmis.velocity * 1000;
439: newmis.angles = vectoangles(newmis.velocity);
440:
441: newmis.touch = T_MissileTouch;
442: newmis.voided = 0;
443:
444: // set newmis duration
445: newmis.nextthink = time + 5;
446: newmis.think = SUB_Remove;
447: newmis.classname = "rocket";
448:
449: setmodel (newmis, "progs/missile.mdl");
450: setsize (newmis, '0 0 0', '0 0 0');
451: setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
452: };
453:
454: /*
455: ===============================================================================
456: LIGHTNING
457: ===============================================================================
458: */
459:
460: void(entity from, float damage) LightningHit =
461: {
462: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
463: WriteByte (MSG_MULTICAST, TE_LIGHTNINGBLOOD);
464: WriteCoord (MSG_MULTICAST, trace_endpos_x);
465: WriteCoord (MSG_MULTICAST, trace_endpos_y);
466: WriteCoord (MSG_MULTICAST, trace_endpos_z);
467: multicast (trace_endpos, MULTICAST_PVS);
468:
469: T_Damage (trace_ent, from, from, damage);
470: };
471:
472: /*
473: =================
474: LightningDamage
475: =================
476: */
477: void(vector p1, vector p2, entity from, float damage) LightningDamage =
478: {
479: local entity e1, e2;
480: local vector f;
481:
482: f = p2 - p1;
483: normalize (f);
484: f_x = 0 - f_y;
485: f_y = f_x;
486: f_z = 0;
487: f = f*16;
488:
489: e1 = e2 = world;
490:
491: traceline (p1, p2, FALSE, self);
492:
493: if (trace_ent.takedamage)
494: {
495: LightningHit (from, damage);
496: if (self.classname == "player")
497: {
498: if (other.classname == "player")
499: trace_ent.velocity_z = trace_ent.velocity_z + 400;
500: }
501: }
502: e1 = trace_ent;
503:
504: traceline (p1 + f, p2 + f, FALSE, self);
505: if (trace_ent != e1 && trace_ent.takedamage)
506: {
507: LightningHit (from, damage);
508: }
509: e2 = trace_ent;
510:
511: traceline (p1 - f, p2 - f, FALSE, self);
512: if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
513: {
514: LightningHit (from, damage);
515: }
516: };
517:
518:
519: void() W_FireLightning =
520: {
521: local vector org;
522: local float cells;
523:
524: if (self.ammo_cells < 1)
525: {
526: self.weapon = W_BestWeapon ();
527: W_SetCurrentAmmo ();
528: return;
529: }
530:
531: // explode if under water
532: if (self.waterlevel > 1)
533: {
534: if (deathmatch > 3)
535: {
536: if (random() <= 0.5)
537: {
538: self.deathtype = "selfwater";
539: T_Damage (self, self, self.owner, 4000 );
540: }
541: else
542: {
543: cells = self.ammo_cells;
544: self.ammo_cells = 0;
545: W_SetCurrentAmmo ();
546: T_RadiusDamage (self, self, 35*cells, world, "");
547: return;
548: }
549: }
550: else
551: {
552: cells = self.ammo_cells;
553: self.ammo_cells = 0;
554: W_SetCurrentAmmo ();
555: T_RadiusDamage (self, self, 35*cells, world,"");
556: return;
557: }
558: }
559:
560: if (self.t_width < time)
561: {
562: sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
563: self.t_width = time + 0.6;
564: }
565: msg_entity = self;
566: WriteByte (MSG_ONE, SVC_SMALLKICK);
567:
568: if (deathmatch != 4)
569: self.currentammo = self.ammo_cells = self.ammo_cells - 1;
570:
571: org = self.origin + '0 0 16';
572:
573: traceline (org, org + v_forward*600, TRUE, self);
574:
575: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
576: WriteByte (MSG_MULTICAST, TE_LIGHTNING2);
577: WriteEntity (MSG_MULTICAST, self);
578: WriteCoord (MSG_MULTICAST, org_x);
579: WriteCoord (MSG_MULTICAST, org_y);
580: WriteCoord (MSG_MULTICAST, org_z);
581: WriteCoord (MSG_MULTICAST, trace_endpos_x);
582: WriteCoord (MSG_MULTICAST, trace_endpos_y);
583: WriteCoord (MSG_MULTICAST, trace_endpos_z);
584: multicast (org, MULTICAST_PHS);
585:
586: LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
587: };
588:
589:
590: //=============================================================================
591:
592:
593: void() GrenadeExplode =
594: {
595: if (self.voided) {
596: return;
597: }
598: self.voided = 1;
599:
600: T_RadiusDamage (self, self.owner, 120, world, "grenade");
601:
602: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
603: WriteByte (MSG_MULTICAST, TE_EXPLOSION);
604: WriteCoord (MSG_MULTICAST, self.origin_x);
605: WriteCoord (MSG_MULTICAST, self.origin_y);
606: WriteCoord (MSG_MULTICAST, self.origin_z);
607: multicast (self.origin, MULTICAST_PHS);
608:
609: remove (self);
610: };
611:
612: void() GrenadeTouch =
613: {
614: if (other == self.owner)
615: return; // don't explode on owner
616: if (other.takedamage == DAMAGE_AIM)
617: {
618: GrenadeExplode();
619: return;
620: }
621: sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
622: if (self.velocity == '0 0 0')
623: self.avelocity = '0 0 0';
624: };
625:
626: /*
627: ================
628: W_FireGrenade
629: ================
630: */
631: void() W_FireGrenade =
632: {
633: if (deathmatch != 4)
634: self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
635:
636: sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
637:
638: msg_entity = self;
639: WriteByte (MSG_ONE, SVC_SMALLKICK);
640:
641: newmis = spawn ();
642: newmis.voided=0;
643: newmis.owner = self;
644: newmis.movetype = MOVETYPE_BOUNCE;
645: newmis.solid = SOLID_BBOX;
646: newmis.classname = "grenade";
647:
648: // set newmis speed
649:
650: makevectors (self.v_angle);
651:
652: if (self.v_angle_x)
653: newmis.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
654: else
655: {
656: newmis.velocity = aim(self, 10000);
657: newmis.velocity = newmis.velocity * 600;
658: newmis.velocity_z = 200;
659: }
660:
661: newmis.avelocity = '300 300 300';
662:
663: newmis.angles = vectoangles(newmis.velocity);
664:
665: newmis.touch = GrenadeTouch;
666:
667: // set newmis duration
668: if (deathmatch == 4)
669: {
670: newmis.nextthink = time + 2.5;
671: self.attack_finished = time + 1.1;
672: // self.health = self.health - 1;
673: T_Damage (self, self, self.owner, 10 );
674: }
675: else
676: newmis.nextthink = time + 2.5;
677:
678: newmis.think = GrenadeExplode;
679:
680: setmodel (newmis, "progs/grenade.mdl");
681: setsize (newmis, '0 0 0', '0 0 0');
682: setorigin (newmis, self.origin);
683: };
684:
685:
686: //=============================================================================
687:
688: void() spike_touch;
689: void() superspike_touch;
690:
691:
692: /*
693: ===============
694: launch_spike
695:
696: Used for both the player and the ogre
697: ===============
698: */
699: void(vector org, vector dir) launch_spike =
700: {
701: newmis = spawn ();
702: newmis.voided=0;
703: newmis.owner = self;
704: newmis.movetype = MOVETYPE_FLYMISSILE;
705: newmis.solid = SOLID_BBOX;
706:
707: newmis.angles = vectoangles(dir);
708:
709: newmis.touch = spike_touch;
710: newmis.classname = "spike";
711: newmis.think = SUB_Remove;
712: newmis.nextthink = time + 6;
713: setmodel (newmis, "progs/spike.mdl");
714: setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
715: setorigin (newmis, org);
716:
717: newmis.velocity = dir * 1000;
718: };
719:
720: void() W_FireSuperSpikes =
721: {
722: local vector dir;
723: local entity old;
724:
725: sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
726: self.attack_finished = time + 0.2;
727: if (deathmatch != 4)
728: self.currentammo = self.ammo_nails = self.ammo_nails - 2;
729: dir = aim (self, 1000);
730: launch_spike (self.origin + '0 0 16', dir);
731: newmis.touch = superspike_touch;
732: setmodel (newmis, "progs/s_spike.mdl");
733: setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
734: msg_entity = self;
735: WriteByte (MSG_ONE, SVC_SMALLKICK);
736: };
737:
738: void(float ox) W_FireSpikes =
739: {
740: local vector dir;
741: local entity old;
742:
743: makevectors (self.v_angle);
744:
745: if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
746: {
747: W_FireSuperSpikes ();
748: return;
749: }
750:
751: if (self.ammo_nails < 1)
752: {
753: self.weapon = W_BestWeapon ();
754: W_SetCurrentAmmo ();
755: return;
756: }
757:
758: sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
759: self.attack_finished = time + 0.2;
760: if (deathmatch != 4)
761: self.currentammo = self.ammo_nails = self.ammo_nails - 1;
762: dir = aim (self, 1000);
763: launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
764:
765: msg_entity = self;
766: WriteByte (MSG_ONE, SVC_SMALLKICK);
767: };
768:
769:
770:
771: .float hit_z;
772: void() spike_touch =
773: {
774: local float rand;
775: if (other == self.owner)
776: return;
777:
778: if (self.voided) {
779: return;
780: }
781: self.voided = 1;
782:
783: if (other.solid == SOLID_TRIGGER)
784: return; // trigger field, do nothing
785:
786: if (pointcontents(self.origin) == CONTENT_SKY)
787: {
788: remove(self);
789: return;
790: }
791:
792: // hit something that bleeds
793: if (other.takedamage)
794: {
795: spawn_touchblood (9);
796: other.deathtype = "nail";
797: T_Damage (other, self, self.owner, 9);
798: }
799: else
800: {
801: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
802: if (self.classname == "wizspike")
803: WriteByte (MSG_MULTICAST, TE_WIZSPIKE);
804: else if (self.classname == "knightspike")
805: WriteByte (MSG_MULTICAST, TE_KNIGHTSPIKE);
806: else
807: WriteByte (MSG_MULTICAST, TE_SPIKE);
808: WriteCoord (MSG_MULTICAST, self.origin_x);
809: WriteCoord (MSG_MULTICAST, self.origin_y);
810: WriteCoord (MSG_MULTICAST, self.origin_z);
811: multicast (self.origin, MULTICAST_PHS);
812: }
813:
814: remove(self);
815:
816: };
817:
818: void() superspike_touch =
819: {
820: local float rand;
821: if (other == self.owner)
822: return;
823:
824: if (self.voided) {
825: return;
826: }
827: self.voided = 1;
828:
829:
830: if (other.solid == SOLID_TRIGGER)
831: return; // trigger field, do nothing
832:
833: if (pointcontents(self.origin) == CONTENT_SKY)
834: {
835: remove(self);
836: return;
837: }
838:
839: // hit something that bleeds
840: if (other.takedamage)
841: {
842: spawn_touchblood (18);
843: other.deathtype = "supernail";
844: T_Damage (other, self, self.owner, 18);
845: }
846: else
847: {
848: WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
849: WriteByte (MSG_MULTICAST, TE_SUPERSPIKE);
850: WriteCoord (MSG_MULTICAST, self.origin_x);
851: WriteCoord (MSG_MULTICAST, self.origin_y);
852: WriteCoord (MSG_MULTICAST, self.origin_z);
853: multicast (self.origin, MULTICAST_PHS);
854: }
855:
856: remove(self);
857:
858: };
859:
860:
861: /*
862: ===============================================================================
863:
864: PLAYER WEAPON USE
865:
866: ===============================================================================
867: */
868:
869: void() W_SetCurrentAmmo =
870: {
871: player_run (); // get out of any weapon firing states
872:
873: self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
874:
875: if (self.weapon == IT_AXE)
876: {
877: self.currentammo = 0;
878: self.weaponmodel = "progs/v_axe.mdl";
879: self.weaponframe = 0;
880: }
881: else if (self.weapon == IT_SHOTGUN)
882: {
883: self.currentammo = self.ammo_shells;
884: self.weaponmodel = "progs/v_shot.mdl";
885: self.weaponframe = 0;
886: self.items = self.items | IT_SHELLS;
887: }
888: else if (self.weapon == IT_SUPER_SHOTGUN)
889: {
890: self.currentammo = self.ammo_shells;
891: self.weaponmodel = "progs/v_shot2.mdl";
892: self.weaponframe = 0;
893: self.items = self.items | IT_SHELLS;
894: }
895: else if (self.weapon == IT_NAILGUN)
896: {
897: self.currentammo = self.ammo_nails;
898: self.weaponmodel = "progs/v_nail.mdl";
899: self.weaponframe = 0;
900: self.items = self.items | IT_NAILS;
901: }
902: else if (self.weapon == IT_SUPER_NAILGUN)
903: {
904: self.currentammo = self.ammo_nails;
905: self.weaponmodel = "progs/v_nail2.mdl";
906: self.weaponframe = 0;
907: self.items = self.items | IT_NAILS;
908: }
909: else if (self.weapon == IT_GRENADE_LAUNCHER)
910: {
911: self.currentammo = self.ammo_rockets;
912: self.weaponmodel = "progs/v_rock.mdl";
913: self.weaponframe = 0;
914: self.items = self.items | IT_ROCKETS;
915: }
916: else if (self.weapon == IT_ROCKET_LAUNCHER)
917: {
918: self.currentammo = self.ammo_rockets;
919: self.weaponmodel = "progs/v_rock2.mdl";
920: self.weaponframe = 0;
921: self.items = self.items | IT_ROCKETS;
922: }
923: else if (self.weapon == IT_LIGHTNING)
924: {
925: self.currentammo = self.ammo_cells;
926: self.weaponmodel = "progs/v_light.mdl";
927: self.weaponframe = 0;
928: self.items = self.items | IT_CELLS;
929: }
930: else
931: {
932: self.currentammo = 0;
933: self.weaponmodel = "";
934: self.weaponframe = 0;
935: }
936: };
937:
938: float() W_BestWeapon =
939: {
940: local float it;
941:
942: it = self.items;
943:
944: if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
945: return IT_LIGHTNING;
946: else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
947: return IT_SUPER_NAILGUN;
948: else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
949: return IT_SUPER_SHOTGUN;
950: else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
951: return IT_NAILGUN;
952: else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
953: return IT_SHOTGUN;
954:
955: /*
956: if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
957: return IT_ROCKET_LAUNCHER;
958: else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
959: return IT_GRENADE_LAUNCHER;
960:
961: */
962:
963: return IT_AXE;
964: };
965:
966: float() W_CheckNoAmmo =
967: {
968: if (self.currentammo > 0)
969: return TRUE;
970:
971: if (self.weapon == IT_AXE)
972: return TRUE;
973:
974: self.weapon = W_BestWeapon ();
975:
976: W_SetCurrentAmmo ();
977:
978: // drop the weapon down
979: return FALSE;
980: };
981:
982: /*
983: ============
984: W_Attack
985:
986: An attack impulse can be triggered now
987: ============
988: */
989: void() player_axe1;
990: void() player_axeb1;
991: void() player_axec1;
992: void() player_axed1;
993: void() player_shot1;
994: void() player_nail1;
995: void() player_light1;
996: void() player_rocket1;
997:
998: void() W_Attack =
999: {
1000: local float r;
1001:
1002: if (!W_CheckNoAmmo ())
1003: return;
1004:
1005: makevectors (self.v_angle); // calculate forward angle for velocity
1006: self.show_hostile = time + 1; // wake monsters up
1007:
1008: if (self.weapon == IT_AXE)
1009: {
1010: self.attack_finished = time + 0.5;
1011: sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
1012: r = random();
1013: if (r < 0.25)
1014: player_axe1 ();
1015: else if (r<0.5)
1016: player_axeb1 ();
1017: else if (r<0.75)
1018: player_axec1 ();
1019: else
1020: player_axed1 ();
1021: }
1022: else if (self.weapon == IT_SHOTGUN)
1023: {
1024: player_shot1 ();
1025: self.attack_finished = time + 0.5;
1026: W_FireShotgun ();
1027: }
1028: else if (self.weapon == IT_SUPER_SHOTGUN)
1029: {
1030: player_shot1 ();
1031: self.attack_finished = time + 0.7;
1032: W_FireSuperShotgun ();
1033: }
1034: else if (self.weapon == IT_NAILGUN)
1035: {
1036: player_nail1 ();
1037: }
1038: else if (self.weapon == IT_SUPER_NAILGUN)
1039: {
1040: player_nail1 ();
1041: }
1042: else if (self.weapon == IT_GRENADE_LAUNCHER)
1043: {
1044: player_rocket1();
1045: self.attack_finished = time + 0.6;
1046: W_FireGrenade();
1047: }
1048: else if (self.weapon == IT_ROCKET_LAUNCHER)
1049: {
1050: player_rocket1();
1051: self.attack_finished = time + 0.8;
1052: W_FireRocket();
1053: }
1054: else if (self.weapon == IT_LIGHTNING)
1055: {
1056: self.attack_finished = time + 0.1;
1057: sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
1058: player_light1();
1059: }
1060: };
1061:
1062: /*
1063: ============
1064: W_ChangeWeapon
1065:
1066: ============
1067: */
1068: void() W_ChangeWeapon =
1069: {
1070: local float it, am, fl;
1071:
1072: it = self.items;
1073: am = 0;
1074:
1075: if (self.impulse == 1)
1076: {
1077: fl = IT_AXE;
1078: }
1079: else if (self.impulse == 2)
1080: {
1081: fl = IT_SHOTGUN;
1082: if (self.ammo_shells < 1)
1083: am = 1;
1084: }
1085: else if (self.impulse == 3)
1086: {
1087: fl = IT_SUPER_SHOTGUN;
1088: if (self.ammo_shells < 2)
1089: am = 1;
1090: }
1091: else if (self.impulse == 4)
1092: {
1093: fl = IT_NAILGUN;
1094: if (self.ammo_nails < 1)
1095: am = 1;
1096: }
1097: else if (self.impulse == 5)
1098: {
1099: fl = IT_SUPER_NAILGUN;
1100: if (self.ammo_nails < 2)
1101: am = 1;
1102: }
1103: else if (self.impulse == 6)
1104: {
1105: fl = IT_GRENADE_LAUNCHER;
1106: if (self.ammo_rockets < 1)
1107: am = 1;
1108: }
1109: else if (self.impulse == 7)
1110: {
1111: fl = IT_ROCKET_LAUNCHER;
1112: if (self.ammo_rockets < 1)
1113: am = 1;
1114: }
1115: else if (self.impulse == 8)
1116: {
1117: fl = IT_LIGHTNING;
1118: if (self.ammo_cells < 1)
1119: am = 1;
1120: }
1121:
1122: self.impulse = 0;
1123:
1124: if (!(self.items & fl))
1125: { // don't have the weapon or the ammo
1126: sprint (self, PRINT_HIGH, "no weapon.\n");
1127: return;
1128: }
1129:
1130: if (am)
1131: { // don't have the ammo
1132: sprint (self, PRINT_HIGH, "not enough ammo.\n");
1133: return;
1134: }
1135:
1136: //
1137: // set weapon, set ammo
1138: //
1139: self.weapon = fl;
1140: W_SetCurrentAmmo ();
1141: };
1142:
1143: /*
1144: ============
1145: CheatCommand
1146: ============
1147: */
1148: void() CheatCommand =
1149: {
1150: // if (deathmatch || coop)
1151: return;
1152:
1153: self.ammo_rockets = 100;
1154: self.ammo_nails = 200;
1155: self.ammo_shells = 100;
1156: self.items = self.items |
1157: IT_AXE |
1158: IT_SHOTGUN |
1159: IT_SUPER_SHOTGUN |
1160: IT_NAILGUN |
1161: IT_SUPER_NAILGUN |
1162: IT_GRENADE_LAUNCHER |
1163: IT_ROCKET_LAUNCHER |
1164: IT_KEY1 | IT_KEY2;
1165:
1166: self.ammo_cells = 200;
1167: self.items = self.items | IT_LIGHTNING;
1168:
1169: self.weapon = IT_ROCKET_LAUNCHER;
1170: self.impulse = 0;
1171: W_SetCurrentAmmo ();
1172: };
1173:
1174: /*
1175: ============
1176: CycleWeaponCommand
1177:
1178: Go to the next weapon with ammo
1179: ============
1180: */
1181: void() CycleWeaponCommand =
1182: {
1183: local float it, am;
1184:
1185: it = self.items;
1186: self.impulse = 0;
1187:
1188: while (1)
1189: {
1190: am = 0;
1191:
1192: if (self.weapon == IT_LIGHTNING)
1193: {
1194: self.weapon = IT_AXE;
1195: }
1196: else if (self.weapon == IT_AXE)
1197: {
1198: self.weapon = IT_SHOTGUN;
1199: if (self.ammo_shells < 1)
1200: am = 1;
1201: }
1202: else if (self.weapon == IT_SHOTGUN)
1203: {
1204: self.weapon = IT_SUPER_SHOTGUN;
1205: if (self.ammo_shells < 2)
1206: am = 1;
1207: }
1208: else if (self.weapon == IT_SUPER_SHOTGUN)
1209: {
1210: self.weapon = IT_NAILGUN;
1211: if (self.ammo_nails < 1)
1212: am = 1;
1213: }
1214: else if (self.weapon == IT_NAILGUN)
1215: {
1216: self.weapon = IT_SUPER_NAILGUN;
1217: if (self.ammo_nails < 2)
1218: am = 1;
1219: }
1220: else if (self.weapon == IT_SUPER_NAILGUN)
1221: {
1222: self.weapon = IT_GRENADE_LAUNCHER;
1223: if (self.ammo_rockets < 1)
1224: am = 1;
1225: }
1226: else if (self.weapon == IT_GRENADE_LAUNCHER)
1227: {
1228: self.weapon = IT_ROCKET_LAUNCHER;
1229: if (self.ammo_rockets < 1)
1230: am = 1;
1231: }
1232: else if (self.weapon == IT_ROCKET_LAUNCHER)
1233: {
1234: self.weapon = IT_LIGHTNING;
1235: if (self.ammo_cells < 1)
1236: am = 1;
1237: }
1238:
1239: if ( (self.items & self.weapon) && am == 0)
1240: {
1241: W_SetCurrentAmmo ();
1242: return;
1243: }
1244: }
1245:
1246: };
1247:
1248:
1249: /*
1250: ============
1251: CycleWeaponReverseCommand
1252:
1253: Go to the prev weapon with ammo
1254: ============
1255: */
1256: void() CycleWeaponReverseCommand =
1257: {
1258: local float it, am;
1259:
1260: it = self.items;
1261: self.impulse = 0;
1262:
1263: while (1)
1264: {
1265: am = 0;
1266:
1267: if (self.weapon == IT_LIGHTNING)
1268: {
1269: self.weapon = IT_ROCKET_LAUNCHER;
1270: if (self.ammo_rockets < 1)
1271: am = 1;
1272: }
1273: else if (self.weapon == IT_ROCKET_LAUNCHER)
1274: {
1275: self.weapon = IT_GRENADE_LAUNCHER;
1276: if (self.ammo_rockets < 1)
1277: am = 1;
1278: }
1279: else if (self.weapon == IT_GRENADE_LAUNCHER)
1280: {
1281: self.weapon = IT_SUPER_NAILGUN;
1282: if (self.ammo_nails < 2)
1283: am = 1;
1284: }
1285: else if (self.weapon == IT_SUPER_NAILGUN)
1286: {
1287: self.weapon = IT_NAILGUN;
1288: if (self.ammo_nails < 1)
1289: am = 1;
1290: }
1291: else if (self.weapon == IT_NAILGUN)
1292: {
1293: self.weapon = IT_SUPER_SHOTGUN;
1294: if (self.ammo_shells < 2)
1295: am = 1;
1296: }
1297: else if (self.weapon == IT_SUPER_SHOTGUN)
1298: {
1299: self.weapon = IT_SHOTGUN;
1300: if (self.ammo_shells < 1)
1301: am = 1;
1302: }
1303: else if (self.weapon == IT_SHOTGUN)
1304: {
1305: self.weapon = IT_AXE;
1306: }
1307: else if (self.weapon == IT_AXE)
1308: {
1309: self.weapon = IT_LIGHTNING;
1310: if (self.ammo_cells < 1)
1311: am = 1;
1312: }
1313:
1314: if ( (it & self.weapon) && am == 0)
1315: {
1316: W_SetCurrentAmmo ();
1317: return;
1318: }
1319: }
1320:
1321: };
1322:
1323:
1324: /*
1325: ============
1326: ServerflagsCommand
1327:
1328: Just for development
1329: ============
1330: */
1331: void() ServerflagsCommand =
1332: {
1333: serverflags = serverflags * 2 + 1;
1334: };
1335:
1336:
1337: /*
1338: ============
1339: ImpulseCommands
1340:
1341: ============
1342: */
1343: void() ImpulseCommands =
1344: {
1345: if (self.impulse >= 1 && self.impulse <= 8)
1346: W_ChangeWeapon ();
1347:
1348: if (self.impulse == 9)
1349: CheatCommand ();
1350: if (self.impulse == 10)
1351: CycleWeaponCommand ();
1352: if (self.impulse == 11)
1353: ServerflagsCommand ();
1354: if (self.impulse == 12)
1355: CycleWeaponReverseCommand ();
1356:
1357: self.impulse = 0;
1358: };
1359:
1360: /*
1361: ============
1362: W_WeaponFrame
1363:
1364: Called every frame so impulse events can be handled as well as possible
1365: ============
1366: */
1367: void() W_WeaponFrame =
1368: {
1369: if (time < self.attack_finished)
1370: return;
1371:
1372: ImpulseCommands ();
1373:
1374: // check for attack
1375: if (self.button0)
1376: {
1377: SuperDamageSound ();
1378: W_Attack ();
1379: }
1380: };
1381:
1382: /*
1383: ========
1384: SuperDamageSound
1385:
1386: Plays sound if needed
1387: ========
1388: */
1389: void() SuperDamageSound =
1390: {
1391: if (self.super_damage_finished > time)
1392: {
1393: if (self.super_sound < time)
1394: {
1395: self.super_sound = time + 1;
1396: sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
1397: }
1398: }
1399: return;
1400: };
1401:
1402:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.