]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/w_common.c
major tweaks to ammo pickups, item respawn times, and all weapons are now parameteriz...
[divverent/nexuiz.git] / qcsrc / gamec / w_common.c
1
2 // increments sprite frame, loops when end is hit.. simple
3
4 float TE_SMOKE =77;
5 void (vector vec) WriteVec =
6 {
7                 WriteCoord (MSG_BROADCAST, vec_x);
8                 WriteCoord (MSG_BROADCAST, vec_y);
9                 WriteCoord (MSG_BROADCAST, vec_z);
10 }
11 void (vector org, vector dir, float counts) W_Smoke =
12 {
13                 WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
14                 WriteByte (MSG_BROADCAST, TE_SMOKE);
15                 WriteVec (org);
16                 WriteVec (dir);
17                 WriteByte (MSG_BROADCAST, counts);
18 }
19
20 // increments sprite frame, loops when end is hit.. simple
21 void animate_sprite (float startframe, float frame_count)
22 {
23         if ((self.frame - startframe) >= (frame_count - 1 ))
24                 self.frame = startframe;
25         else
26                 self.frame = self.frame + 1;
27 }
28
29 void W_UpdateAmmo (void)
30 {
31         /*
32         self.items = self.items - (self.items & (IT_NAILS | IT_SHELLS | IT_ROCKETS | IT_CELLS));
33
34         if (self.weapon == IT_LASER)
35                 self.currentammo = 1;
36         else if (self.weapon == IT_SHOTGUN)
37         {
38                 self.currentammo = self.ammo_shells;
39                 self.items = self.items | IT_SHELLS;
40         }
41         else if (self.weapon == IT_UZI)
42         {
43                 self.currentammo = self.ammo_nails;
44                 self.items = self.items | IT_NAILS;
45         }
46         else if (self.weapon == IT_GRENADE_LAUNCHER || self.weapon == IT_HAGAR || self.weapon == IT_ROCKET_LAUNCHER)
47         {
48                 self.currentammo = self.ammo_rockets;
49                 self.items = self.items | IT_ROCKETS;
50         }
51         else if (self.weapon == IT_ELECTRO || self.weapon == IT_NEX || self.weapon == IT_CRYLINK)
52         {
53                 self.currentammo = self.ammo_cells;
54                 self.items = self.items | IT_CELLS;
55         }
56         */
57 }
58
59 void W_UpdateWeapon (void)
60 {
61         /*
62         if (self.weapon == IT_LASER)
63                 self.weaponmodel = "models/weapons/w_laser.zym";
64         else if (self.weapon == IT_SHOTGUN)
65                 self.weaponmodel = "models/weapons/w_shotgun.zym";
66         else if (self.weapon == IT_UZI)
67                 self.weaponmodel = "models/weapons/w_uzi.zym";
68         else if (self.weapon == IT_GRENADE_LAUNCHER)
69                 self.weaponmodel = "models/weapons/w_gl.zym";
70         else if (self.weapon == IT_ELECTRO)
71                 self.weaponmodel = "models/weapons/w_electro.zym";
72         else if (self.weapon == IT_CRYLINK)
73                 self.weaponmodel = "models/weapons/w_crylink.zym";
74         else if (self.weapon == IT_NEX)
75                 self.weaponmodel = "models/weapons/w_nex.zym";
76         else if (self.weapon == IT_HAGAR)
77                 self.weaponmodel = "models/weapons/w_hagar.zym";
78         else if (self.weapon == IT_ROCKET_LAUNCHER)
79                 self.weaponmodel = "models/weapons/w_rl.zym";
80         else
81                 objerror ("Illegal weapon - please register your guns please!");
82         */
83 }
84
85 float W_GetBestWeapon (entity e)
86 {
87         /*
88         if ((e.items & IT_ROCKET_LAUNCHER) && e.ammo_rockets)
89                 return IT_ROCKET_LAUNCHER;
90         else if ((e.items & IT_NEX) && e.ammo_cells)
91                 return IT_NEX;
92         else if ((e.items & IT_HAGAR) && e.ammo_rockets)
93                 return IT_HAGAR;
94         else if ((e.items & IT_GRENADE_LAUNCHER) && e.ammo_rockets)
95                 return IT_GRENADE_LAUNCHER;
96         else if ((e.items & IT_ELECTRO) && e.ammo_cells)
97                 return IT_ELECTRO;
98         else if ((e.items & IT_CRYLINK) && e.ammo_cells)
99                 return IT_CRYLINK;
100         else if ((e.items & IT_UZI) && e.ammo_nails)
101                 return IT_UZI;
102         else if ((e.items & IT_SHOTGUN) && e.ammo_shells)
103                 return IT_SHOTGUN;
104         else
105
106                 */
107         return IT_LASER;
108 }
109
110 void W_GiveWeapon (entity e, float wep)
111 {
112         entity oldself;
113
114         if (!wep)
115                 return;
116
117         e.items = e.items | wep;
118
119         oldself = self;
120         self = e;
121
122         weapon_action(self.weapon, WR_UPDATECOUNTS);
123 /*
124         W_UpdateWeapon ();
125         W_UpdateAmmo ();
126 */
127         self = oldself;
128 }
129 /*
130 void W_SwitchWeapon (float wep)
131 {
132         float           nextwep;
133         var float       noammo = FALSE;
134
135         if (wep == 1)
136                 nextwep = IT_LASER;
137         else if (wep == 2)
138         {
139                 nextwep = IT_SHOTGUN;
140                 if (!self.ammo_shells)
141                         noammo = TRUE;
142         }
143         else if (wep == 3)
144         {
145                 nextwep = IT_UZI;
146                 if (!self.ammo_nails)
147                         noammo = TRUE;
148         }
149         else if (wep == 4)
150         {
151                 nextwep = IT_CRYLINK;
152                 if (!self.ammo_cells)
153                         noammo = TRUE;
154         }
155         else if (wep == 5)
156         {
157                 nextwep = IT_ELECTRO;
158                 if (!self.ammo_cells)
159                         noammo = TRUE;
160         }
161         else if (wep == 6)
162         {
163                 nextwep = IT_GRENADE_LAUNCHER;
164                 if (!self.ammo_rockets)
165                         noammo = TRUE;
166         }
167         else if (wep == 7)
168         {
169                 nextwep = IT_HAGAR;
170                 if (!self.ammo_rockets)
171                         noammo = TRUE;
172         }
173         else if (wep == 8)
174         {
175                 nextwep = IT_NEX;
176                 if (!self.ammo_cells)
177                         noammo = TRUE;
178         }
179         else if (wep == 9)
180         {
181                 nextwep = IT_ROCKET_LAUNCHER;
182                 if (!self.ammo_rockets)
183                         noammo = TRUE;
184         }
185
186
187         if (!(self.items & nextwep))
188         {
189                 sprint (self, "You don't own that weapon\n");
190                 return;
191         }
192         else if (noammo)
193         {
194                 sprint (self, "You don't have any ammo for that weapon\n");
195                 return;
196         }
197
198         self.weapon = nextwep;
199         W_UpdateWeapon ();
200         W_UpdateAmmo ();
201         self.attack_finished = time + 0.2;
202         if (self.viewzoom != 1)
203                 self.viewzoom = 1;
204 }
205
206 void W_NextWeapon (void)
207 {
208         float   noammo;
209
210         while (TRUE)
211         {
212                 noammo = FALSE;
213
214                 if (self.weapon == IT_ROCKET_LAUNCHER)
215                         self.weapon = IT_LASER;
216                 else if (self.weapon == IT_LASER)
217                 {
218                         self.weapon = IT_SHOTGUN;
219                         if (!self.ammo_shells)
220                                 noammo = TRUE;
221                 }
222                 else if (self.weapon == IT_SHOTGUN)
223                 {
224                         self.weapon = IT_UZI;
225                         if (!self.ammo_nails)
226                                 noammo = TRUE;
227                 }
228                 else if (self.weapon == IT_UZI)
229                 {
230                         self.weapon = IT_CRYLINK;
231                         if (!self.ammo_cells)
232                         noammo = TRUE;
233                 }
234                 else if (self.weapon == IT_CRYLINK)
235                 {
236                         self.weapon = IT_ELECTRO;
237                         if (!self.ammo_cells)
238                                 noammo = TRUE;
239                 }
240                 else if (self.weapon == IT_ELECTRO)
241                 {
242                         self.weapon = IT_GRENADE_LAUNCHER;
243                         if (!self.ammo_cells)
244                                 noammo = TRUE;
245                 }
246                 else if (self.weapon == IT_GRENADE_LAUNCHER)
247                 {
248                         self.weapon = IT_HAGAR;
249                         if (!self.ammo_rockets)
250                                 noammo = TRUE;
251                 }
252                 else if (self.weapon == IT_HAGAR)
253                 {
254                         self.weapon = IT_NEX;
255                         if (!self.ammo_rockets)
256                         noammo = TRUE;
257                 }
258                 else if (self.weapon == IT_NEX)
259                 {
260                         self.weapon = IT_ROCKET_LAUNCHER;
261                         if (!self.ammo_cells)
262                         noammo = TRUE;
263                 }
264
265                 if ((self.items & self.weapon) && !noammo)
266                 {
267                         W_UpdateWeapon ();
268                         W_UpdateAmmo ();
269                         return;
270                 }
271         }
272 }
273
274 void W_PreviousWeapon (void)
275 {
276         float   noammo;
277
278         while (TRUE)
279         {
280                 noammo = FALSE;
281
282                 if (self.weapon == IT_SHOTGUN)
283                         self.weapon = IT_LASER;
284                 else if (self.weapon == IT_UZI)
285                 {
286                         self.weapon = IT_SHOTGUN;
287                         if (!self.ammo_shells)
288                                 noammo = TRUE;
289                 }
290                 else if (self.weapon == IT_CRYLINK)
291                 {
292                         self.weapon = IT_UZI;
293                         if (!self.ammo_nails)
294                                 noammo = TRUE;
295                 }
296                 else if (self.weapon == IT_ELECTRO)
297                 {
298                         self.weapon = IT_CRYLINK;
299                         if (!self.ammo_cells)
300                                 noammo = TRUE;
301                 }
302                 else if (self.weapon == IT_GRENADE_LAUNCHER)
303                 {
304                         self.weapon = IT_ELECTRO;
305                         if (!self.ammo_cells)
306                                 noammo = TRUE;
307                 }
308                 else if (self.weapon == IT_HAGAR)
309                 {
310                         self.weapon = IT_GRENADE_LAUNCHER;
311                         if (!self.ammo_rockets)
312                                 noammo = TRUE;
313                 }
314                 else if (self.weapon == IT_NEX)
315                 {
316                         self.weapon = IT_HAGAR;
317                         if (!self.ammo_rockets)
318                                 noammo = TRUE;
319                 }
320                 else if (self.weapon == IT_ROCKET_LAUNCHER)
321                 {
322                         self.weapon = IT_NEX;
323                         if (!self.ammo_cells)
324                                 noammo = TRUE;
325                 }
326                 else if (self.weapon == IT_LASER)
327                 {
328                         self.weapon = IT_ROCKET_LAUNCHER;
329                         if (!self.ammo_rockets)
330                                 noammo = TRUE;
331                 }
332
333                 if ((self.items & self.weapon) && !noammo)
334                 {
335                         W_UpdateWeapon ();
336                         W_UpdateAmmo ();
337                         return;
338                 }
339         }
340 }
341 */
342 float W_CheckAmmo (void)
343 {
344         if (game & (GAME_INSTAGIB | GAME_ROCKET_ARENA))
345                 return TRUE;
346
347         W_UpdateAmmo ();
348         if (self.weapon == IT_LASER)
349                 return TRUE;
350         else if (self.currentammo)
351                 return TRUE;
352
353         self.weapon = W_GetBestWeapon (self);
354         W_UpdateWeapon ();
355
356         return FALSE;
357 }
358
359 /*
360 void FireRailgunBullet (vector src, float bdamage, vector dir, float spread, float deathtype)
361 {
362         vector  v, lastpos;
363         entity  saveself, last;
364         vector  org;
365         org = self.origin + self.view_ofs;
366         if (bdamage < 1)
367                 return;
368
369         last = self;
370         lastpos = src;
371
372         while (bdamage > 0)
373         {
374                 traceline_hitcorpse (self, org, org + v_forward * 4096 + v_right * crandom () * spread + v_up * crandom () * spread, FALSE, self);
375                 last = trace_ent;
376                 lastpos = trace_endpos;
377                 if (trace_fraction != 1.0)
378                 {
379                         if (pointcontents(trace_endpos - dir*4) == CONTENT_SKY)
380                                 return;
381
382                         if (trace_ent.takedamage || trace_ent.classname == "case")
383                         {
384                                 if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
385                                         te_blood (trace_endpos, dir * bdamage * 16, bdamage);
386                                 Damage (trace_ent, self, self, bdamage, deathtype, trace_endpos, dir * bdamage);
387                         }
388                 }
389                 if (last.solid == SOLID_BSP)
390                         bdamage = 0;
391         }
392 }
393 */
394
395 void FireRailgunBullet (vector start, vector end, float bdamage, float deathtype)
396 {
397         local vector hitloc, dir, force;
398         local entity ent;
399         //local entity explosion;
400
401         force = normalize(end - start) * (bdamage * 0.1);
402
403         // find how far the beam can go until it hits a wall
404         traceline (start, end, TRUE, self);
405         // go a little bit into the wall because we need to hit this wall later
406         end = trace_endpos + normalize(end - start);
407
408         // beam effect
409         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
410         WriteByte (MSG_BROADCAST, 76);
411         WriteCoord (MSG_BROADCAST, start_x);
412         WriteCoord (MSG_BROADCAST, start_y);
413         WriteCoord (MSG_BROADCAST, start_z);
414         WriteCoord (MSG_BROADCAST, end_x);
415         WriteCoord (MSG_BROADCAST, end_y);
416         WriteCoord (MSG_BROADCAST, end_z);
417         WriteCoord (MSG_BROADCAST, 0);
418         WriteCoord (MSG_BROADCAST, 0);
419         WriteCoord (MSG_BROADCAST, 0);
420
421         // flash and burn the wall
422         te_plasmaburn (trace_endpos);
423
424         /*
425         // flame effect at impact
426         dir = trace_plane_normal * 100;
427         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
428         WriteByte (MSG_BROADCAST, TE_FLAMEJET);
429         WriteCoord (MSG_BROADCAST, trace_endpos_x);
430         WriteCoord (MSG_BROADCAST, trace_endpos_y);
431         WriteCoord (MSG_BROADCAST, trace_endpos_z);
432         WriteCoord (MSG_BROADCAST, dir_x);
433         WriteCoord (MSG_BROADCAST, dir_y);
434         WriteCoord (MSG_BROADCAST, dir_z);
435         WriteByte (MSG_BROADCAST, 255);
436         */
437         // play a sound
438         PointSound (trace_endpos, "weapons/neximpact.wav", 1, ATTN_NORM);
439
440
441         // trace multiple times until we hit a wall, each obstacle will be made
442         // non-solid so we can hit the next, while doing this we spawn effects and
443         // note down which entities were hit so we can damage them later
444         while (1)
445         {
446                 traceline_hitcorpse (self, start, end, FALSE, self);
447
448                 // if it is world we can't hurt it so stop now
449                 if (trace_ent == world || trace_fraction == 1)
450                         break;
451
452                 // make the entity non-solid so we can hit the next one
453                 trace_ent.railgunhit = TRUE;
454                 trace_ent.railgunhitloc = trace_endpos;
455                 trace_ent.railgunhitsolidbackup = trace_ent.solid;
456
457                 // stop if this is a wall
458                 if (trace_ent.solid == SOLID_BSP)
459                         break;
460
461                 // make the entity non-solid
462                 trace_ent.solid = SOLID_NOT;
463         }
464
465         // find all the entities the railgun hit and restore their solid state
466         ent = findfloat(world, railgunhit, TRUE);
467         while (ent)
468         {
469                 // restore their solid type
470                 ent.solid = ent.railgunhitsolidbackup;
471                 ent = findfloat(ent, railgunhit, TRUE);
472         }
473
474         // spawn a temporary explosion entity for RadiusDamage calls
475         //explosion = spawn();
476
477         // find all the entities the railgun hit and hurt them
478         ent = findfloat(world, railgunhit, TRUE);
479         while (ent)
480         {
481                 // get the details we need to call the damage function
482                 hitloc = ent.railgunhitloc;
483                 ent.railgunhitloc = '0 0 0';
484                 ent.railgunhitsolidbackup = SOLID_NOT;
485                 ent.railgunhit = FALSE;
486
487                 // apply the damage
488                 if (ent.takedamage || ent.classname == "case")
489                         Damage (ent, self, self, bdamage, deathtype, hitloc, force);
490
491                 // create a small explosion to throw gibs around (if applicable)
492                 //setorigin (explosion, hitloc);
493                 //RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype);
494
495                 // advance to the next entity
496                 ent = findfloat(ent, railgunhit, TRUE);
497         }
498
499         // we're done with the explosion entity, remove it
500         //remove(explosion);
501 }
502
503
504 void fireBullet (vector start, vector dir, float spread, float damage, float dtype)
505 {
506         vector  end;
507         float r;
508
509         // use traceline_hitcorpse to make sure it can hit gibs and corpses too
510         end = start + (dir + randomvec() * spread) * 1048576;
511         traceline_hitcorpse (self, start, end, FALSE, self);
512
513         // FIXME - causes excessive 'tinking'. Hopefully remove "tink1.wav" from the ricochets with csqc
514         if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY))
515         {
516                 if (trace_ent.solid == SOLID_BSP)
517                 {
518                         pointcontents (self.origin);
519                         te_gunshot (trace_endpos);
520                         r = random ();
521                         if (r < 0.10)
522                                 sound (self, CHAN_IMPACT, "weapons/ric1.wav", 1, ATTN_NORM);
523                         else if (r < 0.20)
524                                 sound (self, CHAN_IMPACT, "weapons/ric2.wav", 1, ATTN_NORM);
525                         else if (r < 0.30)
526                                 sound (self, CHAN_IMPACT, "weapons/ric3.wav", 1, ATTN_NORM);
527                 }
528                 else if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
529                         sound (trace_ent, CHAN_IMPACT, "misc/enemyimpact.wav", 1, ATTN_NORM);
530                 Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * damage * 5);
531         }
532 }
533
534 /*
535 void W_Attack (void)
536 {
537         if (self.deadflag != DEAD_NO)
538         {
539                 if (self.death_time < time)
540                         PutClientInServer();
541
542                 return;
543         }
544
545         if (!W_CheckAmmo ())
546                 return;
547
548         makevectors (self.v_angle);
549         //if (self.weapon == IT_LASER)
550         //      W_Laser_Attack ();
551         //if (self.weapon == IT_SHOTGUN)
552                 //W_Shotgun_Attack ();
553         //else if (self.weapon == IT_UZI)
554                 //W_Uzi_Attack ();
555         if (self.weapon == IT_CRYLINK)
556                 W_Crylink_Attack ();
557         else if (self.weapon == IT_ELECTRO)
558                 {
559                 W_Electro_Attack (self.electrocount);
560                 self.electrocount = self.electrocount + 1;
561                 if (self.electrocount == 3)
562                         self.electrocount = 0;
563                 }
564         else if (self.weapon == IT_GRENADE_LAUNCHER)
565                 W_Grenade_Attack ();
566         else if (self.weapon == IT_HAGAR)
567                 W_Hagar_Attack ();
568         else if (self.weapon == IT_NEX)
569                 W_Nex_Attack ();
570         //else if (self.weapon == IT_ROCKET_LAUNCHER)
571         //      W_Rocket_Attack ();
572
573         W_UpdateAmmo ();
574 }
575
576 void W_SecondaryAttack (void)
577 {
578         if (self.deadflag != DEAD_NO)
579         {
580                 if (self.death_time < time)
581                         PutClientInServer();
582
583                 return;
584         }
585
586         if (!W_CheckAmmo ())
587                 return;
588
589         makevectors (self.v_angle);
590         //if (self.weapon == IT_LASER)
591                 //W_Laser_Attack2 ();
592         //if (self.weapon == IT_SHOTGUN)
593                 //W_Shotgun_Attack2 ();
594         //else if (self.weapon == IT_UZI)
595                 //W_Uzi_Attack2 ();
596         else if (self.weapon == IT_CRYLINK)
597                 W_Crylink_Attack2 ();
598         else if (self.weapon == IT_ELECTRO) {
599                 W_Electro_Attack2 (self.electrocount);
600                 self.electrocount = self.electrocount + 1;
601                 if (self.electrocount == 3)
602                         self.electrocount = 0;
603                 }
604         else if (self.weapon == IT_GRENADE_LAUNCHER)
605                 W_Grenade_Attack2 ();
606         else if (self.weapon == IT_HAGAR)
607                 W_Hagar_Attack2 ();
608         else if (self.weapon == IT_NEX)
609                 W_Nex_Attack2 ();
610         //else if (self.weapon == IT_ROCKET_LAUNCHER)
611                 //W_Rocket_Attack2 ();
612
613         W_UpdateAmmo ();
614 }
615
616 void W_ThirdAttack (void)
617 {
618         if (self.deadflag != DEAD_NO)
619         {
620                 if (self.death_time < time)
621                         PutClientInServer();
622
623                 return;
624         }
625
626         if (!W_CheckAmmo ())
627                 return;
628
629         makevectors (self.v_angle);
630         //if (self.weapon == IT_LASER)
631                 //W_Laser_Attack2 ();
632         //if (self.weapon == IT_SHOTGUN)
633                 //W_Shotgun_Attack2 ();
634         //else if (self.weapon == IT_UZI)
635                 //W_Uzi_Attack3 ();
636         else if (self.weapon == IT_CRYLINK)
637                 W_Crylink_Attack2 ();
638         else if (self.weapon == IT_ELECTRO) {
639                 W_Electro_Attack3 (self.electrocount);
640                 self.electrocount = self.electrocount + 1;
641                 if (self.electrocount == 3)
642                         self.electrocount = 0;
643                 }
644         else if (self.weapon == IT_GRENADE_LAUNCHER)
645                 W_Grenade_Attack3 ();
646         else if (self.weapon == IT_HAGAR)
647                 W_Hagar_Attack3 ();
648         else if (self.weapon == IT_NEX)
649                 W_Nex_Attack2 ();
650         //else if (self.weapon == IT_ROCKET_LAUNCHER)
651                 //W_Rocket_Attack3 ();
652
653         W_UpdateAmmo ();
654 }
655 */