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