1 /*
2 ===========================================================================
3 Copyright (C) 1999-2005 Id Software, Inc.
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22 //
23 // bg_misc.c -- both games misc functions, all completely stateless
24
25 #include "../qcommon/q_shared.h"
26 #include "bg_public.h"
27
28 /*QUAKED item_***** ( 0 0 0 ) (-16 -16 -16) (16 16 16) suspended
29 DO NOT USE THIS CLASS, IT JUST HOLDS GENERAL INFORMATION.
30 The suspended flag will allow items to hang in the air, otherwise they are dropped to the next surface.
31
32 If an item is the target of another entity, it will not spawn in until fired.
33
34 An item fires all of its targets when it is picked up. If the toucher can't carry it, the targets won't be fired.
35
36 "notfree" if set to 1, don't spawn in free for all games
37 "notteam" if set to 1, don't spawn in team games
38 "notsingle" if set to 1, don't spawn in single player games
39 "wait" override the default wait before respawning. -1 = never respawn automatically, which can be used with targeted spawning.
40 "random" random number of plus or minus seconds varied from the respawn time
41 "count" override quantity or duration on most items.
42 */
43
44 gitem_t bg_itemlist[] =
45 {
46 {
47 NULL,
48 NULL,
49 { NULL,
50 NULL,
51 NULL, NULL} ,
52 /* icon */ NULL,
53 /* pickup */ NULL,
54 0,
55 0,
56 0,
57 /* precache */ "",
58 /* sounds */ ""
59 }, // leave index 0 alone
60
61 //
62 // ARMOR
63 //
64
65 /*QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
66 */
67 {
68 "item_armor_shard",
69 "sound/misc/ar1_pkup.wav",
70 { "models/powerups/armor/shard.md3",
71 "models/powerups/armor/shard_sphere.md3",
72 NULL, NULL} ,
73 /* icon */ "icons/iconr_shard",
74 /* pickup */ "Armor Shard",
75 5,
76 IT_ARMOR,
77 0,
78 /* precache */ "",
79 /* sounds */ ""
80 },
81
82 /*QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
83 */
84 {
85 "item_armor_combat",
86 "sound/misc/ar2_pkup.wav",
87 { "models/powerups/armor/armor_yel.md3",
88 NULL, NULL, NULL},
89 /* icon */ "icons/iconr_yellow",
90 /* pickup */ "Armor",
91 50,
92 IT_ARMOR,
93 0,
94 /* precache */ "",
95 /* sounds */ ""
96 },
97
98 /*QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
99 */
100 {
101 "item_armor_body",
102 "sound/misc/ar2_pkup.wav",
103 { "models/powerups/armor/armor_red.md3",
104 NULL, NULL, NULL},
105 /* icon */ "icons/iconr_red",
106 /* pickup */ "Heavy Armor",
107 100,
108 IT_ARMOR,
109 0,
110 /* precache */ "",
111 /* sounds */ ""
112 },
113
114 //
115 // health
116 //
117 /*QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
118 */
119 {
120 "item_health_small",
121 "sound/items/s_health.wav",
122 { "models/powerups/health/small_cross.md3",
123 "models/powerups/health/small_sphere.md3",
124 NULL, NULL },
125 /* icon */ "icons/iconh_green",
126 /* pickup */ "5 Health",
127 5,
128 IT_HEALTH,
129 0,
130 /* precache */ "",
131 /* sounds */ ""
132 },
133
134 /*QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
135 */
136 {
137 "item_health",
138 "sound/items/n_health.wav",
139 { "models/powerups/health/medium_cross.md3",
140 "models/powerups/health/medium_sphere.md3",
141 NULL, NULL },
142 /* icon */ "icons/iconh_yellow",
143 /* pickup */ "25 Health",
144 25,
145 IT_HEALTH,
146 0,
147 /* precache */ "",
148 /* sounds */ ""
149 },
150
151 /*QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
152 */
153 {
154 "item_health_large",
155 "sound/items/l_health.wav",
156 { "models/powerups/health/large_cross.md3",
157 "models/powerups/health/large_sphere.md3",
158 NULL, NULL },
159 /* icon */ "icons/iconh_red",
160 /* pickup */ "50 Health",
161 50,
162 IT_HEALTH,
163 0,
164 /* precache */ "",
165 /* sounds */ ""
166 },
167
168 /*QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
169 */
170 {
171 "item_health_mega",
172 "sound/items/m_health.wav",
173 { "models/powerups/health/mega_cross.md3",
174 "models/powerups/health/mega_sphere.md3",
175 NULL, NULL },
176 /* icon */ "icons/iconh_mega",
177 /* pickup */ "Mega Health",
178 100,
179 IT_HEALTH,
180 0,
181 /* precache */ "",
182 /* sounds */ ""
183 },
184
185
186 //
187 // WEAPONS
188 //
189
190 /*QUAKED weapon_gauntlet (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
191 */
192 {
193 "weapon_gauntlet",
194 "sound/misc/w_pkup.wav",
195 { "models/weapons2/gauntlet/gauntlet.md3",
196 NULL, NULL, NULL},
197 /* icon */ "icons/iconw_gauntlet",
198 /* pickup */ "Gauntlet",
199 0,
200 IT_WEAPON,
201 WP_GAUNTLET,
202 /* precache */ "",
203 /* sounds */ ""
204 },
205
206 /*QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
207 */
208 {
209 "weapon_shotgun",
210 "sound/misc/w_pkup.wav",
211 { "models/weapons2/shotgun/shotgun.md3",
212 NULL, NULL, NULL},
213 /* icon */ "icons/iconw_shotgun",
214 /* pickup */ "Shotgun",
215 10,
216 IT_WEAPON,
217 WP_SHOTGUN,
218 /* precache */ "",
219 /* sounds */ ""
220 },
221
222 /*QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
223 */
224 {
225 "weapon_machinegun",
226 "sound/misc/w_pkup.wav",
227 { "models/weapons2/machinegun/machinegun.md3",
228 NULL, NULL, NULL},
229 /* icon */ "icons/iconw_machinegun",
230 /* pickup */ "Machinegun",
231 40,
232 IT_WEAPON,
233 WP_MACHINEGUN,
234 /* precache */ "",
235 /* sounds */ ""
236 },
237
238 /*QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
239 */
240 {
241 "weapon_grenadelauncher",
242 "sound/misc/w_pkup.wav",
243 { "models/weapons2/grenadel/grenadel.md3",
244 NULL, NULL, NULL},
245 /* icon */ "icons/iconw_grenade",
246 /* pickup */ "Grenade Launcher",
247 10,
248 IT_WEAPON,
249 WP_GRENADE_LAUNCHER,
250 /* precache */ "",
251 /* sounds */ "sound/weapons/grenade/hgrenb1a.wav sound/weapons/grenade/hgrenb2a.wav"
252 },
253
254 /*QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
255 */
256 {
257 "weapon_rocketlauncher",
258 "sound/misc/w_pkup.wav",
259 { "models/weapons2/rocketl/rocketl.md3",
260 NULL, NULL, NULL},
261 /* icon */ "icons/iconw_rocket",
262 /* pickup */ "Rocket Launcher",
263 10,
264 IT_WEAPON,
265 WP_ROCKET_LAUNCHER,
266 /* precache */ "",
267 /* sounds */ ""
268 },
269
270 /*QUAKED weapon_lightning (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
271 */
272 {
273 "weapon_lightning",
274 "sound/misc/w_pkup.wav",
275 { "models/weapons2/lightning/lightning.md3",
276 NULL, NULL, NULL},
277 /* icon */ "icons/iconw_lightning",
278 /* pickup */ "Lightning Gun",
279 100,
280 IT_WEAPON,
281 WP_LIGHTNING,
282 /* precache */ "",
283 /* sounds */ ""
284 },
285
286 /*QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
287 */
288 {
289 "weapon_railgun",
290 "sound/misc/w_pkup.wav",
291 { "models/weapons2/railgun/railgun.md3",
292 NULL, NULL, NULL},
293 /* icon */ "icons/iconw_railgun",
294 /* pickup */ "Railgun",
295 10,
296 IT_WEAPON,
297 WP_RAILGUN,
298 /* precache */ "",
299 /* sounds */ ""
300 },
301
302 /*QUAKED weapon_plasmagun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
303 */
304 {
305 "weapon_plasmagun",
306 "sound/misc/w_pkup.wav",
307 { "models/weapons2/plasma/plasma.md3",
308 NULL, NULL, NULL},
309 /* icon */ "icons/iconw_plasma",
310 /* pickup */ "Plasma Gun",
311 50,
312 IT_WEAPON,
313 WP_PLASMAGUN,
314 /* precache */ "",
315 /* sounds */ ""
316 },
317
318 /*QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
319 */
320 {
321 "weapon_bfg",
322 "sound/misc/w_pkup.wav",
323 { "models/weapons2/bfg/bfg.md3",
324 NULL, NULL, NULL},
325 /* icon */ "icons/iconw_bfg",
326 /* pickup */ "BFG10K",
327 20,
328 IT_WEAPON,
329 WP_BFG,
330 /* precache */ "",
331 /* sounds */ ""
332 },
333
334 /*QUAKED weapon_grapplinghook (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
335 */
336 {
337 "weapon_grapplinghook",
338 "sound/misc/w_pkup.wav",
339 { "models/weapons2/grapple/grapple.md3",
340 NULL, NULL, NULL},
341 /* icon */ "icons/iconw_grapple",
342 /* pickup */ "Grappling Hook",
343 0,
344 IT_WEAPON,
345 WP_GRAPPLING_HOOK,
346 /* precache */ "",
347 /* sounds */ ""
348 },
349
350 //
351 // AMMO ITEMS
352 //
353
354 /*QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
355 */
356 {
357 "ammo_shells",
358 "sound/misc/am_pkup.wav",
359 { "models/powerups/ammo/shotgunam.md3",
360 NULL, NULL, NULL},
361 /* icon */ "icons/icona_shotgun",
362 /* pickup */ "Shells",
363 10,
364 IT_AMMO,
365 WP_SHOTGUN,
366 /* precache */ "",
367 /* sounds */ ""
368 },
369
370 /*QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
371 */
372 {
373 "ammo_bullets",
374 "sound/misc/am_pkup.wav",
375 { "models/powerups/ammo/machinegunam.md3",
376 NULL, NULL, NULL},
377 /* icon */ "icons/icona_machinegun",
378 /* pickup */ "Bullets",
379 50,
380 IT_AMMO,
381 WP_MACHINEGUN,
382 /* precache */ "",
383 /* sounds */ ""
384 },
385
386 /*QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
387 */
388 {
389 "ammo_grenades",
390 "sound/misc/am_pkup.wav",
391 { "models/powerups/ammo/grenadeam.md3",
392 NULL, NULL, NULL},
393 /* icon */ "icons/icona_grenade",
394 /* pickup */ "Grenades",
395 5,
396 IT_AMMO,
397 WP_GRENADE_LAUNCHER,
398 /* precache */ "",
399 /* sounds */ ""
400 },
401
402 /*QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
403 */
404 {
405 "ammo_cells",
406 "sound/misc/am_pkup.wav",
407 { "models/powerups/ammo/plasmaam.md3",
408 NULL, NULL, NULL},
409 /* icon */ "icons/icona_plasma",
410 /* pickup */ "Cells",
411 30,
412 IT_AMMO,
413 WP_PLASMAGUN,
414 /* precache */ "",
415 /* sounds */ ""
416 },
417
418 /*QUAKED ammo_lightning (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
419 */
420 {
421 "ammo_lightning",
422 "sound/misc/am_pkup.wav",
423 { "models/powerups/ammo/lightningam.md3",
424 NULL, NULL, NULL},
425 /* icon */ "icons/icona_lightning",
426 /* pickup */ "Lightning",
427 60,
428 IT_AMMO,
429 WP_LIGHTNING,
430 /* precache */ "",
431 /* sounds */ ""
432 },
433
434 /*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
435 */
436 {
437 "ammo_rockets",
438 "sound/misc/am_pkup.wav",
439 { "models/powerups/ammo/rocketam.md3",
440 NULL, NULL, NULL},
441 /* icon */ "icons/icona_rocket",
442 /* pickup */ "Rockets",
443 5,
444 IT_AMMO,
445 WP_ROCKET_LAUNCHER,
446 /* precache */ "",
447 /* sounds */ ""
448 },
449
450 /*QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
451 */
452 {
453 "ammo_slugs",
454 "sound/misc/am_pkup.wav",
455 { "models/powerups/ammo/railgunam.md3",
456 NULL, NULL, NULL},
457 /* icon */ "icons/icona_railgun",
458 /* pickup */ "Slugs",
459 10,
460 IT_AMMO,
461 WP_RAILGUN,
462 /* precache */ "",
463 /* sounds */ ""
464 },
465
466 /*QUAKED ammo_bfg (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
467 */
468 {
469 "ammo_bfg",
470 "sound/misc/am_pkup.wav",
471 { "models/powerups/ammo/bfgam.md3",
472 NULL, NULL, NULL},
473 /* icon */ "icons/icona_bfg",
474 /* pickup */ "Bfg Ammo",
475 15,
476 IT_AMMO,
477 WP_BFG,
478 /* precache */ "",
479 /* sounds */ ""
480 },
481
482 //
483 // HOLDABLE ITEMS
484 //
485 /*QUAKED holdable_teleporter (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
486 */
487 {
488 "holdable_teleporter",
489 "sound/items/holdable.wav",
490 { "models/powerups/holdable/teleporter.md3",
491 NULL, NULL, NULL},
492 /* icon */ "icons/teleporter",
493 /* pickup */ "Personal Teleporter",
494 60,
495 IT_HOLDABLE,
496 HI_TELEPORTER,
497 /* precache */ "",
498 /* sounds */ ""
499 },
500 /*QUAKED holdable_medkit (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
501 */
502 {
503 "holdable_medkit",
504 "sound/items/holdable.wav",
505 {
506 "models/powerups/holdable/medkit.md3",
507 "models/powerups/holdable/medkit_sphere.md3",
508 NULL, NULL},
509 /* icon */ "icons/medkit",
510 /* pickup */ "Medkit",
511 60,
512 IT_HOLDABLE,
513 HI_MEDKIT,
514 /* precache */ "",
515 /* sounds */ "sound/items/use_medkit.wav"
516 },
517
518 //
519 // POWERUP ITEMS
520 //
521 /*QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
522 */
523 {
524 "item_quad",
525 "sound/items/quaddamage.wav",
526 { "models/powerups/instant/quad.md3",
527 "models/powerups/instant/quad_ring.md3",
528 NULL, NULL },
529 /* icon */ "icons/quad",
530 /* pickup */ "Quad Damage",
531 30,
532 IT_POWERUP,
533 PW_QUAD,
534 /* precache */ "",
535 /* sounds */ "sound/items/damage2.wav sound/items/damage3.wav"
536 },
537
538 /*QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
539 */
540 {
541 "item_enviro",
542 "sound/items/protect.wav",
543 { "models/powerups/instant/enviro.md3",
544 "models/powerups/instant/enviro_ring.md3",
545 NULL, NULL },
546 /* icon */ "icons/envirosuit",
547 /* pickup */ "Battle Suit",
548 30,
549 IT_POWERUP,
550 PW_BATTLESUIT,
551 /* precache */ "",
552 /* sounds */ "sound/items/airout.wav sound/items/protect3.wav"
553 },
554
555 /*QUAKED item_haste (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
556 */
557 {
558 "item_haste",
559 "sound/items/haste.wav",
560 { "models/powerups/instant/haste.md3",
561 "models/powerups/instant/haste_ring.md3",
562 NULL, NULL },
563 /* icon */ "icons/haste",
564 /* pickup */ "Speed",
565 30,
566 IT_POWERUP,
567 PW_HASTE,
568 /* precache */ "",
569 /* sounds */ ""
570 },
571
572 /*QUAKED item_invis (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
573 */
574 {
575 "item_invis",
576 "sound/items/invisibility.wav",
577 { "models/powerups/instant/invis.md3",
578 "models/powerups/instant/invis_ring.md3",
579 NULL, NULL },
580 /* icon */ "icons/invis",
581 /* pickup */ "Invisibility",
582 30,
583 IT_POWERUP,
584 PW_INVIS,
585 /* precache */ "",
586 /* sounds */ ""
587 },
588
589 /*QUAKED item_regen (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
590 */
591 {
592 "item_regen",
593 "sound/items/regeneration.wav",
594 { "models/powerups/instant/regen.md3",
595 "models/powerups/instant/regen_ring.md3",
596 NULL, NULL },
597 /* icon */ "icons/regen",
598 /* pickup */ "Regeneration",
599 30,
600 IT_POWERUP,
601 PW_REGEN,
602 /* precache */ "",
603 /* sounds */ "sound/items/regen.wav"
604 },
605
606 /*QUAKED item_flight (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
607 */
608 {
609 "item_flight",
610 "sound/items/flight.wav",
611 { "models/powerups/instant/flight.md3",
612 "models/powerups/instant/flight_ring.md3",
613 NULL, NULL },
614 /* icon */ "icons/flight",
615 /* pickup */ "Flight",
616 60,
617 IT_POWERUP,
618 PW_FLIGHT,
619 /* precache */ "",
620 /* sounds */ "sound/items/flight.wav"
621 },
622
623 /*QUAKED team_CTF_redflag (1 0 0) (-16 -16 -16) (16 16 16)
624 Only in CTF games
625 */
626 {
627 "team_CTF_redflag",
628 NULL,
629 { "models/flags/r_flag.md3",
630 NULL, NULL, NULL },
631 /* icon */ "icons/iconf_red1",
632 /* pickup */ "Red Flag",
633 0,
634 IT_TEAM,
635 PW_REDFLAG,
636 /* precache */ "",
637 /* sounds */ ""
638 },
639
640 /*QUAKED team_CTF_blueflag (0 0 1) (-16 -16 -16) (16 16 16)
641 Only in CTF games
642 */
643 {
644 "team_CTF_blueflag",
645 NULL,
646 { "models/flags/b_flag.md3",
647 NULL, NULL, NULL },
648 /* icon */ "icons/iconf_blu1",
649 /* pickup */ "Blue Flag",
650 0,
651 IT_TEAM,
652 PW_BLUEFLAG,
653 /* precache */ "",
654 /* sounds */ ""
655 },
656
657 #ifdef MISSIONPACK
658 /*QUAKED holdable_kamikaze (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
659 */
660 {
661 "holdable_kamikaze",
662 "sound/items/holdable.wav",
663 { "models/powerups/kamikazi.md3",
664 NULL, NULL, NULL},
665 /* icon */ "icons/kamikaze",
666 /* pickup */ "Kamikaze",
667 60,
668 IT_HOLDABLE,
669 HI_KAMIKAZE,
670 /* precache */ "",
671 /* sounds */ "sound/items/kamikazerespawn.wav"
672 },
673
674 /*QUAKED holdable_portal (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
675 */
676 {
677 "holdable_portal",
678 "sound/items/holdable.wav",
679 { "models/powerups/holdable/porter.md3",
680 NULL, NULL, NULL},
681 /* icon */ "icons/portal",
682 /* pickup */ "Portal",
683 60,
684 IT_HOLDABLE,
685 HI_PORTAL,
686 /* precache */ "",
687 /* sounds */ ""
688 },
689
690 /*QUAKED holdable_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
691 */
692 {
693 "holdable_invulnerability",
694 "sound/items/holdable.wav",
695 { "models/powerups/holdable/invulnerability.md3",
696 NULL, NULL, NULL},
697 /* icon */ "icons/invulnerability",
698 /* pickup */ "Invulnerability",
699 60,
700 IT_HOLDABLE,
701 HI_INVULNERABILITY,
702 /* precache */ "",
703 /* sounds */ ""
704 },
705
706 /*QUAKED ammo_nails (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
707 */
708 {
709 "ammo_nails",
710 "sound/misc/am_pkup.wav",
711 { "models/powerups/ammo/nailgunam.md3",
712 NULL, NULL, NULL},
713 /* icon */ "icons/icona_nailgun",
714 /* pickup */ "Nails",
715 20,
716 IT_AMMO,
717 WP_NAILGUN,
718 /* precache */ "",
719 /* sounds */ ""
720 },
721
722 /*QUAKED ammo_mines (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
723 */
724 {
725 "ammo_mines",
726 "sound/misc/am_pkup.wav",
727 { "models/powerups/ammo/proxmineam.md3",
728 NULL, NULL, NULL},
729 /* icon */ "icons/icona_proxlauncher",
730 /* pickup */ "Proximity Mines",
731 10,
732 IT_AMMO,
733 WP_PROX_LAUNCHER,
734 /* precache */ "",
735 /* sounds */ ""
736 },
737
738 /*QUAKED ammo_belt (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
739 */
740 {
741 "ammo_belt",
742 "sound/misc/am_pkup.wav",
743 { "models/powerups/ammo/chaingunam.md3",
744 NULL, NULL, NULL},
745 /* icon */ "icons/icona_chaingun",
746 /* pickup */ "Chaingun Belt",
747 100,
748 IT_AMMO,
749 WP_CHAINGUN,
750 /* precache */ "",
751 /* sounds */ ""
752 },
753
754 //
755 // PERSISTANT POWERUP ITEMS
756 //
757 /*QUAKED item_scout (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
758 */
759 {
760 "item_scout",
761 "sound/items/scout.wav",
762 { "models/powerups/scout.md3",
763 NULL, NULL, NULL },
764 /* icon */ "icons/scout",
765 /* pickup */ "Scout",
766 30,
767 IT_PERSISTANT_POWERUP,
768 PW_SCOUT,
769 /* precache */ "",
770 /* sounds */ ""
771 },
772
773 /*QUAKED item_guard (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
774 */
775 {
776 "item_guard",
777 "sound/items/guard.wav",
778 { "models/powerups/guard.md3",
779 NULL, NULL, NULL },
780 /* icon */ "icons/guard",
781 /* pickup */ "Guard",
782 30,
783 IT_PERSISTANT_POWERUP,
784 PW_GUARD,
785 /* precache */ "",
786 /* sounds */ ""
787 },
788
789 /*QUAKED item_doubler (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
790 */
791 {
792 "item_doubler",
793 "sound/items/doubler.wav",
794 { "models/powerups/doubler.md3",
795 NULL, NULL, NULL },
796 /* icon */ "icons/doubler",
797 /* pickup */ "Doubler",
798 30,
799 IT_PERSISTANT_POWERUP,
800 PW_DOUBLER,
801 /* precache */ "",
802 /* sounds */ ""
803 },
804
805 /*QUAKED item_doubler (.3 .3 1) (-16 -16 -16) (16 16 16) suspended redTeam blueTeam
806 */
807 {
808 "item_ammoregen",
809 "sound/items/ammoregen.wav",
810 { "models/powerups/ammo.md3",
811 NULL, NULL, NULL },
812 /* icon */ "icons/ammo_regen",
813 /* pickup */ "Ammo Regen",
814 30,
815 IT_PERSISTANT_POWERUP,
816 PW_AMMOREGEN,
817 /* precache */ "",
818 /* sounds */ ""
819 },
820
821 /*QUAKED team_CTF_neutralflag (0 0 1) (-16 -16 -16) (16 16 16)
822 Only in One Flag CTF games
823 */
824 {
825 "team_CTF_neutralflag",
826 NULL,
827 { "models/flags/n_flag.md3",
828 NULL, NULL, NULL },
829 /* icon */ "icons/iconf_neutral1",
830 /* pickup */ "Neutral Flag",
831 0,
832 IT_TEAM,
833 PW_NEUTRALFLAG,
834 /* precache */ "",
835 /* sounds */ ""
836 },
837
838 {
839 "item_redcube",
840 "sound/misc/am_pkup.wav",
841 { "models/powerups/orb/r_orb.md3",
842 NULL, NULL, NULL },
843 /* icon */ "icons/iconh_rorb",
844 /* pickup */ "Red Cube",
845 0,
846 IT_TEAM,
847 0,
848 /* precache */ "",
849 /* sounds */ ""
850 },
851
852 {
853 "item_bluecube",
854 "sound/misc/am_pkup.wav",
855 { "models/powerups/orb/b_orb.md3",
856 NULL, NULL, NULL },
857 /* icon */ "icons/iconh_borb",
858 /* pickup */ "Blue Cube",
859 0,
860 IT_TEAM,
861 0,
862 /* precache */ "",
863 /* sounds */ ""
864 },
865 /*QUAKED weapon_nailgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
866 */
867 {
868 "weapon_nailgun",
869 "sound/misc/w_pkup.wav",
870 { "models/weapons/nailgun/nailgun.md3",
871 NULL, NULL, NULL},
872 /* icon */ "icons/iconw_nailgun",
873 /* pickup */ "Nailgun",
874 10,
875 IT_WEAPON,
876 WP_NAILGUN,
877 /* precache */ "",
878 /* sounds */ ""
879 },
880
881 /*QUAKED weapon_prox_launcher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
882 */
883 {
884 "weapon_prox_launcher",
885 "sound/misc/w_pkup.wav",
886 { "models/weapons/proxmine/proxmine.md3",
887 NULL, NULL, NULL},
888 /* icon */ "icons/iconw_proxlauncher",
889 /* pickup */ "Prox Launcher",
890 5,
891 IT_WEAPON,
892 WP_PROX_LAUNCHER,
893 /* precache */ "",
894 /* sounds */ "sound/weapons/proxmine/wstbtick.wav "
895 "sound/weapons/proxmine/wstbactv.wav "
896 "sound/weapons/proxmine/wstbimpl.wav "
897 "sound/weapons/proxmine/wstbimpm.wav "
898 "sound/weapons/proxmine/wstbimpd.wav "
899 "sound/weapons/proxmine/wstbactv.wav"
900 },
901
902 /*QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
903 */
904 {
905 "weapon_chaingun",
906 "sound/misc/w_pkup.wav",
907 { "models/weapons/vulcan/vulcan.md3",
908 NULL, NULL, NULL},
909 /* icon */ "icons/iconw_chaingun",
910 /* pickup */ "Chaingun",
911 80,
912 IT_WEAPON,
913 WP_CHAINGUN,
914 /* precache */ "",
915 /* sounds */ "sound/weapons/vulcan/wvulwind.wav"
916 },
917 #endif
918
919 // end of list marker
920 {NULL}
921 };
922
923 int bg_numItems = sizeof(bg_itemlist) / sizeof(bg_itemlist[0]) - 1;
924
925
926 /*
927 ==============
928 BG_FindItemForPowerup
929 ==============
930 */
BG_FindItemForPowerup(powerup_t pw)931 gitem_t *BG_FindItemForPowerup( powerup_t pw ) {
932 int i;
933
934 for ( i = 0 ; i < bg_numItems ; i++ ) {
935 if ( (bg_itemlist[i].giType == IT_POWERUP ||
936 bg_itemlist[i].giType == IT_TEAM ||
937 bg_itemlist[i].giType == IT_PERSISTANT_POWERUP) &&
938 bg_itemlist[i].giTag == pw ) {
939 return &bg_itemlist[i];
940 }
941 }
942
943 return NULL;
944 }
945
946
947 /*
948 ==============
949 BG_FindItemForHoldable
950 ==============
951 */
BG_FindItemForHoldable(holdable_t pw)952 gitem_t *BG_FindItemForHoldable( holdable_t pw ) {
953 int i;
954
955 for ( i = 0 ; i < bg_numItems ; i++ ) {
956 if ( bg_itemlist[i].giType == IT_HOLDABLE && bg_itemlist[i].giTag == pw ) {
957 return &bg_itemlist[i];
958 }
959 }
960
961 Com_Error( ERR_DROP, "HoldableItem not found" );
962
963 return NULL;
964 }
965
966
967 /*
968 ===============
969 BG_FindItemForWeapon
970
971 ===============
972 */
BG_FindItemForWeapon(weapon_t weapon)973 gitem_t *BG_FindItemForWeapon( weapon_t weapon ) {
974 gitem_t *it;
975
976 for ( it = bg_itemlist + 1 ; it->classname ; it++) {
977 if ( it->giType == IT_WEAPON && it->giTag == weapon ) {
978 return it;
979 }
980 }
981
982 Com_Error( ERR_DROP, "Couldn't find item for weapon %i", weapon);
983 return NULL;
984 }
985
986 /*
987 ===============
988 BG_FindItem
989
990 ===============
991 */
BG_FindItem(const char * pickupName)992 gitem_t *BG_FindItem( const char *pickupName ) {
993 gitem_t *it;
994
995 for ( it = bg_itemlist + 1 ; it->classname ; it++ ) {
996 if ( !Q_stricmp( it->pickup_name, pickupName ) )
997 return it;
998 }
999
1000 return NULL;
1001 }
1002
1003 /*
1004 ============
1005 BG_PlayerTouchesItem
1006
1007 Items can be picked up without actually touching their physical bounds to make
1008 grabbing them easier
1009 ============
1010 */
BG_PlayerTouchesItem(playerState_t * ps,entityState_t * item,int atTime)1011 qboolean BG_PlayerTouchesItem( playerState_t *ps, entityState_t *item, int atTime ) {
1012 vec3_t origin;
1013
1014 BG_EvaluateTrajectory( &item->pos, atTime, origin );
1015
1016 // we are ignoring ducked differences here
1017 if ( ps->origin[0] - origin[0] > 44
1018 || ps->origin[0] - origin[0] < -50
1019 || ps->origin[1] - origin[1] > 36
1020 || ps->origin[1] - origin[1] < -36
1021 || ps->origin[2] - origin[2] > 36
1022 || ps->origin[2] - origin[2] < -36 ) {
1023 return qfalse;
1024 }
1025
1026 return qtrue;
1027 }
1028
1029
1030
1031 /*
1032 ================
1033 BG_CanItemBeGrabbed
1034
1035 Returns false if the item should not be picked up.
1036 This needs to be the same for client side prediction and server use.
1037 ================
1038 */
BG_CanItemBeGrabbed(int gametype,const entityState_t * ent,const playerState_t * ps)1039 qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const playerState_t *ps ) {
1040 gitem_t *item;
1041 #ifdef MISSIONPACK
1042 int upperBound;
1043 #endif
1044
1045 if ( ent->modelindex < 1 || ent->modelindex >= bg_numItems ) {
1046 Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: index out of range" );
1047 }
1048
1049 item = &bg_itemlist[ent->modelindex];
1050
1051 switch( item->giType ) {
1052 case IT_WEAPON:
1053 return qtrue; // weapons are always picked up
1054
1055 case IT_AMMO:
1056 if ( ps->ammo[ item->giTag ] >= 200 ) {
1057 return qfalse; // can't hold any more
1058 }
1059 return qtrue;
1060
1061 case IT_ARMOR:
1062 #ifdef MISSIONPACK
1063 if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_SCOUT ) {
1064 return qfalse;
1065 }
1066
1067 // we also clamp armor to the maxhealth for handicapping
1068 if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
1069 upperBound = ps->stats[STAT_MAX_HEALTH];
1070 }
1071 else {
1072 upperBound = ps->stats[STAT_MAX_HEALTH] * 2;
1073 }
1074
1075 if ( ps->stats[STAT_ARMOR] >= upperBound ) {
1076 return qfalse;
1077 }
1078 #else
1079 if ( ps->stats[STAT_ARMOR] >= ps->stats[STAT_MAX_HEALTH] * 2 ) {
1080 return qfalse;
1081 }
1082 #endif
1083 return qtrue;
1084
1085 case IT_HEALTH:
1086 // small and mega healths will go over the max, otherwise
1087 // don't pick up if already at max
1088 #ifdef MISSIONPACK
1089 if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
1090 upperBound = ps->stats[STAT_MAX_HEALTH];
1091 }
1092 else
1093 #endif
1094 if ( item->quantity == 5 || item->quantity == 100 ) {
1095 if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] * 2 ) {
1096 return qfalse;
1097 }
1098 return qtrue;
1099 }
1100
1101 if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] ) {
1102 return qfalse;
1103 }
1104 return qtrue;
1105
1106 case IT_POWERUP:
1107 return qtrue; // powerups are always picked up
1108
1109 #ifdef MISSIONPACK
1110 case IT_PERSISTANT_POWERUP:
1111 // can only hold one item at a time
1112 if ( ps->stats[STAT_PERSISTANT_POWERUP] ) {
1113 return qfalse;
1114 }
1115
1116 // check team only
1117 if( ( ent->generic1 & 2 ) && ( ps->persistant[PERS_TEAM] != TEAM_RED ) ) {
1118 return qfalse;
1119 }
1120 if( ( ent->generic1 & 4 ) && ( ps->persistant[PERS_TEAM] != TEAM_BLUE ) ) {
1121 return qfalse;
1122 }
1123
1124 return qtrue;
1125 #endif
1126
1127 case IT_TEAM: // team items, such as flags
1128 #ifdef MISSIONPACK
1129 if( gametype == GT_1FCTF ) {
1130 // neutral flag can always be picked up
1131 if( item->giTag == PW_NEUTRALFLAG ) {
1132 return qtrue;
1133 }
1134 if (ps->persistant[PERS_TEAM] == TEAM_RED) {
1135 if (item->giTag == PW_BLUEFLAG && ps->powerups[PW_NEUTRALFLAG] ) {
1136 return qtrue;
1137 }
1138 } else if (ps->persistant[PERS_TEAM] == TEAM_BLUE) {
1139 if (item->giTag == PW_REDFLAG && ps->powerups[PW_NEUTRALFLAG] ) {
1140 return qtrue;
1141 }
1142 }
1143 }
1144 #endif
1145 if( gametype == GT_CTF ) {
1146 // ent->modelindex2 is non-zero on items if they are dropped
1147 // we need to know this because we can pick up our dropped flag (and return it)
1148 // but we can't pick up our flag at base
1149 if (ps->persistant[PERS_TEAM] == TEAM_RED) {
1150 if (item->giTag == PW_BLUEFLAG ||
1151 (item->giTag == PW_REDFLAG && ent->modelindex2) ||
1152 (item->giTag == PW_REDFLAG && ps->powerups[PW_BLUEFLAG]) )
1153 return qtrue;
1154 } else if (ps->persistant[PERS_TEAM] == TEAM_BLUE) {
1155 if (item->giTag == PW_REDFLAG ||
1156 (item->giTag == PW_BLUEFLAG && ent->modelindex2) ||
1157 (item->giTag == PW_BLUEFLAG && ps->powerups[PW_REDFLAG]) )
1158 return qtrue;
1159 }
1160 }
1161
1162 #ifdef MISSIONPACK
1163 if( gametype == GT_HARVESTER ) {
1164 return qtrue;
1165 }
1166 #endif
1167 return qfalse;
1168
1169 case IT_HOLDABLE:
1170 // can only hold one item at a time
1171 if ( ps->stats[STAT_HOLDABLE_ITEM] ) {
1172 return qfalse;
1173 }
1174 return qtrue;
1175
1176 case IT_BAD:
1177 Com_Error( ERR_DROP, "BG_CanItemBeGrabbed: IT_BAD" );
1178 default:
1179 #ifndef Q3_VM
1180 #ifndef NDEBUG
1181 Com_Printf("BG_CanItemBeGrabbed: unknown enum %d\n", item->giType );
1182 #endif
1183 #endif
1184 break;
1185 }
1186
1187 return qfalse;
1188 }
1189
1190 //======================================================================
1191
1192 /*
1193 ================
1194 BG_EvaluateTrajectory
1195
1196 ================
1197 */
BG_EvaluateTrajectory(const trajectory_t * tr,int atTime,vec3_t result)1198 void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) {
1199 float deltaTime;
1200 float phase;
1201
1202 switch( tr->trType ) {
1203 case TR_STATIONARY:
1204 case TR_INTERPOLATE:
1205 VectorCopy( tr->trBase, result );
1206 break;
1207 case TR_LINEAR:
1208 deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
1209 VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
1210 break;
1211 case TR_SINE:
1212 deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
1213 phase = sin( deltaTime * M_PI * 2 );
1214 VectorMA( tr->trBase, phase, tr->trDelta, result );
1215 break;
1216 case TR_LINEAR_STOP:
1217 if ( atTime > tr->trTime + tr->trDuration ) {
1218 atTime = tr->trTime + tr->trDuration;
1219 }
1220 deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
1221 if ( deltaTime < 0 ) {
1222 deltaTime = 0;
1223 }
1224 VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
1225 break;
1226 case TR_GRAVITY:
1227 deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
1228 VectorMA( tr->trBase, deltaTime, tr->trDelta, result );
1229 result[2] -= 0.5 * DEFAULT_GRAVITY * deltaTime * deltaTime; // FIXME: local gravity...
1230 break;
1231 default:
1232 Com_Error( ERR_DROP, "BG_EvaluateTrajectory: unknown trType: %i", tr->trTime );
1233 break;
1234 }
1235 }
1236
1237 /*
1238 ================
1239 BG_EvaluateTrajectoryDelta
1240
1241 For determining velocity at a given time
1242 ================
1243 */
BG_EvaluateTrajectoryDelta(const trajectory_t * tr,int atTime,vec3_t result)1244 void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result ) {
1245 float deltaTime;
1246 float phase;
1247
1248 switch( tr->trType ) {
1249 case TR_STATIONARY:
1250 case TR_INTERPOLATE:
1251 VectorClear( result );
1252 break;
1253 case TR_LINEAR:
1254 VectorCopy( tr->trDelta, result );
1255 break;
1256 case TR_SINE:
1257 deltaTime = ( atTime - tr->trTime ) / (float) tr->trDuration;
1258 phase = cos( deltaTime * M_PI * 2 ); // derivative of sin = cos
1259 phase *= 0.5;
1260 VectorScale( tr->trDelta, phase, result );
1261 break;
1262 case TR_LINEAR_STOP:
1263 if ( atTime > tr->trTime + tr->trDuration ) {
1264 VectorClear( result );
1265 return;
1266 }
1267 VectorCopy( tr->trDelta, result );
1268 break;
1269 case TR_GRAVITY:
1270 deltaTime = ( atTime - tr->trTime ) * 0.001; // milliseconds to seconds
1271 VectorCopy( tr->trDelta, result );
1272 result[2] -= DEFAULT_GRAVITY * deltaTime; // FIXME: local gravity...
1273 break;
1274 default:
1275 Com_Error( ERR_DROP, "BG_EvaluateTrajectoryDelta: unknown trType: %i", tr->trTime );
1276 break;
1277 }
1278 }
1279
1280 char *eventnames[] = {
1281 "EV_NONE",
1282
1283 "EV_FOOTSTEP",
1284 "EV_FOOTSTEP_METAL",
1285 "EV_FOOTSPLASH",
1286 "EV_FOOTWADE",
1287 "EV_SWIM",
1288
1289 "EV_STEP_4",
1290 "EV_STEP_8",
1291 "EV_STEP_12",
1292 "EV_STEP_16",
1293
1294 "EV_FALL_SHORT",
1295 "EV_FALL_MEDIUM",
1296 "EV_FALL_FAR",
1297
1298 "EV_JUMP_PAD", // boing sound at origin", jump sound on player
1299
1300 "EV_JUMP",
1301 "EV_WATER_TOUCH", // foot touches
1302 "EV_WATER_LEAVE", // foot leaves
1303 "EV_WATER_UNDER", // head touches
1304 "EV_WATER_CLEAR", // head leaves
1305
1306 "EV_ITEM_PICKUP", // normal item pickups are predictable
1307 "EV_GLOBAL_ITEM_PICKUP", // powerup / team sounds are broadcast to everyone
1308
1309 "EV_NOAMMO",
1310 "EV_CHANGE_WEAPON",
1311 "EV_FIRE_WEAPON",
1312
1313 "EV_USE_ITEM0",
1314 "EV_USE_ITEM1",
1315 "EV_USE_ITEM2",
1316 "EV_USE_ITEM3",
1317 "EV_USE_ITEM4",
1318 "EV_USE_ITEM5",
1319 "EV_USE_ITEM6",
1320 "EV_USE_ITEM7",
1321 "EV_USE_ITEM8",
1322 "EV_USE_ITEM9",
1323 "EV_USE_ITEM10",
1324 "EV_USE_ITEM11",
1325 "EV_USE_ITEM12",
1326 "EV_USE_ITEM13",
1327 "EV_USE_ITEM14",
1328 "EV_USE_ITEM15",
1329
1330 "EV_ITEM_RESPAWN",
1331 "EV_ITEM_POP",
1332 "EV_PLAYER_TELEPORT_IN",
1333 "EV_PLAYER_TELEPORT_OUT",
1334
1335 "EV_GRENADE_BOUNCE", // eventParm will be the soundindex
1336
1337 "EV_GENERAL_SOUND",
1338 "EV_GLOBAL_SOUND", // no attenuation
1339 "EV_GLOBAL_TEAM_SOUND",
1340
1341 "EV_BULLET_HIT_FLESH",
1342 "EV_BULLET_HIT_WALL",
1343
1344 "EV_MISSILE_HIT",
1345 "EV_MISSILE_MISS",
1346 "EV_MISSILE_MISS_METAL",
1347 "EV_RAILTRAIL",
1348 "EV_SHOTGUN",
1349 "EV_BULLET", // otherEntity is the shooter
1350
1351 "EV_PAIN",
1352 "EV_DEATH1",
1353 "EV_DEATH2",
1354 "EV_DEATH3",
1355 "EV_OBITUARY",
1356
1357 "EV_POWERUP_QUAD",
1358 "EV_POWERUP_BATTLESUIT",
1359 "EV_POWERUP_REGEN",
1360
1361 "EV_GIB_PLAYER", // gib a previously living player
1362 "EV_SCOREPLUM", // score plum
1363
1364 //#ifdef MISSIONPACK
1365 "EV_PROXIMITY_MINE_STICK",
1366 "EV_PROXIMITY_MINE_TRIGGER",
1367 "EV_KAMIKAZE", // kamikaze explodes
1368 "EV_OBELISKEXPLODE", // obelisk explodes
1369 "EV_INVUL_IMPACT", // invulnerability sphere impact
1370 "EV_JUICED", // invulnerability juiced effect
1371 "EV_LIGHTNINGBOLT", // lightning bolt bounced of invulnerability sphere
1372 //#endif
1373
1374 "EV_DEBUG_LINE",
1375 "EV_STOPLOOPINGSOUND",
1376 "EV_TAUNT"
1377
1378 };
1379
1380 /*
1381 ===============
1382 BG_AddPredictableEventToPlayerstate
1383
1384 Handles the sequence numbers
1385 ===============
1386 */
1387
1388 void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize );
1389
BG_AddPredictableEventToPlayerstate(int newEvent,int eventParm,playerState_t * ps)1390 void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps ) {
1391
1392 #ifdef _DEBUG
1393 {
1394 char buf[256];
1395 trap_Cvar_VariableStringBuffer("showevents", buf, sizeof(buf));
1396 if ( atof(buf) != 0 ) {
1397 #ifdef QAGAME
1398 Com_Printf(" game event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm);
1399 #else
1400 Com_Printf("Cgame event svt %5d -> %5d: num = %20s parm %d\n", ps->pmove_framecount/*ps->commandTime*/, ps->eventSequence, eventnames[newEvent], eventParm);
1401 #endif
1402 }
1403 }
1404 #endif
1405 ps->events[ps->eventSequence & (MAX_PS_EVENTS-1)] = newEvent;
1406 ps->eventParms[ps->eventSequence & (MAX_PS_EVENTS-1)] = eventParm;
1407 ps->eventSequence++;
1408 }
1409
1410 /*
1411 ========================
1412 BG_TouchJumpPad
1413 ========================
1414 */
BG_TouchJumpPad(playerState_t * ps,entityState_t * jumppad)1415 void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) {
1416 vec3_t angles;
1417 float p;
1418 int effectNum;
1419
1420 // spectators don't use jump pads
1421 if ( ps->pm_type != PM_NORMAL ) {
1422 return;
1423 }
1424
1425 // flying characters don't hit bounce pads
1426 if ( ps->powerups[PW_FLIGHT] ) {
1427 return;
1428 }
1429
1430 // if we didn't hit this same jumppad the previous frame
1431 // then don't play the event sound again if we are in a fat trigger
1432 if ( ps->jumppad_ent != jumppad->number ) {
1433
1434 vectoangles( jumppad->origin2, angles);
1435 p = fabs( AngleNormalize180( angles[PITCH] ) );
1436 if( p < 45 ) {
1437 effectNum = 0;
1438 } else {
1439 effectNum = 1;
1440 }
1441 BG_AddPredictableEventToPlayerstate( EV_JUMP_PAD, effectNum, ps );
1442 }
1443 // remember hitting this jumppad this frame
1444 ps->jumppad_ent = jumppad->number;
1445 ps->jumppad_frame = ps->pmove_framecount;
1446 // give the player the velocity from the jumppad
1447 VectorCopy( jumppad->origin2, ps->velocity );
1448 }
1449
1450 /*
1451 ========================
1452 BG_PlayerStateToEntityState
1453
1454 This is done after each set of usercmd_t on the server,
1455 and after local prediction on the client
1456 ========================
1457 */
BG_PlayerStateToEntityState(playerState_t * ps,entityState_t * s,qboolean snap)1458 void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap ) {
1459 int i;
1460
1461 if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) {
1462 s->eType = ET_INVISIBLE;
1463 } else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) {
1464 s->eType = ET_INVISIBLE;
1465 } else {
1466 s->eType = ET_PLAYER;
1467 }
1468
1469 s->number = ps->clientNum;
1470
1471 s->pos.trType = TR_INTERPOLATE;
1472 VectorCopy( ps->origin, s->pos.trBase );
1473 if ( snap ) {
1474 SnapVector( s->pos.trBase );
1475 }
1476 // set the trDelta for flag direction
1477 VectorCopy( ps->velocity, s->pos.trDelta );
1478
1479 s->apos.trType = TR_INTERPOLATE;
1480 VectorCopy( ps->viewangles, s->apos.trBase );
1481 if ( snap ) {
1482 SnapVector( s->apos.trBase );
1483 }
1484
1485 s->angles2[YAW] = ps->movementDir;
1486 s->legsAnim = ps->legsAnim;
1487 s->torsoAnim = ps->torsoAnim;
1488 s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
1489 // so corpses can also reference the proper config
1490 s->eFlags = ps->eFlags;
1491 if ( ps->stats[STAT_HEALTH] <= 0 ) {
1492 s->eFlags |= EF_DEAD;
1493 } else {
1494 s->eFlags &= ~EF_DEAD;
1495 }
1496
1497 if ( ps->externalEvent ) {
1498 s->event = ps->externalEvent;
1499 s->eventParm = ps->externalEventParm;
1500 } else if ( ps->entityEventSequence < ps->eventSequence ) {
1501 int seq;
1502
1503 if ( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS) {
1504 ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
1505 }
1506 seq = ps->entityEventSequence & (MAX_PS_EVENTS-1);
1507 s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
1508 s->eventParm = ps->eventParms[ seq ];
1509 ps->entityEventSequence++;
1510 }
1511
1512 s->weapon = ps->weapon;
1513 s->groundEntityNum = ps->groundEntityNum;
1514
1515 s->powerups = 0;
1516 for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
1517 if ( ps->powerups[ i ] ) {
1518 s->powerups |= 1 << i;
1519 }
1520 }
1521
1522 s->loopSound = ps->loopSound;
1523 s->generic1 = ps->generic1;
1524 }
1525
1526 /*
1527 ========================
1528 BG_PlayerStateToEntityStateExtraPolate
1529
1530 This is done after each set of usercmd_t on the server,
1531 and after local prediction on the client
1532 ========================
1533 */
BG_PlayerStateToEntityStateExtraPolate(playerState_t * ps,entityState_t * s,int time,qboolean snap)1534 void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap ) {
1535 int i;
1536
1537 if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPECTATOR ) {
1538 s->eType = ET_INVISIBLE;
1539 } else if ( ps->stats[STAT_HEALTH] <= GIB_HEALTH ) {
1540 s->eType = ET_INVISIBLE;
1541 } else {
1542 s->eType = ET_PLAYER;
1543 }
1544
1545 s->number = ps->clientNum;
1546
1547 s->pos.trType = TR_LINEAR_STOP;
1548 VectorCopy( ps->origin, s->pos.trBase );
1549 if ( snap ) {
1550 SnapVector( s->pos.trBase );
1551 }
1552 // set the trDelta for flag direction and linear prediction
1553 VectorCopy( ps->velocity, s->pos.trDelta );
1554 // set the time for linear prediction
1555 s->pos.trTime = time;
1556 // set maximum extra polation time
1557 s->pos.trDuration = 50; // 1000 / sv_fps (default = 20)
1558
1559 s->apos.trType = TR_INTERPOLATE;
1560 VectorCopy( ps->viewangles, s->apos.trBase );
1561 if ( snap ) {
1562 SnapVector( s->apos.trBase );
1563 }
1564
1565 s->angles2[YAW] = ps->movementDir;
1566 s->legsAnim = ps->legsAnim;
1567 s->torsoAnim = ps->torsoAnim;
1568 s->clientNum = ps->clientNum; // ET_PLAYER looks here instead of at number
1569 // so corpses can also reference the proper config
1570 s->eFlags = ps->eFlags;
1571 if ( ps->stats[STAT_HEALTH] <= 0 ) {
1572 s->eFlags |= EF_DEAD;
1573 } else {
1574 s->eFlags &= ~EF_DEAD;
1575 }
1576
1577 if ( ps->externalEvent ) {
1578 s->event = ps->externalEvent;
1579 s->eventParm = ps->externalEventParm;
1580 } else if ( ps->entityEventSequence < ps->eventSequence ) {
1581 int seq;
1582
1583 if ( ps->entityEventSequence < ps->eventSequence - MAX_PS_EVENTS) {
1584 ps->entityEventSequence = ps->eventSequence - MAX_PS_EVENTS;
1585 }
1586 seq = ps->entityEventSequence & (MAX_PS_EVENTS-1);
1587 s->event = ps->events[ seq ] | ( ( ps->entityEventSequence & 3 ) << 8 );
1588 s->eventParm = ps->eventParms[ seq ];
1589 ps->entityEventSequence++;
1590 }
1591
1592 s->weapon = ps->weapon;
1593 s->groundEntityNum = ps->groundEntityNum;
1594
1595 s->powerups = 0;
1596 for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
1597 if ( ps->powerups[ i ] ) {
1598 s->powerups |= 1 << i;
1599 }
1600 }
1601
1602 s->loopSound = ps->loopSound;
1603 s->generic1 = ps->generic1;
1604 }
1605