1 /*
2 ===========================================================================
3 Copyright (C) 2000 - 2013, Raven Software, Inc.
4 Copyright (C) 2001 - 2013, Activision, Inc.
5 Copyright (C) 2013 - 2015, OpenJK contributors
6 
7 This file is part of the OpenJK source code.
8 
9 OpenJK is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License version 2 as
11 published by the Free Software Foundation.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, see <http://www.gnu.org/licenses/>.
20 ===========================================================================
21 */
22 
23 // BG_PAnimate.c
24 // game and cgame, NOT ui
25 
26 #include "qcommon/q_shared.h"
27 #include "bg_public.h"
28 #include "bg_local.h"
29 #include "anims.h"
30 #include "cgame/animtable.h"
31 
32 #ifdef _GAME
33 	#include "g_local.h"
34 #elif _CGAME
35 	#include "cgame/cg_local.h"
36 #elif UI_BUILD
37 	#include "ui/ui_local.h"
38 #endif
39 
40 extern saberInfo_t *BG_MySaber( int clientNum, int saberNum );
41 /*
42 ==============================================================================
43 BEGIN: Animation utility functions (sequence checking)
44 ==============================================================================
45 */
46 //Called regardless of pm validity:
47 
48 // VVFIXME - Most of these functions are totally stateless and stupid. Don't
49 // need multiple copies of this, but it's much easier (and less likely to
50 // break in the future) if I keep separate namespace versions now.
51 
BG_SaberStanceAnim(int anim)52 qboolean BG_SaberStanceAnim( int anim )
53 {
54 	switch ( anim )
55 	{
56 	case BOTH_STAND1://not really a saberstance anim, actually... "saber off" stance
57 	case BOTH_STAND2://single-saber, medium style
58 	case BOTH_SABERFAST_STANCE://single-saber, fast style
59 	case BOTH_SABERSLOW_STANCE://single-saber, strong style
60 	case BOTH_SABERSTAFF_STANCE://saber staff style
61 	case BOTH_SABERDUAL_STANCE://dual saber style
62 		return qtrue;
63 		break;
64 	}
65 	return qfalse;
66 }
67 
BG_CrouchAnim(int anim)68 qboolean BG_CrouchAnim( int anim )
69 {
70 	switch ( anim )
71 	{
72 	case BOTH_SIT1:				//# Normal chair sit.
73 	case BOTH_SIT2:				//# Lotus position.
74 	case BOTH_SIT3:				//# Sitting in tired position: elbows on knees
75 	case BOTH_CROUCH1:			//# Transition from standing to crouch
76 	case BOTH_CROUCH1IDLE:		//# Crouching idle
77 	case BOTH_CROUCH1WALK:		//# Walking while crouched
78 	case BOTH_CROUCH1WALKBACK:	//# Walking while crouched
79 	case BOTH_CROUCH2TOSTAND1:	//# going from crouch2 to stand1
80 	case BOTH_CROUCH3:			//# Desann crouching down to Kyle (cin 9)
81 	case BOTH_KNEES1:			//# Tavion on her knees
82 	case BOTH_CROUCHATTACKBACK1://FIXME: not if in middle of anim?
83 	case BOTH_ROLL_STAB:
84 		return qtrue;
85 		break;
86 	}
87 	return qfalse;
88 }
89 
BG_InSpecialJump(int anim)90 qboolean BG_InSpecialJump( int anim )
91 {
92 	switch ( (anim) )
93 	{
94 	case BOTH_WALL_RUN_RIGHT:
95 	case BOTH_WALL_RUN_RIGHT_STOP:
96 	case BOTH_WALL_RUN_RIGHT_FLIP:
97 	case BOTH_WALL_RUN_LEFT:
98 	case BOTH_WALL_RUN_LEFT_STOP:
99 	case BOTH_WALL_RUN_LEFT_FLIP:
100 	case BOTH_WALL_FLIP_RIGHT:
101 	case BOTH_WALL_FLIP_LEFT:
102 	case BOTH_FLIP_BACK1:
103 	case BOTH_FLIP_BACK2:
104 	case BOTH_FLIP_BACK3:
105 	case BOTH_WALL_FLIP_BACK1:
106 	case BOTH_BUTTERFLY_LEFT:
107 	case BOTH_BUTTERFLY_RIGHT:
108 	case BOTH_BUTTERFLY_FL1:
109 	case BOTH_BUTTERFLY_FR1:
110 	case BOTH_FJSS_TR_BL:
111 	case BOTH_FJSS_TL_BR:
112 	case BOTH_FORCELEAP2_T__B_:
113 	case BOTH_JUMPFLIPSLASHDOWN1://#
114 	case BOTH_JUMPFLIPSTABDOWN://#
115 	case BOTH_JUMPATTACK6:
116 	case BOTH_JUMPATTACK7:
117 	case BOTH_ARIAL_LEFT:
118 	case BOTH_ARIAL_RIGHT:
119 	case BOTH_ARIAL_F1:
120 	case BOTH_CARTWHEEL_LEFT:
121 	case BOTH_CARTWHEEL_RIGHT:
122 
123 	case BOTH_FORCELONGLEAP_START:
124 	case BOTH_FORCELONGLEAP_ATTACK:
125 	case BOTH_FORCEWALLRUNFLIP_START:
126 	case BOTH_FORCEWALLRUNFLIP_END:
127 	case BOTH_FORCEWALLRUNFLIP_ALT:
128 	case BOTH_FLIP_ATTACK7:
129 	case BOTH_FLIP_HOLD7:
130 	case BOTH_FLIP_LAND:
131 	case BOTH_A7_SOULCAL:
132 		return qtrue;
133 	}
134 	if ( BG_InReboundJump( anim ) )
135 	{
136 		return qtrue;
137 	}
138 	if ( BG_InReboundHold( anim ) )
139 	{
140 		return qtrue;
141 	}
142 	if ( BG_InReboundRelease( anim ) )
143 	{
144 		return qtrue;
145 	}
146 	if ( BG_InBackFlip( anim ) )
147 	{
148 		return qtrue;
149 	}
150 	return qfalse;
151 }
152 
BG_InSaberStandAnim(int anim)153 qboolean BG_InSaberStandAnim( int anim )
154 {
155 	switch ( (anim) )
156 	{
157 	case BOTH_SABERFAST_STANCE:
158 	case BOTH_STAND2:
159 	case BOTH_SABERSLOW_STANCE:
160 	case BOTH_SABERDUAL_STANCE:
161 	case BOTH_SABERSTAFF_STANCE:
162 		return qtrue;
163 	default:
164 		return qfalse;
165 	}
166 }
167 
BG_InReboundJump(int anim)168 qboolean BG_InReboundJump( int anim )
169 {
170 	switch ( anim )
171 	{
172 	case BOTH_FORCEWALLREBOUND_FORWARD:
173 	case BOTH_FORCEWALLREBOUND_LEFT:
174 	case BOTH_FORCEWALLREBOUND_BACK:
175 	case BOTH_FORCEWALLREBOUND_RIGHT:
176 		return qtrue;
177 		break;
178 	}
179 	return qfalse;
180 }
181 
BG_InReboundHold(int anim)182 qboolean BG_InReboundHold( int anim )
183 {
184 	switch ( anim )
185 	{
186 	case BOTH_FORCEWALLHOLD_FORWARD:
187 	case BOTH_FORCEWALLHOLD_LEFT:
188 	case BOTH_FORCEWALLHOLD_BACK:
189 	case BOTH_FORCEWALLHOLD_RIGHT:
190 		return qtrue;
191 		break;
192 	}
193 	return qfalse;
194 }
195 
BG_InReboundRelease(int anim)196 qboolean BG_InReboundRelease( int anim )
197 {
198 	switch ( anim )
199 	{
200 	case BOTH_FORCEWALLRELEASE_FORWARD:
201 	case BOTH_FORCEWALLRELEASE_LEFT:
202 	case BOTH_FORCEWALLRELEASE_BACK:
203 	case BOTH_FORCEWALLRELEASE_RIGHT:
204 		return qtrue;
205 		break;
206 	}
207 	return qfalse;
208 }
209 
BG_InBackFlip(int anim)210 qboolean BG_InBackFlip( int anim )
211 {
212 	switch ( anim )
213 	{
214 	case BOTH_FLIP_BACK1:
215 	case BOTH_FLIP_BACK2:
216 	case BOTH_FLIP_BACK3:
217 		return qtrue;
218 		break;
219 	}
220 	return qfalse;
221 }
222 
BG_DirectFlippingAnim(int anim)223 qboolean BG_DirectFlippingAnim( int anim )
224 {
225 	switch ( (anim) )
226 	{
227 	case BOTH_FLIP_F:			//# Flip forward
228 	case BOTH_FLIP_B:			//# Flip backwards
229 	case BOTH_FLIP_L:			//# Flip left
230 	case BOTH_FLIP_R:			//# Flip right
231 		return qtrue;
232 		break;
233 	}
234 
235 	return qfalse;
236 }
237 
BG_SaberInAttackPure(int move)238 qboolean BG_SaberInAttackPure( int move )
239 {
240 	if ( move >= LS_A_TL2BR && move <= LS_A_T2B )
241 	{
242 		return qtrue;
243 	}
244 	return qfalse;
245 }
BG_SaberInAttack(int move)246 qboolean BG_SaberInAttack( int move )
247 {
248 	if ( move >= LS_A_TL2BR && move <= LS_A_T2B )
249 	{
250 		return qtrue;
251 	}
252 	switch ( move )
253 	{
254 	case LS_A_BACK:
255 	case LS_A_BACK_CR:
256 	case LS_A_BACKSTAB:
257 	case LS_ROLL_STAB:
258 	case LS_A_LUNGE:
259 	case LS_A_JUMP_T__B_:
260 	case LS_A_FLIP_STAB:
261 	case LS_A_FLIP_SLASH:
262 	case LS_JUMPATTACK_DUAL:
263 	case LS_JUMPATTACK_ARIAL_LEFT:
264 	case LS_JUMPATTACK_ARIAL_RIGHT:
265 	case LS_JUMPATTACK_CART_LEFT:
266 	case LS_JUMPATTACK_CART_RIGHT:
267 	case LS_JUMPATTACK_STAFF_LEFT:
268 	case LS_JUMPATTACK_STAFF_RIGHT:
269 	case LS_BUTTERFLY_LEFT:
270 	case LS_BUTTERFLY_RIGHT:
271 	case LS_A_BACKFLIP_ATK:
272 	case LS_SPINATTACK_DUAL:
273 	case LS_SPINATTACK:
274 	case LS_LEAP_ATTACK:
275 	case LS_SWOOP_ATTACK_RIGHT:
276 	case LS_SWOOP_ATTACK_LEFT:
277 	case LS_TAUNTAUN_ATTACK_RIGHT:
278 	case LS_TAUNTAUN_ATTACK_LEFT:
279 	case LS_KICK_F:
280 	case LS_KICK_B:
281 	case LS_KICK_R:
282 	case LS_KICK_L:
283 	case LS_KICK_S:
284 	case LS_KICK_BF:
285 	case LS_KICK_RL:
286 	case LS_KICK_F_AIR:
287 	case LS_KICK_B_AIR:
288 	case LS_KICK_R_AIR:
289 	case LS_KICK_L_AIR:
290 	case LS_STABDOWN:
291 	case LS_STABDOWN_STAFF:
292 	case LS_STABDOWN_DUAL:
293 	case LS_DUAL_SPIN_PROTECT:
294 	case LS_STAFF_SOULCAL:
295 	case LS_A1_SPECIAL:
296 	case LS_A2_SPECIAL:
297 	case LS_A3_SPECIAL:
298 	case LS_UPSIDE_DOWN_ATTACK:
299 	case LS_PULL_ATTACK_STAB:
300 	case LS_PULL_ATTACK_SWING:
301 	case LS_SPINATTACK_ALORA:
302 	case LS_DUAL_FB:
303 	case LS_DUAL_LR:
304 	case LS_HILT_BASH:
305 		return qtrue;
306 		break;
307 	}
308 	return qfalse;
309 }
310 
BG_SaberInKata(int saberMove)311 qboolean BG_SaberInKata( int saberMove )
312 {
313 	switch ( saberMove )
314 	{
315 	case LS_A1_SPECIAL:
316 	case LS_A2_SPECIAL:
317 	case LS_A3_SPECIAL:
318 	case LS_DUAL_SPIN_PROTECT:
319 	case LS_STAFF_SOULCAL:
320 		return qtrue;
321 	}
322 	return qfalse;
323 }
324 
BG_InKataAnim(int anim)325 qboolean BG_InKataAnim(int anim)
326 {
327 	switch (anim)
328 	{
329 	case BOTH_A6_SABERPROTECT:
330 	case BOTH_A7_SOULCAL:
331 	case BOTH_A1_SPECIAL:
332 	case BOTH_A2_SPECIAL:
333 	case BOTH_A3_SPECIAL:
334 		return qtrue;
335 	}
336 	return qfalse;
337 }
338 
BG_SaberInSpecial(int move)339 qboolean BG_SaberInSpecial( int move )
340 {
341 	switch( move )
342 	{
343 	case LS_A_BACK:
344 	case LS_A_BACK_CR:
345 	case LS_A_BACKSTAB:
346 	case LS_ROLL_STAB:
347 	case LS_A_LUNGE:
348 	case LS_A_JUMP_T__B_:
349 	case LS_A_FLIP_STAB:
350 	case LS_A_FLIP_SLASH:
351 	case LS_JUMPATTACK_DUAL:
352 	case LS_JUMPATTACK_ARIAL_LEFT:
353 	case LS_JUMPATTACK_ARIAL_RIGHT:
354 	case LS_JUMPATTACK_CART_LEFT:
355 	case LS_JUMPATTACK_CART_RIGHT:
356 	case LS_JUMPATTACK_STAFF_LEFT:
357 	case LS_JUMPATTACK_STAFF_RIGHT:
358 	case LS_BUTTERFLY_LEFT:
359 	case LS_BUTTERFLY_RIGHT:
360 	case LS_A_BACKFLIP_ATK:
361 	case LS_SPINATTACK_DUAL:
362 	case LS_SPINATTACK:
363 	case LS_LEAP_ATTACK:
364 	case LS_SWOOP_ATTACK_RIGHT:
365 	case LS_SWOOP_ATTACK_LEFT:
366 	case LS_TAUNTAUN_ATTACK_RIGHT:
367 	case LS_TAUNTAUN_ATTACK_LEFT:
368 	case LS_KICK_F:
369 	case LS_KICK_B:
370 	case LS_KICK_R:
371 	case LS_KICK_L:
372 	case LS_KICK_S:
373 	case LS_KICK_BF:
374 	case LS_KICK_RL:
375 	case LS_KICK_F_AIR:
376 	case LS_KICK_B_AIR:
377 	case LS_KICK_R_AIR:
378 	case LS_KICK_L_AIR:
379 	case LS_STABDOWN:
380 	case LS_STABDOWN_STAFF:
381 	case LS_STABDOWN_DUAL:
382 	case LS_DUAL_SPIN_PROTECT:
383 	case LS_STAFF_SOULCAL:
384 	case LS_A1_SPECIAL:
385 	case LS_A2_SPECIAL:
386 	case LS_A3_SPECIAL:
387 	case LS_UPSIDE_DOWN_ATTACK:
388 	case LS_PULL_ATTACK_STAB:
389 	case LS_PULL_ATTACK_SWING:
390 	case LS_SPINATTACK_ALORA:
391 	case LS_DUAL_FB:
392 	case LS_DUAL_LR:
393 	case LS_HILT_BASH:
394 		return qtrue;
395 	}
396 	return qfalse;
397 }
398 
BG_KickMove(int move)399 qboolean BG_KickMove( int move )
400 {
401 	switch( move )
402 	{
403 	case LS_KICK_F:
404 	case LS_KICK_B:
405 	case LS_KICK_R:
406 	case LS_KICK_L:
407 	case LS_KICK_S:
408 	case LS_KICK_BF:
409 	case LS_KICK_RL:
410 	case LS_KICK_F_AIR:
411 	case LS_KICK_B_AIR:
412 	case LS_KICK_R_AIR:
413 	case LS_KICK_L_AIR:
414 	case LS_HILT_BASH:
415 		return qtrue;
416 	}
417 	return qfalse;
418 }
419 
BG_SaberInIdle(int move)420 qboolean BG_SaberInIdle( int move )
421 {
422 	switch ( move )
423 	{
424 	case LS_NONE:
425 	case LS_READY:
426 	case LS_DRAW:
427 	case LS_PUTAWAY:
428 		return qtrue;
429 		break;
430 	}
431 	return qfalse;
432 }
433 
BG_InExtraDefenseSaberMove(int move)434 qboolean BG_InExtraDefenseSaberMove( int move )
435 {
436 	switch ( move )
437 	{
438 	case LS_SPINATTACK_DUAL:
439 	case LS_SPINATTACK:
440 	case LS_DUAL_SPIN_PROTECT:
441 	case LS_STAFF_SOULCAL:
442 	case LS_A1_SPECIAL:
443 	case LS_A2_SPECIAL:
444 	case LS_A3_SPECIAL:
445 	case LS_JUMPATTACK_DUAL:
446 		return qtrue;
447 		break;
448 	}
449 	return qfalse;
450 }
451 
BG_FlippingAnim(int anim)452 qboolean BG_FlippingAnim( int anim )
453 {
454 	switch ( anim )
455 	{
456 	case BOTH_FLIP_F:			//# Flip forward
457 	case BOTH_FLIP_B:			//# Flip backwards
458 	case BOTH_FLIP_L:			//# Flip left
459 	case BOTH_FLIP_R:			//# Flip right
460 	case BOTH_WALL_RUN_RIGHT_FLIP:
461 	case BOTH_WALL_RUN_LEFT_FLIP:
462 	case BOTH_WALL_FLIP_RIGHT:
463 	case BOTH_WALL_FLIP_LEFT:
464 	case BOTH_FLIP_BACK1:
465 	case BOTH_FLIP_BACK2:
466 	case BOTH_FLIP_BACK3:
467 	case BOTH_WALL_FLIP_BACK1:
468 	//Not really flips, but...
469 	case BOTH_WALL_RUN_RIGHT:
470 	case BOTH_WALL_RUN_LEFT:
471 	case BOTH_WALL_RUN_RIGHT_STOP:
472 	case BOTH_WALL_RUN_LEFT_STOP:
473 	case BOTH_BUTTERFLY_LEFT:
474 	case BOTH_BUTTERFLY_RIGHT:
475 	case BOTH_BUTTERFLY_FL1:
476 	case BOTH_BUTTERFLY_FR1:
477 	//
478 	case BOTH_ARIAL_LEFT:
479 	case BOTH_ARIAL_RIGHT:
480 	case BOTH_ARIAL_F1:
481 	case BOTH_CARTWHEEL_LEFT:
482 	case BOTH_CARTWHEEL_RIGHT:
483 	case BOTH_JUMPFLIPSLASHDOWN1:
484 	case BOTH_JUMPFLIPSTABDOWN:
485 	case BOTH_JUMPATTACK6:
486 	case BOTH_JUMPATTACK7:
487 	//JKA
488 	case BOTH_FORCEWALLRUNFLIP_END:
489 	case BOTH_FORCEWALLRUNFLIP_ALT:
490 	case BOTH_FLIP_ATTACK7:
491 	case BOTH_A7_SOULCAL:
492 		return qtrue;
493 		break;
494 	}
495 	return qfalse;
496 }
497 
BG_SpinningSaberAnim(int anim)498 qboolean BG_SpinningSaberAnim( int anim )
499 {
500 	switch ( anim )
501 	{
502 	//level 1 - FIXME: level 1 will have *no* spins
503 	case BOTH_T1_BR_BL:
504 	case BOTH_T1__R__L:
505 	case BOTH_T1__R_BL:
506 	case BOTH_T1_TR_BL:
507 	case BOTH_T1_BR_TL:
508 	case BOTH_T1_BR__L:
509 	case BOTH_T1_TL_BR:
510 	case BOTH_T1__L_BR:
511 	case BOTH_T1__L__R:
512 	case BOTH_T1_BL_BR:
513 	case BOTH_T1_BL__R:
514 	case BOTH_T1_BL_TR:
515 	//level 2
516 	case BOTH_T2_BR__L:
517 	case BOTH_T2_BR_BL:
518 	case BOTH_T2__R_BL:
519 	case BOTH_T2__L_BR:
520 	case BOTH_T2_BL_BR:
521 	case BOTH_T2_BL__R:
522 	//level 3
523 	case BOTH_T3_BR__L:
524 	case BOTH_T3_BR_BL:
525 	case BOTH_T3__R_BL:
526 	case BOTH_T3__L_BR:
527 	case BOTH_T3_BL_BR:
528 	case BOTH_T3_BL__R:
529 	//level 4
530 	case BOTH_T4_BR__L:
531 	case BOTH_T4_BR_BL:
532 	case BOTH_T4__R_BL:
533 	case BOTH_T4__L_BR:
534 	case BOTH_T4_BL_BR:
535 	case BOTH_T4_BL__R:
536 	//level 5
537 	case BOTH_T5_BR_BL:
538 	case BOTH_T5__R__L:
539 	case BOTH_T5__R_BL:
540 	case BOTH_T5_TR_BL:
541 	case BOTH_T5_BR_TL:
542 	case BOTH_T5_BR__L:
543 	case BOTH_T5_TL_BR:
544 	case BOTH_T5__L_BR:
545 	case BOTH_T5__L__R:
546 	case BOTH_T5_BL_BR:
547 	case BOTH_T5_BL__R:
548 	case BOTH_T5_BL_TR:
549 	//level 6
550 	case BOTH_T6_BR_TL:
551 	case BOTH_T6__R_TL:
552 	case BOTH_T6__R__L:
553 	case BOTH_T6__R_BL:
554 	case BOTH_T6_TR_TL:
555 	case BOTH_T6_TR__L:
556 	case BOTH_T6_TR_BL:
557 	case BOTH_T6_T__TL:
558 	case BOTH_T6_T__BL:
559 	case BOTH_T6_TL_BR:
560 	case BOTH_T6__L_BR:
561 	case BOTH_T6__L__R:
562 	case BOTH_T6_TL__R:
563 	case BOTH_T6_TL_TR:
564 	case BOTH_T6__L_TR:
565 	case BOTH_T6__L_T_:
566 	case BOTH_T6_BL_T_:
567 	case BOTH_T6_BR__L:
568 	case BOTH_T6_BR_BL:
569 	case BOTH_T6_BL_BR:
570 	case BOTH_T6_BL__R:
571 	case BOTH_T6_BL_TR:
572 	//level 7
573 	case BOTH_T7_BR_TL:
574 	case BOTH_T7_BR__L:
575 	case BOTH_T7_BR_BL:
576 	case BOTH_T7__R__L:
577 	case BOTH_T7__R_BL:
578 	case BOTH_T7_TR__L:
579 	case BOTH_T7_T___R:
580 	case BOTH_T7_TL_BR:
581 	case BOTH_T7__L_BR:
582 	case BOTH_T7__L__R:
583 	case BOTH_T7_BL_BR:
584 	case BOTH_T7_BL__R:
585 	case BOTH_T7_BL_TR:
586 	case BOTH_T7_TL_TR:
587 	case BOTH_T7_T__BR:
588 	case BOTH_T7__L_TR:
589 	case BOTH_V7_BL_S7:
590 	//special
591 	//case BOTH_A2_STABBACK1:
592 	case BOTH_ATTACK_BACK:
593 	case BOTH_CROUCHATTACKBACK1:
594 	case BOTH_BUTTERFLY_LEFT:
595 	case BOTH_BUTTERFLY_RIGHT:
596 	case BOTH_FJSS_TR_BL:
597 	case BOTH_FJSS_TL_BR:
598 	case BOTH_JUMPFLIPSLASHDOWN1:
599 	case BOTH_JUMPFLIPSTABDOWN:
600 		return qtrue;
601 		break;
602 	}
603 	return qfalse;
604 }
605 
BG_SaberInSpecialAttack(int anim)606 qboolean BG_SaberInSpecialAttack( int anim )
607 {
608 	switch ( anim )
609 	{
610 	case BOTH_A2_STABBACK1:
611 	case BOTH_ATTACK_BACK:
612 	case BOTH_CROUCHATTACKBACK1:
613 	case BOTH_ROLL_STAB:
614 	case BOTH_BUTTERFLY_LEFT:
615 	case BOTH_BUTTERFLY_RIGHT:
616 	case BOTH_BUTTERFLY_FL1:
617 	case BOTH_BUTTERFLY_FR1:
618 	case BOTH_FJSS_TR_BL:
619 	case BOTH_FJSS_TL_BR:
620 	case BOTH_LUNGE2_B__T_:
621 	case BOTH_FORCELEAP2_T__B_:
622 	case BOTH_JUMPFLIPSLASHDOWN1://#
623 	case BOTH_JUMPFLIPSTABDOWN://#
624 	case BOTH_JUMPATTACK6:
625 	case BOTH_JUMPATTACK7:
626 	case BOTH_SPINATTACK6:
627 	case BOTH_SPINATTACK7:
628 	case BOTH_FORCELONGLEAP_ATTACK:
629 	case BOTH_VS_ATR_S:
630 	case BOTH_VS_ATL_S:
631 	case BOTH_VT_ATR_S:
632 	case BOTH_VT_ATL_S:
633 	case BOTH_A7_KICK_F:
634 	case BOTH_A7_KICK_B:
635 	case BOTH_A7_KICK_R:
636 	case BOTH_A7_KICK_L:
637 	case BOTH_A7_KICK_S:
638 	case BOTH_A7_KICK_BF:
639 	case BOTH_A7_KICK_RL:
640 	case BOTH_A7_KICK_F_AIR:
641 	case BOTH_A7_KICK_B_AIR:
642 	case BOTH_A7_KICK_R_AIR:
643 	case BOTH_A7_KICK_L_AIR:
644 	case BOTH_STABDOWN:
645 	case BOTH_STABDOWN_STAFF:
646 	case BOTH_STABDOWN_DUAL:
647 	case BOTH_A6_SABERPROTECT:
648 	case BOTH_A7_SOULCAL:
649 	case BOTH_A1_SPECIAL:
650 	case BOTH_A2_SPECIAL:
651 	case BOTH_A3_SPECIAL:
652 	case BOTH_FLIP_ATTACK7:
653 	case BOTH_PULL_IMPALE_STAB:
654 	case BOTH_PULL_IMPALE_SWING:
655 	case BOTH_ALORA_SPIN_SLASH:
656 	case BOTH_A6_FB:
657 	case BOTH_A6_LR:
658 	case BOTH_A7_HILT:
659 		return qtrue;
660 	}
661 	return qfalse;
662 }
663 
BG_KickingAnim(int anim)664 qboolean BG_KickingAnim( int anim )
665 {
666 	switch ( anim )
667 	{
668 	case BOTH_A7_KICK_F:
669 	case BOTH_A7_KICK_B:
670 	case BOTH_A7_KICK_R:
671 	case BOTH_A7_KICK_L:
672 	case BOTH_A7_KICK_S:
673 	case BOTH_A7_KICK_BF:
674 	case BOTH_A7_KICK_RL:
675 	case BOTH_A7_KICK_F_AIR:
676 	case BOTH_A7_KICK_B_AIR:
677 	case BOTH_A7_KICK_R_AIR:
678 	case BOTH_A7_KICK_L_AIR:
679 	case BOTH_A7_HILT:
680 	//NOT kicks, but do kick traces anyway
681 	case BOTH_GETUP_BROLL_B:
682 	case BOTH_GETUP_BROLL_F:
683 	case BOTH_GETUP_FROLL_B:
684 	case BOTH_GETUP_FROLL_F:
685 		return qtrue;
686 		break;
687 	}
688 	return qfalse;
689 }
690 
BG_InGrappleMove(int anim)691 int BG_InGrappleMove(int anim)
692 {
693 	switch (anim)
694 	{
695 	case BOTH_KYLE_GRAB:
696 	case BOTH_KYLE_MISS:
697 		return 1; //grabbing at someone
698 	case BOTH_KYLE_PA_1:
699 	case BOTH_KYLE_PA_2:
700 		return 2; //beating the shit out of someone
701 	case BOTH_PLAYER_PA_1:
702 	case BOTH_PLAYER_PA_2:
703 	case BOTH_PLAYER_PA_FLY:
704 		return 3; //getting the shit beaten out of you
705 		break;
706 	}
707 
708 	return 0;
709 }
710 
BG_BrokenParryForAttack(int move)711 int BG_BrokenParryForAttack( int move )
712 {
713 	//Our attack was knocked away by a knockaway parry
714 	//FIXME: need actual anims for this
715 	//FIXME: need to know which side of the saber was hit!  For now, we presume the saber gets knocked away from the center
716 	switch ( saberMoveData[move].startQuad )
717 	{
718 	case Q_B:
719 		return LS_V1_B_;
720 		break;
721 	case Q_BR:
722 		return LS_V1_BR;
723 		break;
724 	case Q_R:
725 		return LS_V1__R;
726 		break;
727 	case Q_TR:
728 		return LS_V1_TR;
729 		break;
730 	case Q_T:
731 		return LS_V1_T_;
732 		break;
733 	case Q_TL:
734 		return LS_V1_TL;
735 		break;
736 	case Q_L:
737 		return LS_V1__L;
738 		break;
739 	case Q_BL:
740 		return LS_V1_BL;
741 		break;
742 	}
743 	return LS_NONE;
744 }
745 
BG_BrokenParryForParry(int move)746 int BG_BrokenParryForParry( int move )
747 {
748 	//FIXME: need actual anims for this
749 	//FIXME: need to know which side of the saber was hit!  For now, we presume the saber gets knocked away from the center
750 	switch ( move )
751 	{
752 	case LS_PARRY_UP:
753 		//Hmm... since we don't know what dir the hit came from, randomly pick knock down or knock back
754 		if ( Q_irand( 0, 1 ) )
755 		{
756 			return LS_H1_B_;
757 		}
758 		else
759 		{
760 			return LS_H1_T_;
761 		}
762 		break;
763 	case LS_PARRY_UR:
764 		return LS_H1_TR;
765 		break;
766 	case LS_PARRY_UL:
767 		return LS_H1_TL;
768 		break;
769 	case LS_PARRY_LR:
770 		return LS_H1_BR;
771 		break;
772 	case LS_PARRY_LL:
773 		return LS_H1_BL;
774 		break;
775 	case LS_READY:
776 		return LS_H1_B_;//???
777 		break;
778 	}
779 	return LS_NONE;
780 }
781 
BG_KnockawayForParry(int move)782 int BG_KnockawayForParry( int move )
783 {
784 	//FIXME: need actual anims for this
785 	//FIXME: need to know which side of the saber was hit!  For now, we presume the saber gets knocked away from the center
786 	switch ( move )
787 	{
788 	case BLOCKED_TOP://LS_PARRY_UP:
789 		return LS_K1_T_;//push up
790 		break;
791 	case BLOCKED_UPPER_RIGHT://LS_PARRY_UR:
792 	default://case LS_READY:
793 		return LS_K1_TR;//push up, slightly to right
794 		break;
795 	case BLOCKED_UPPER_LEFT://LS_PARRY_UL:
796 		return LS_K1_TL;//push up and to left
797 		break;
798 	case BLOCKED_LOWER_RIGHT://LS_PARRY_LR:
799 		return LS_K1_BR;//push down and to left
800 		break;
801 	case BLOCKED_LOWER_LEFT://LS_PARRY_LL:
802 		return LS_K1_BL;//push down and to right
803 		break;
804 	}
805 	//return LS_NONE;
806 }
807 
BG_InRoll(playerState_t * ps,int anim)808 qboolean BG_InRoll( playerState_t *ps, int anim )
809 {
810 	switch ( (anim) )
811 	{
812 	case BOTH_GETUP_BROLL_B:
813 	case BOTH_GETUP_BROLL_F:
814 	case BOTH_GETUP_BROLL_L:
815 	case BOTH_GETUP_BROLL_R:
816 	case BOTH_GETUP_FROLL_B:
817 	case BOTH_GETUP_FROLL_F:
818 	case BOTH_GETUP_FROLL_L:
819 	case BOTH_GETUP_FROLL_R:
820 	case BOTH_ROLL_F:
821 	case BOTH_ROLL_B:
822 	case BOTH_ROLL_R:
823 	case BOTH_ROLL_L:
824 		if ( ps->legsTimer > 0 )
825 		{
826 			return qtrue;
827 		}
828 		break;
829 	}
830 	return qfalse;
831 }
832 
BG_InSpecialDeathAnim(int anim)833 qboolean BG_InSpecialDeathAnim( int anim )
834 {
835 	switch( anim )
836 	{
837 	case BOTH_DEATH_ROLL:		//# Death anim from a roll
838 	case BOTH_DEATH_FLIP:		//# Death anim from a flip
839 	case BOTH_DEATH_SPIN_90_R:	//# Death anim when facing 90 degrees right
840 	case BOTH_DEATH_SPIN_90_L:	//# Death anim when facing 90 degrees left
841 	case BOTH_DEATH_SPIN_180:	//# Death anim when facing backwards
842 	case BOTH_DEATH_LYING_UP:	//# Death anim when lying on back
843 	case BOTH_DEATH_LYING_DN:	//# Death anim when lying on front
844 	case BOTH_DEATH_FALLING_DN:	//# Death anim when falling on face
845 	case BOTH_DEATH_FALLING_UP:	//# Death anim when falling on back
846 	case BOTH_DEATH_CROUCHED:	//# Death anim when crouched
847 		return qtrue;
848 		break;
849 	default:
850 		return qfalse;
851 		break;
852 	}
853 }
854 
BG_InDeathAnim(int anim)855 qboolean BG_InDeathAnim ( int anim )
856 {//Purposely does not cover stumbledeath and falldeath...
857 	switch( anim )
858 	{
859 	case BOTH_DEATH1:		//# First Death anim
860 	case BOTH_DEATH2:			//# Second Death anim
861 	case BOTH_DEATH3:			//# Third Death anim
862 	case BOTH_DEATH4:			//# Fourth Death anim
863 	case BOTH_DEATH5:			//# Fifth Death anim
864 	case BOTH_DEATH6:			//# Sixth Death anim
865 	case BOTH_DEATH7:			//# Seventh Death anim
866 	case BOTH_DEATH8:			//#
867 	case BOTH_DEATH9:			//#
868 	case BOTH_DEATH10:			//#
869 	case BOTH_DEATH11:			//#
870 	case BOTH_DEATH12:			//#
871 	case BOTH_DEATH13:			//#
872 	case BOTH_DEATH14:			//#
873 	case BOTH_DEATH14_UNGRIP:	//# Desann's end death (cin #35)
874 	case BOTH_DEATH14_SITUP:		//# Tavion sitting up after having been thrown (cin #23)
875 	case BOTH_DEATH15:			//#
876 	case BOTH_DEATH16:			//#
877 	case BOTH_DEATH17:			//#
878 	case BOTH_DEATH18:			//#
879 	case BOTH_DEATH19:			//#
880 	case BOTH_DEATH20:			//#
881 	case BOTH_DEATH21:			//#
882 	case BOTH_DEATH22:			//#
883 	case BOTH_DEATH23:			//#
884 	case BOTH_DEATH24:			//#
885 	case BOTH_DEATH25:			//#
886 
887 	case BOTH_DEATHFORWARD1:		//# First Death in which they get thrown forward
888 	case BOTH_DEATHFORWARD2:		//# Second Death in which they get thrown forward
889 	case BOTH_DEATHFORWARD3:		//# Tavion's falling in cin# 23
890 	case BOTH_DEATHBACKWARD1:	//# First Death in which they get thrown backward
891 	case BOTH_DEATHBACKWARD2:	//# Second Death in which they get thrown backward
892 
893 	case BOTH_DEATH1IDLE:		//# Idle while close to death
894 	case BOTH_LYINGDEATH1:		//# Death to play when killed lying down
895 	case BOTH_STUMBLEDEATH1:		//# Stumble forward and fall face first death
896 	case BOTH_FALLDEATH1:		//# Fall forward off a high cliff and splat death - start
897 	case BOTH_FALLDEATH1INAIR:	//# Fall forward off a high cliff and splat death - loop
898 	case BOTH_FALLDEATH1LAND:	//# Fall forward off a high cliff and splat death - hit bottom
899 	//# #sep case BOTH_ DEAD POSES # Should be last frame of corresponding previous anims
900 	case BOTH_DEAD1:				//# First Death finished pose
901 	case BOTH_DEAD2:				//# Second Death finished pose
902 	case BOTH_DEAD3:				//# Third Death finished pose
903 	case BOTH_DEAD4:				//# Fourth Death finished pose
904 	case BOTH_DEAD5:				//# Fifth Death finished pose
905 	case BOTH_DEAD6:				//# Sixth Death finished pose
906 	case BOTH_DEAD7:				//# Seventh Death finished pose
907 	case BOTH_DEAD8:				//#
908 	case BOTH_DEAD9:				//#
909 	case BOTH_DEAD10:			//#
910 	case BOTH_DEAD11:			//#
911 	case BOTH_DEAD12:			//#
912 	case BOTH_DEAD13:			//#
913 	case BOTH_DEAD14:			//#
914 	case BOTH_DEAD15:			//#
915 	case BOTH_DEAD16:			//#
916 	case BOTH_DEAD17:			//#
917 	case BOTH_DEAD18:			//#
918 	case BOTH_DEAD19:			//#
919 	case BOTH_DEAD20:			//#
920 	case BOTH_DEAD21:			//#
921 	case BOTH_DEAD22:			//#
922 	case BOTH_DEAD23:			//#
923 	case BOTH_DEAD24:			//#
924 	case BOTH_DEAD25:			//#
925 	case BOTH_DEADFORWARD1:		//# First thrown forward death finished pose
926 	case BOTH_DEADFORWARD2:		//# Second thrown forward death finished pose
927 	case BOTH_DEADBACKWARD1:		//# First thrown backward death finished pose
928 	case BOTH_DEADBACKWARD2:		//# Second thrown backward death finished pose
929 	case BOTH_LYINGDEAD1:		//# Killed lying down death finished pose
930 	case BOTH_STUMBLEDEAD1:		//# Stumble forward death finished pose
931 	case BOTH_FALLDEAD1LAND:		//# Fall forward and splat death finished pose
932 	//# #sep case BOTH_ DEAD TWITCH/FLOP # React to being shot from death poses
933 	case BOTH_DEADFLOP1:		//# React to being shot from First Death finished pose
934 	case BOTH_DEADFLOP2:		//# React to being shot from Second Death finished pose
935 	case BOTH_DISMEMBER_HEAD1:	//#
936 	case BOTH_DISMEMBER_TORSO1:	//#
937 	case BOTH_DISMEMBER_LLEG:	//#
938 	case BOTH_DISMEMBER_RLEG:	//#
939 	case BOTH_DISMEMBER_RARM:	//#
940 	case BOTH_DISMEMBER_LARM:	//#
941 		return qtrue;
942 		break;
943 	default:
944 		return BG_InSpecialDeathAnim( anim );
945 		break;
946 	}
947 }
948 
BG_InKnockDownOnly(int anim)949 qboolean BG_InKnockDownOnly( int anim )
950 {
951 	switch ( anim )
952 	{
953 	case BOTH_KNOCKDOWN1:
954 	case BOTH_KNOCKDOWN2:
955 	case BOTH_KNOCKDOWN3:
956 	case BOTH_KNOCKDOWN4:
957 	case BOTH_KNOCKDOWN5:
958 		return qtrue;
959 	}
960 	return qfalse;
961 }
962 
BG_InSaberLockOld(int anim)963 qboolean BG_InSaberLockOld( int anim )
964 {
965 	switch ( anim )
966 	{
967 	case BOTH_BF2LOCK:
968 	case BOTH_BF1LOCK:
969 	case BOTH_CWCIRCLELOCK:
970 	case BOTH_CCWCIRCLELOCK:
971 		return qtrue;
972 	}
973 	return qfalse;
974 }
975 
BG_InSaberLock(int anim)976 qboolean BG_InSaberLock( int anim )
977 {
978 	switch ( anim )
979 	{
980 	case BOTH_LK_S_DL_S_L_1:		//lock if I'm using single vs. a dual
981 	case BOTH_LK_S_DL_T_L_1:		//lock if I'm using single vs. a dual
982 	case BOTH_LK_S_ST_S_L_1:		//lock if I'm using single vs. a staff
983 	case BOTH_LK_S_ST_T_L_1:		//lock if I'm using single vs. a staff
984 	case BOTH_LK_S_S_S_L_1:		//lock if I'm using single vs. a single and I initiated
985 	case BOTH_LK_S_S_T_L_1:		//lock if I'm using single vs. a single and I initiated
986 	case BOTH_LK_DL_DL_S_L_1:	//lock if I'm using dual vs. dual and I initiated
987 	case BOTH_LK_DL_DL_T_L_1:	//lock if I'm using dual vs. dual and I initiated
988 	case BOTH_LK_DL_ST_S_L_1:	//lock if I'm using dual vs. a staff
989 	case BOTH_LK_DL_ST_T_L_1:	//lock if I'm using dual vs. a staff
990 	case BOTH_LK_DL_S_S_L_1:		//lock if I'm using dual vs. a single
991 	case BOTH_LK_DL_S_T_L_1:		//lock if I'm using dual vs. a single
992 	case BOTH_LK_ST_DL_S_L_1:	//lock if I'm using staff vs. dual
993 	case BOTH_LK_ST_DL_T_L_1:	//lock if I'm using staff vs. dual
994 	case BOTH_LK_ST_ST_S_L_1:	//lock if I'm using staff vs. a staff and I initiated
995 	case BOTH_LK_ST_ST_T_L_1:	//lock if I'm using staff vs. a staff and I initiated
996 	case BOTH_LK_ST_S_S_L_1:		//lock if I'm using staff vs. a single
997 	case BOTH_LK_ST_S_T_L_1:		//lock if I'm using staff vs. a single
998 	case BOTH_LK_S_S_S_L_2:
999 	case BOTH_LK_S_S_T_L_2:
1000 	case BOTH_LK_DL_DL_S_L_2:
1001 	case BOTH_LK_DL_DL_T_L_2:
1002 	case BOTH_LK_ST_ST_S_L_2:
1003 	case BOTH_LK_ST_ST_T_L_2:
1004 		return qtrue;
1005 		break;
1006 	default:
1007 		return BG_InSaberLockOld( anim );
1008 		break;
1009 	}
1010 	//return qfalse;
1011 }
1012 
1013 //Called only where pm is valid (not all require pm, but some do):
PM_InCartwheel(int anim)1014 qboolean PM_InCartwheel( int anim )
1015 {
1016 	switch ( anim )
1017 	{
1018 	case BOTH_ARIAL_LEFT:
1019 	case BOTH_ARIAL_RIGHT:
1020 	case BOTH_ARIAL_F1:
1021 	case BOTH_CARTWHEEL_LEFT:
1022 	case BOTH_CARTWHEEL_RIGHT:
1023 		return qtrue;
1024 		break;
1025 	}
1026 	return qfalse;
1027 }
1028 
BG_InKnockDownOnGround(playerState_t * ps)1029 qboolean BG_InKnockDownOnGround( playerState_t *ps )
1030 {
1031 	switch ( ps->legsAnim )
1032 	{
1033 	case BOTH_KNOCKDOWN1:
1034 	case BOTH_KNOCKDOWN2:
1035 	case BOTH_KNOCKDOWN3:
1036 	case BOTH_KNOCKDOWN4:
1037 	case BOTH_KNOCKDOWN5:
1038 	case BOTH_RELEASED:
1039 		//if ( PM_AnimLength( g_entities[ps->clientNum].client->clientInfo.animFileIndex, (animNumber_t)ps->legsAnim ) - ps->legsAnimTimer > 300 )
1040 		{//at end of fall down anim
1041 			return qtrue;
1042 		}
1043 		break;
1044 	case BOTH_GETUP1:
1045 	case BOTH_GETUP2:
1046 	case BOTH_GETUP3:
1047 	case BOTH_GETUP4:
1048 	case BOTH_GETUP5:
1049 	case BOTH_GETUP_CROUCH_F1:
1050 	case BOTH_GETUP_CROUCH_B1:
1051 	case BOTH_FORCE_GETUP_F1:
1052 	case BOTH_FORCE_GETUP_F2:
1053 	case BOTH_FORCE_GETUP_B1:
1054 	case BOTH_FORCE_GETUP_B2:
1055 	case BOTH_FORCE_GETUP_B3:
1056 	case BOTH_FORCE_GETUP_B4:
1057 	case BOTH_FORCE_GETUP_B5:
1058 	case BOTH_FORCE_GETUP_B6:
1059 		if ( BG_AnimLength( 0, (animNumber_t)ps->legsAnim ) - ps->legsTimer < 500 )
1060 		{//at beginning of getup anim
1061 			return qtrue;
1062 		}
1063 		break;
1064 	case BOTH_GETUP_BROLL_B:
1065 	case BOTH_GETUP_BROLL_F:
1066 	case BOTH_GETUP_BROLL_L:
1067 	case BOTH_GETUP_BROLL_R:
1068 	case BOTH_GETUP_FROLL_B:
1069 	case BOTH_GETUP_FROLL_F:
1070 	case BOTH_GETUP_FROLL_L:
1071 	case BOTH_GETUP_FROLL_R:
1072 		if ( BG_AnimLength( 0, (animNumber_t)ps->legsAnim ) - ps->legsTimer < 500 )
1073 		{//at beginning of getup anim
1074 			return qtrue;
1075 		}
1076 		break;
1077 	case BOTH_LK_DL_ST_T_SB_1_L:
1078 		if ( ps->legsTimer < 1000 )
1079 		{
1080 			return qtrue;
1081 		}
1082 		break;
1083 	case BOTH_PLAYER_PA_3_FLY:
1084 		if ( ps->legsTimer < 300 )
1085 		{
1086 			return qtrue;
1087 		}
1088 		break;
1089 	}
1090 	return qfalse;
1091 }
1092 
BG_StabDownAnim(int anim)1093 qboolean BG_StabDownAnim( int anim )
1094 {
1095 	switch ( anim )
1096 	{
1097 	case BOTH_STABDOWN:
1098 	case BOTH_STABDOWN_STAFF:
1099 	case BOTH_STABDOWN_DUAL:
1100 		return qtrue;
1101 	}
1102 	return qfalse;
1103 }
1104 
PM_SaberBounceForAttack(int move)1105 int PM_SaberBounceForAttack( int move )
1106 {
1107 	switch ( saberMoveData[move].startQuad )
1108 	{
1109 	case Q_B:
1110 	case Q_BR:
1111 		return LS_B1_BR;
1112 		break;
1113 	case Q_R:
1114 		return LS_B1__R;
1115 		break;
1116 	case Q_TR:
1117 		return LS_B1_TR;
1118 		break;
1119 	case Q_T:
1120 		return LS_B1_T_;
1121 		break;
1122 	case Q_TL:
1123 		return LS_B1_TL;
1124 		break;
1125 	case Q_L:
1126 		return LS_B1__L;
1127 		break;
1128 	case Q_BL:
1129 		return LS_B1_BL;
1130 		break;
1131 	}
1132 	return LS_NONE;
1133 }
1134 
PM_SaberDeflectionForQuad(int quad)1135 int PM_SaberDeflectionForQuad( int quad )
1136 {
1137 	switch ( quad )
1138 	{
1139 	case Q_B:
1140 		return LS_D1_B_;
1141 		break;
1142 	case Q_BR:
1143 		return LS_D1_BR;
1144 		break;
1145 	case Q_R:
1146 		return LS_D1__R;
1147 		break;
1148 	case Q_TR:
1149 		return LS_D1_TR;
1150 		break;
1151 	case Q_T:
1152 		return LS_D1_T_;
1153 		break;
1154 	case Q_TL:
1155 		return LS_D1_TL;
1156 		break;
1157 	case Q_L:
1158 		return LS_D1__L;
1159 		break;
1160 	case Q_BL:
1161 		return LS_D1_BL;
1162 		break;
1163 	}
1164 	return LS_NONE;
1165 }
1166 
PM_SaberInDeflect(int move)1167 qboolean PM_SaberInDeflect( int move )
1168 {
1169 	if ( move >= LS_D1_BR && move <= LS_D1_B_ )
1170 	{
1171 		return qtrue;
1172 	}
1173 	return qfalse;
1174 }
1175 
PM_SaberInParry(int move)1176 qboolean PM_SaberInParry( int move )
1177 {
1178 	if ( move >= LS_PARRY_UP && move <= LS_PARRY_LL )
1179 	{
1180 		return qtrue;
1181 	}
1182 	return qfalse;
1183 }
1184 
PM_SaberInKnockaway(int move)1185 qboolean PM_SaberInKnockaway( int move )
1186 {
1187 	if ( move >= LS_K1_T_ && move <= LS_K1_BL )
1188 	{
1189 		return qtrue;
1190 	}
1191 	return qfalse;
1192 }
1193 
PM_SaberInReflect(int move)1194 qboolean PM_SaberInReflect( int move )
1195 {
1196 	if ( move >= LS_REFLECT_UP && move <= LS_REFLECT_LL )
1197 	{
1198 		return qtrue;
1199 	}
1200 	return qfalse;
1201 }
1202 
PM_SaberInStart(int move)1203 qboolean PM_SaberInStart( int move )
1204 {
1205 	if ( move >= LS_S_TL2BR && move <= LS_S_T2B )
1206 	{
1207 		return qtrue;
1208 	}
1209 	return qfalse;
1210 }
1211 
PM_SaberInReturn(int move)1212 qboolean PM_SaberInReturn( int move )
1213 {
1214 	if ( move >= LS_R_TL2BR && move <= LS_R_T2B )
1215 	{
1216 		return qtrue;
1217 	}
1218 	return qfalse;
1219 }
1220 
BG_SaberInReturn(int move)1221 qboolean BG_SaberInReturn( int move )
1222 {
1223 	return PM_SaberInReturn( move );
1224 }
1225 
PM_InSaberAnim(int anim)1226 qboolean PM_InSaberAnim( int anim )
1227 {
1228 	if ( (anim) >= BOTH_A1_T__B_ && (anim) <= BOTH_H1_S1_BR )
1229 	{
1230 		return qtrue;
1231 	}
1232 	return qfalse;
1233 }
1234 
PM_InKnockDown(playerState_t * ps)1235 qboolean PM_InKnockDown( playerState_t *ps )
1236 {
1237 	switch ( (ps->legsAnim) )
1238 	{
1239 	case BOTH_KNOCKDOWN1:
1240 	case BOTH_KNOCKDOWN2:
1241 	case BOTH_KNOCKDOWN3:
1242 	case BOTH_KNOCKDOWN4:
1243 	case BOTH_KNOCKDOWN5:
1244 		return qtrue;
1245 		break;
1246 	case BOTH_GETUP1:
1247 	case BOTH_GETUP2:
1248 	case BOTH_GETUP3:
1249 	case BOTH_GETUP4:
1250 	case BOTH_GETUP5:
1251 	case BOTH_FORCE_GETUP_F1:
1252 	case BOTH_FORCE_GETUP_F2:
1253 	case BOTH_FORCE_GETUP_B1:
1254 	case BOTH_FORCE_GETUP_B2:
1255 	case BOTH_FORCE_GETUP_B3:
1256 	case BOTH_FORCE_GETUP_B4:
1257 	case BOTH_FORCE_GETUP_B5:
1258 	case BOTH_GETUP_BROLL_B:
1259 	case BOTH_GETUP_BROLL_F:
1260 	case BOTH_GETUP_BROLL_L:
1261 	case BOTH_GETUP_BROLL_R:
1262 	case BOTH_GETUP_FROLL_B:
1263 	case BOTH_GETUP_FROLL_F:
1264 	case BOTH_GETUP_FROLL_L:
1265 	case BOTH_GETUP_FROLL_R:
1266 		if ( ps->legsTimer )
1267 		{
1268 			return qtrue;
1269 		}
1270 		break;
1271 	}
1272 	return qfalse;
1273 }
1274 
PM_PainAnim(int anim)1275 qboolean PM_PainAnim( int anim )
1276 {
1277 	switch ( (anim) )
1278 	{
1279 		case BOTH_PAIN1:				//# First take pain anim
1280 		case BOTH_PAIN2:				//# Second take pain anim
1281 		case BOTH_PAIN3:				//# Third take pain anim
1282 		case BOTH_PAIN4:				//# Fourth take pain anim
1283 		case BOTH_PAIN5:				//# Fifth take pain anim - from behind
1284 		case BOTH_PAIN6:				//# Sixth take pain anim - from behind
1285 		case BOTH_PAIN7:				//# Seventh take pain anim - from behind
1286 		case BOTH_PAIN8:				//# Eigth take pain anim - from behind
1287 		case BOTH_PAIN9:				//#
1288 		case BOTH_PAIN10:			//#
1289 		case BOTH_PAIN11:			//#
1290 		case BOTH_PAIN12:			//#
1291 		case BOTH_PAIN13:			//#
1292 		case BOTH_PAIN14:			//#
1293 		case BOTH_PAIN15:			//#
1294 		case BOTH_PAIN16:			//#
1295 		case BOTH_PAIN17:			//#
1296 		case BOTH_PAIN18:			//#
1297 		return qtrue;
1298 		break;
1299 	}
1300 	return qfalse;
1301 }
1302 
PM_JumpingAnim(int anim)1303 qboolean PM_JumpingAnim( int anim )
1304 {
1305 	switch ( (anim) )
1306 	{
1307 		case BOTH_JUMP1:				//# Jump - wind-up and leave ground
1308 		case BOTH_INAIR1:			//# In air loop (from jump)
1309 		case BOTH_LAND1:				//# Landing (from in air loop)
1310 		case BOTH_LAND2:				//# Landing Hard (from a great height)
1311 		case BOTH_JUMPBACK1:			//# Jump backwards - wind-up and leave ground
1312 		case BOTH_INAIRBACK1:		//# In air loop (from jump back)
1313 		case BOTH_LANDBACK1:			//# Landing backwards(from in air loop)
1314 		case BOTH_JUMPLEFT1:			//# Jump left - wind-up and leave ground
1315 		case BOTH_INAIRLEFT1:		//# In air loop (from jump left)
1316 		case BOTH_LANDLEFT1:			//# Landing left(from in air loop)
1317 		case BOTH_JUMPRIGHT1:		//# Jump right - wind-up and leave ground
1318 		case BOTH_INAIRRIGHT1:		//# In air loop (from jump right)
1319 		case BOTH_LANDRIGHT1:		//# Landing right(from in air loop)
1320 		case BOTH_FORCEJUMP1:				//# Jump - wind-up and leave ground
1321 		case BOTH_FORCEINAIR1:			//# In air loop (from jump)
1322 		case BOTH_FORCELAND1:				//# Landing (from in air loop)
1323 		case BOTH_FORCEJUMPBACK1:			//# Jump backwards - wind-up and leave ground
1324 		case BOTH_FORCEINAIRBACK1:		//# In air loop (from jump back)
1325 		case BOTH_FORCELANDBACK1:			//# Landing backwards(from in air loop)
1326 		case BOTH_FORCEJUMPLEFT1:			//# Jump left - wind-up and leave ground
1327 		case BOTH_FORCEINAIRLEFT1:		//# In air loop (from jump left)
1328 		case BOTH_FORCELANDLEFT1:			//# Landing left(from in air loop)
1329 		case BOTH_FORCEJUMPRIGHT1:		//# Jump right - wind-up and leave ground
1330 		case BOTH_FORCEINAIRRIGHT1:		//# In air loop (from jump right)
1331 		case BOTH_FORCELANDRIGHT1:		//# Landing right(from in air loop)
1332 		return qtrue;
1333 		break;
1334 	}
1335 	return qfalse;
1336 }
1337 
PM_LandingAnim(int anim)1338 qboolean PM_LandingAnim( int anim )
1339 {
1340 	switch ( (anim) )
1341 	{
1342 		case BOTH_LAND1:				//# Landing (from in air loop)
1343 		case BOTH_LAND2:				//# Landing Hard (from a great height)
1344 		case BOTH_LANDBACK1:			//# Landing backwards(from in air loop)
1345 		case BOTH_LANDLEFT1:			//# Landing left(from in air loop)
1346 		case BOTH_LANDRIGHT1:		//# Landing right(from in air loop)
1347 		case BOTH_FORCELAND1:		//# Landing (from in air loop)
1348 		case BOTH_FORCELANDBACK1:	//# Landing backwards(from in air loop)
1349 		case BOTH_FORCELANDLEFT1:	//# Landing left(from in air loop)
1350 		case BOTH_FORCELANDRIGHT1:	//# Landing right(from in air loop)
1351 		return qtrue;
1352 		break;
1353 	}
1354 	return qfalse;
1355 }
1356 
PM_SpinningAnim(int anim)1357 qboolean PM_SpinningAnim( int anim )
1358 {
1359 	/*
1360 	switch ( anim )
1361 	{
1362 	//FIXME: list any other spinning anims
1363 	default:
1364 		break;
1365 	}
1366 	*/
1367 	return BG_SpinningSaberAnim( anim );
1368 }
1369 
PM_InOnGroundAnim(int anim)1370 qboolean PM_InOnGroundAnim ( int anim )
1371 {
1372 	switch( anim )
1373 	{
1374 	case BOTH_DEAD1:
1375 	case BOTH_DEAD2:
1376 	case BOTH_DEAD3:
1377 	case BOTH_DEAD4:
1378 	case BOTH_DEAD5:
1379 	case BOTH_DEADFORWARD1:
1380 	case BOTH_DEADBACKWARD1:
1381 	case BOTH_DEADFORWARD2:
1382 	case BOTH_DEADBACKWARD2:
1383 	case BOTH_LYINGDEATH1:
1384 	case BOTH_LYINGDEAD1:
1385 	case BOTH_SLEEP1:			//# laying on back-rknee up-rhand on torso
1386 	case BOTH_KNOCKDOWN1:		//#
1387 	case BOTH_KNOCKDOWN2:		//#
1388 	case BOTH_KNOCKDOWN3:		//#
1389 	case BOTH_KNOCKDOWN4:		//#
1390 	case BOTH_KNOCKDOWN5:		//#
1391 	case BOTH_GETUP1:
1392 	case BOTH_GETUP2:
1393 	case BOTH_GETUP3:
1394 	case BOTH_GETUP4:
1395 	case BOTH_GETUP5:
1396 	case BOTH_GETUP_CROUCH_F1:
1397 	case BOTH_GETUP_CROUCH_B1:
1398 	case BOTH_FORCE_GETUP_F1:
1399 	case BOTH_FORCE_GETUP_F2:
1400 	case BOTH_FORCE_GETUP_B1:
1401 	case BOTH_FORCE_GETUP_B2:
1402 	case BOTH_FORCE_GETUP_B3:
1403 	case BOTH_FORCE_GETUP_B4:
1404 	case BOTH_FORCE_GETUP_B5:
1405 	case BOTH_FORCE_GETUP_B6:
1406 	case BOTH_GETUP_BROLL_B:
1407 	case BOTH_GETUP_BROLL_F:
1408 	case BOTH_GETUP_BROLL_L:
1409 	case BOTH_GETUP_BROLL_R:
1410 	case BOTH_GETUP_FROLL_B:
1411 	case BOTH_GETUP_FROLL_F:
1412 	case BOTH_GETUP_FROLL_L:
1413 	case BOTH_GETUP_FROLL_R:
1414 		return qtrue;
1415 		break;
1416 	}
1417 
1418 	return qfalse;
1419 }
1420 
PM_InRollComplete(playerState_t * ps,int anim)1421 qboolean PM_InRollComplete( playerState_t *ps, int anim )
1422 {
1423 	switch ( (anim) )
1424 	{
1425 	case BOTH_ROLL_F:
1426 	case BOTH_ROLL_B:
1427 	case BOTH_ROLL_R:
1428 	case BOTH_ROLL_L:
1429 		if ( ps->legsTimer < 1 )
1430 		{
1431 			return qtrue;
1432 		}
1433 		break;
1434 	}
1435 	return qfalse;
1436 }
1437 
PM_CanRollFromSoulCal(playerState_t * ps)1438 qboolean PM_CanRollFromSoulCal( playerState_t *ps )
1439 {
1440 	if ( ps->legsAnim == BOTH_A7_SOULCAL
1441 		&& ps->legsTimer < 700
1442 		&& ps->legsTimer > 250 )
1443 	{
1444 		return qtrue;
1445 	}
1446 	return qfalse;
1447 }
1448 
BG_SuperBreakLoseAnim(int anim)1449 qboolean BG_SuperBreakLoseAnim( int anim )
1450 {
1451 	switch ( anim )
1452 	{
1453 	case BOTH_LK_S_DL_S_SB_1_L:	//super break I lost
1454 	case BOTH_LK_S_DL_T_SB_1_L:	//super break I lost
1455 	case BOTH_LK_S_ST_S_SB_1_L:	//super break I lost
1456 	case BOTH_LK_S_ST_T_SB_1_L:	//super break I lost
1457 	case BOTH_LK_S_S_S_SB_1_L:	//super break I lost
1458 	case BOTH_LK_S_S_T_SB_1_L:	//super break I lost
1459 	case BOTH_LK_DL_DL_S_SB_1_L:	//super break I lost
1460 	case BOTH_LK_DL_DL_T_SB_1_L:	//super break I lost
1461 	case BOTH_LK_DL_ST_S_SB_1_L:	//super break I lost
1462 	case BOTH_LK_DL_ST_T_SB_1_L:	//super break I lost
1463 	case BOTH_LK_DL_S_S_SB_1_L:	//super break I lost
1464 	case BOTH_LK_DL_S_T_SB_1_L:	//super break I lost
1465 	case BOTH_LK_ST_DL_S_SB_1_L:	//super break I lost
1466 	case BOTH_LK_ST_DL_T_SB_1_L:	//super break I lost
1467 	case BOTH_LK_ST_ST_S_SB_1_L:	//super break I lost
1468 	case BOTH_LK_ST_ST_T_SB_1_L:	//super break I lost
1469 	case BOTH_LK_ST_S_S_SB_1_L:	//super break I lost
1470 	case BOTH_LK_ST_S_T_SB_1_L:	//super break I lost
1471 		return qtrue;
1472 		break;
1473 	}
1474 	return qfalse;
1475 }
1476 
BG_SuperBreakWinAnim(int anim)1477 qboolean BG_SuperBreakWinAnim( int anim )
1478 {
1479 	switch ( anim )
1480 	{
1481 	case BOTH_LK_S_DL_S_SB_1_W:	//super break I won
1482 	case BOTH_LK_S_DL_T_SB_1_W:	//super break I won
1483 	case BOTH_LK_S_ST_S_SB_1_W:	//super break I won
1484 	case BOTH_LK_S_ST_T_SB_1_W:	//super break I won
1485 	case BOTH_LK_S_S_S_SB_1_W:	//super break I won
1486 	case BOTH_LK_S_S_T_SB_1_W:	//super break I won
1487 	case BOTH_LK_DL_DL_S_SB_1_W:	//super break I won
1488 	case BOTH_LK_DL_DL_T_SB_1_W:	//super break I won
1489 	case BOTH_LK_DL_ST_S_SB_1_W:	//super break I won
1490 	case BOTH_LK_DL_ST_T_SB_1_W:	//super break I won
1491 	case BOTH_LK_DL_S_S_SB_1_W:	//super break I won
1492 	case BOTH_LK_DL_S_T_SB_1_W:	//super break I won
1493 	case BOTH_LK_ST_DL_S_SB_1_W:	//super break I won
1494 	case BOTH_LK_ST_DL_T_SB_1_W:	//super break I won
1495 	case BOTH_LK_ST_ST_S_SB_1_W:	//super break I won
1496 	case BOTH_LK_ST_ST_T_SB_1_W:	//super break I won
1497 	case BOTH_LK_ST_S_S_SB_1_W:	//super break I won
1498 	case BOTH_LK_ST_S_T_SB_1_W:	//super break I won
1499 		return qtrue;
1500 		break;
1501 	}
1502 	return qfalse;
1503 }
1504 
1505 
BG_SaberLockBreakAnim(int anim)1506 qboolean BG_SaberLockBreakAnim( int anim )
1507 {
1508 	switch ( anim )
1509 	{
1510 	case BOTH_BF1BREAK:
1511 	case BOTH_BF2BREAK:
1512 	case BOTH_CWCIRCLEBREAK:
1513 	case BOTH_CCWCIRCLEBREAK:
1514 	case BOTH_LK_S_DL_S_B_1_L:	//normal break I lost
1515 	case BOTH_LK_S_DL_S_B_1_W:	//normal break I won
1516 	case BOTH_LK_S_DL_T_B_1_L:	//normal break I lost
1517 	case BOTH_LK_S_DL_T_B_1_W:	//normal break I won
1518 	case BOTH_LK_S_ST_S_B_1_L:	//normal break I lost
1519 	case BOTH_LK_S_ST_S_B_1_W:	//normal break I won
1520 	case BOTH_LK_S_ST_T_B_1_L:	//normal break I lost
1521 	case BOTH_LK_S_ST_T_B_1_W:	//normal break I won
1522 	case BOTH_LK_S_S_S_B_1_L:	//normal break I lost
1523 	case BOTH_LK_S_S_S_B_1_W:	//normal break I won
1524 	case BOTH_LK_S_S_T_B_1_L:	//normal break I lost
1525 	case BOTH_LK_S_S_T_B_1_W:	//normal break I won
1526 	case BOTH_LK_DL_DL_S_B_1_L:	//normal break I lost
1527 	case BOTH_LK_DL_DL_S_B_1_W:	//normal break I won
1528 	case BOTH_LK_DL_DL_T_B_1_L:	//normal break I lost
1529 	case BOTH_LK_DL_DL_T_B_1_W:	//normal break I won
1530 	case BOTH_LK_DL_ST_S_B_1_L:	//normal break I lost
1531 	case BOTH_LK_DL_ST_S_B_1_W:	//normal break I won
1532 	case BOTH_LK_DL_ST_T_B_1_L:	//normal break I lost
1533 	case BOTH_LK_DL_ST_T_B_1_W:	//normal break I won
1534 	case BOTH_LK_DL_S_S_B_1_L:	//normal break I lost
1535 	case BOTH_LK_DL_S_S_B_1_W:	//normal break I won
1536 	case BOTH_LK_DL_S_T_B_1_L:	//normal break I lost
1537 	case BOTH_LK_DL_S_T_B_1_W:	//normal break I won
1538 	case BOTH_LK_ST_DL_S_B_1_L:	//normal break I lost
1539 	case BOTH_LK_ST_DL_S_B_1_W:	//normal break I won
1540 	case BOTH_LK_ST_DL_T_B_1_L:	//normal break I lost
1541 	case BOTH_LK_ST_DL_T_B_1_W:	//normal break I won
1542 	case BOTH_LK_ST_ST_S_B_1_L:	//normal break I lost
1543 	case BOTH_LK_ST_ST_S_B_1_W:	//normal break I won
1544 	case BOTH_LK_ST_ST_T_B_1_L:	//normal break I lost
1545 	case BOTH_LK_ST_ST_T_B_1_W:	//normal break I won
1546 	case BOTH_LK_ST_S_S_B_1_L:	//normal break I lost
1547 	case BOTH_LK_ST_S_S_B_1_W:	//normal break I won
1548 	case BOTH_LK_ST_S_T_B_1_L:	//normal break I lost
1549 	case BOTH_LK_ST_S_T_B_1_W:	//normal break I won
1550 		return qtrue;
1551 		break;
1552 	}
1553 	return (BG_SuperBreakLoseAnim(anim)||BG_SuperBreakWinAnim(anim));
1554 }
1555 
1556 
BG_FullBodyTauntAnim(int anim)1557 qboolean BG_FullBodyTauntAnim( int anim )
1558 {
1559 	switch ( anim )
1560 	{
1561 	case BOTH_GESTURE1:
1562 	case BOTH_DUAL_TAUNT:
1563 	case BOTH_STAFF_TAUNT:
1564 	case BOTH_BOW:
1565 	case BOTH_MEDITATE:
1566 	case BOTH_SHOWOFF_FAST:
1567 	case BOTH_SHOWOFF_MEDIUM:
1568 	case BOTH_SHOWOFF_STRONG:
1569 	case BOTH_SHOWOFF_DUAL:
1570 	case BOTH_SHOWOFF_STAFF:
1571 	case BOTH_VICTORY_FAST:
1572 	case BOTH_VICTORY_MEDIUM:
1573 	case BOTH_VICTORY_STRONG:
1574 	case BOTH_VICTORY_DUAL:
1575 	case BOTH_VICTORY_STAFF:
1576 		return qtrue;
1577 		break;
1578 	}
1579 	return qfalse;
1580 }
1581 
1582 
1583 /*
1584 =============
1585 BG_AnimLength
1586 
1587 Get the "length" of an anim given the local anim index (which skeleton)
1588 and anim number. Obviously does not take things like the length of the
1589 anim while force speeding (as an example) and whatnot into account.
1590 =============
1591 */
BG_AnimLength(int index,animNumber_t anim)1592 int BG_AnimLength( int index, animNumber_t anim ) {
1593 	if ( (int)anim < 0 || anim >= MAX_ANIMATIONS ) {
1594 		return 0;
1595 	}
1596 
1597 	return bgAllAnims[index].anims[anim].numFrames * fabs( (float)(bgAllAnims[index].anims[anim].frameLerp) );
1598 }
1599 
1600 //just use whatever pm->animations is
PM_AnimLength(int index,animNumber_t anim)1601 int PM_AnimLength( int index, animNumber_t anim ) {
1602 	if ( !pm->animations || (int)anim < 0 || anim >= MAX_ANIMATIONS ) {
1603 		return 0;
1604 	}
1605 
1606 	return pm->animations[anim].numFrames * fabs( (float)(pm->animations[anim].frameLerp) );
1607 }
1608 
PM_DebugLegsAnim(int anim)1609 void PM_DebugLegsAnim(int anim)
1610 {
1611 	int oldAnim = (pm->ps->legsAnim);
1612 	int newAnim = (anim);
1613 
1614 	if (oldAnim < MAX_TOTALANIMATIONS && oldAnim >= BOTH_DEATH1 &&
1615 		newAnim < MAX_TOTALANIMATIONS && newAnim >= BOTH_DEATH1)
1616 	{
1617 		Com_Printf("OLD: %s\n", animTable[oldAnim]);
1618 		Com_Printf("NEW: %s\n", animTable[newAnim]);
1619 	}
1620 }
1621 
PM_SaberInTransition(int move)1622 qboolean PM_SaberInTransition( int move )
1623 {
1624 	if ( move >= LS_T1_BR__R && move <= LS_T1_BL__L )
1625 	{
1626 		return qtrue;
1627 	}
1628 	return qfalse;
1629 }
1630 
BG_SaberInTransitionAny(int move)1631 qboolean BG_SaberInTransitionAny( int move )
1632 {
1633 	if ( PM_SaberInStart( move ) )
1634 	{
1635 		return qtrue;
1636 	}
1637 	else if ( PM_SaberInTransition( move ) )
1638 	{
1639 		return qtrue;
1640 	}
1641 	else if ( PM_SaberInReturn( move ) )
1642 	{
1643 		return qtrue;
1644 	}
1645 	return qfalse;
1646 }
1647 
1648 /*
1649 ==============================================================================
1650 END: Animation utility functions (sequence checking)
1651 ==============================================================================
1652 */
1653 
BG_FlipPart(playerState_t * ps,int part)1654 void BG_FlipPart(playerState_t *ps, int part)
1655 {
1656 	if (part == SETANIM_TORSO)
1657 	{
1658 		if (ps->torsoFlip)
1659 		{
1660 			ps->torsoFlip = qfalse;
1661 		}
1662 		else
1663 		{
1664 			ps->torsoFlip = qtrue;
1665 		}
1666 	}
1667 	else if (part == SETANIM_LEGS)
1668 	{
1669 		if (ps->legsFlip)
1670 		{
1671 			ps->legsFlip = qfalse;
1672 		}
1673 		else
1674 		{
1675 			ps->legsFlip = qtrue;
1676 		}
1677 	}
1678 }
1679 
1680 qboolean	BGPAFtextLoaded = qfalse;
1681 animation_t	bgHumanoidAnimations[MAX_TOTALANIMATIONS]; //humanoid animations are the only ones that are statically allocated.
1682 
1683 bgLoadedAnim_t bgAllAnims[MAX_ANIM_FILES];
1684 int bgNumAllAnims = 2; //start off at 2, because 0 will always be assigned to humanoid, and 1 will always be rockettrooper
1685 
1686 //ALWAYS call on game/cgame init
BG_InitAnimsets(void)1687 void BG_InitAnimsets(void)
1688 {
1689 	memset(&bgAllAnims, 0, sizeof(bgAllAnims));
1690 	BGPAFtextLoaded = qfalse;	// VVFIXME - The PC doesn't seem to need this, but why?
1691 }
1692 
1693 //ALWAYS call on game/cgame shutdown
BG_ClearAnimsets(void)1694 void BG_ClearAnimsets(void)
1695 {
1696 	/*
1697 	int i = 1;
1698 
1699 	while (i < bgNumAllAnims)
1700 	{
1701 		if (bgAllAnims[i].anims)
1702 		{
1703 			strap_TrueFree((void **)&bgAllAnims[i].anims);
1704 		}
1705 		i++;
1706 	}
1707 	*/
1708 }
1709 
BG_AnimsetAlloc(void)1710 animation_t *BG_AnimsetAlloc(void)
1711 {
1712 	assert (bgNumAllAnims < MAX_ANIM_FILES);
1713 	bgAllAnims[bgNumAllAnims].anims = (animation_t *) BG_Alloc(sizeof(animation_t)*MAX_TOTALANIMATIONS);
1714 
1715 	return bgAllAnims[bgNumAllAnims].anims;
1716 }
1717 
BG_AnimsetFree(animation_t * animset)1718 void BG_AnimsetFree(animation_t *animset)
1719 {
1720 	/*
1721 	if (!animset)
1722 	{
1723 		return;
1724 	}
1725 
1726 	strap_TrueFree((void **)&animset);
1727 
1728 #ifdef _DEBUG
1729 	if (animset)
1730 	{
1731 		assert(!"Failed to free anim set");
1732 	}
1733 #endif
1734 	*/
1735 }
1736 
1737 #ifdef _CGAME //none of this is actually needed serverside. Could just be moved to cgame code but it's here since it used to tie in a lot with the anim loading stuff.
1738 stringID_table_t animEventTypeTable[MAX_ANIM_EVENTS+1] =
1739 {
1740 	ENUM2STRING(AEV_SOUND),			//# animID AEV_SOUND framenum soundpath randomlow randomhi chancetoplay
1741 	ENUM2STRING(AEV_FOOTSTEP),		//# animID AEV_FOOTSTEP framenum footstepType
1742 	ENUM2STRING(AEV_EFFECT),		//# animID AEV_EFFECT framenum effectpath boltName
1743 	ENUM2STRING(AEV_FIRE),			//# animID AEV_FIRE framenum altfire chancetofire
1744 	ENUM2STRING(AEV_MOVE),			//# animID AEV_MOVE framenum forwardpush rightpush uppush
1745 	ENUM2STRING(AEV_SOUNDCHAN),		//# animID AEV_SOUNDCHAN framenum CHANNEL soundpath randomlow randomhi chancetoplay
1746 	ENUM2STRING(AEV_SABER_SWING),	//# animID AEV_SABER_SWING framenum CHANNEL randomlow randomhi chancetoplay
1747 	ENUM2STRING(AEV_SABER_SPIN),	//# animID AEV_SABER_SPIN framenum CHANNEL chancetoplay
1748 	//must be terminated
1749 	{ NULL,-1 }
1750 };
1751 
1752 stringID_table_t footstepTypeTable[NUM_FOOTSTEP_TYPES+1] =
1753 {
1754 	ENUM2STRING(FOOTSTEP_R),
1755 	ENUM2STRING(FOOTSTEP_L),
1756 	ENUM2STRING(FOOTSTEP_HEAVY_R),
1757 	ENUM2STRING(FOOTSTEP_HEAVY_L),
1758 	//must be terminated
1759 	{ NULL,-1 }
1760 };
1761 
CheckAnimFrameForEventType(animevent_t * animEvents,int keyFrame,animEventType_t eventType)1762 int CheckAnimFrameForEventType( animevent_t *animEvents, int keyFrame, animEventType_t eventType )
1763 {
1764 	int i;
1765 
1766 	for ( i = 0; i < MAX_ANIM_EVENTS; i++ )
1767 	{
1768 		if ( animEvents[i].keyFrame == keyFrame )
1769 		{//there is an animevent on this frame already
1770 			if ( animEvents[i].eventType == eventType )
1771 			{//and it is of the same type
1772 				return i;
1773 			}
1774 		}
1775 	}
1776 	//nope
1777 	return -1;
1778 }
1779 
ParseAnimationEvtBlock(const char * aeb_filename,animevent_t * animEvents,animation_t * animations,int * i,const char ** text_p)1780 void ParseAnimationEvtBlock(const char *aeb_filename, animevent_t *animEvents, animation_t *animations, int *i,const char **text_p)
1781 {
1782 	const char		*token;
1783 	int				num, n, animNum, keyFrame, lowestVal, highestVal, curAnimEvent, lastAnimEvent = 0;
1784 	animEventType_t	eventType;
1785 	char			stringData[MAX_QPATH];
1786 
1787 	// get past starting bracket
1788 	while(1)
1789 	{
1790 		token = COM_Parse( text_p );
1791 		if ( !Q_stricmp( token, "{" ) )
1792 		{
1793 			break;
1794 		}
1795 	}
1796 
1797 	//NOTE: instead of a blind increment, increase the index
1798 	//			this way if we have an event on an anim that already
1799 	//			has an event of that type, it stomps it
1800 
1801 	// read information for each frame
1802 	while ( 1 )
1803 	{
1804 		if ( lastAnimEvent >= MAX_ANIM_EVENTS )
1805 		{
1806 			Com_Error( ERR_DROP, "ParseAnimationEvtBlock: number events in animEvent file %s > MAX_ANIM_EVENTS(%i)", aeb_filename, MAX_ANIM_EVENTS );
1807 			return;
1808 		}
1809 		// Get base frame of sequence
1810 		token = COM_Parse( text_p );
1811 		if ( !token || !token[0])
1812 		{
1813 			break;
1814 		}
1815 
1816 		if ( !Q_stricmp( token, "}" ) )		// At end of block
1817 		{
1818 			break;
1819 		}
1820 
1821 		//Compare to same table as animations used
1822 		//	so we don't have to use actual numbers for animation first frames,
1823 		//	just need offsets.
1824 		//This way when animation numbers change, this table won't have to be updated,
1825 		//	at least not much.
1826 		animNum = GetIDForString(animTable, token);
1827 		if(animNum == -1)
1828 		{//Unrecognized ANIM ENUM name, or we're skipping this line, keep going till you get a good one
1829 			Com_Printf(S_COLOR_YELLOW"WARNING: Unknown token %s in animEvent file %s\n", token, aeb_filename );
1830 			while (token[0])
1831 			{
1832 				token = COM_ParseExt( text_p, qfalse );	//returns empty string when next token is EOL
1833 			}
1834 			continue;
1835 		}
1836 
1837 		if ( animations[animNum].numFrames == 0 )
1838 		{//we don't use this anim
1839 			Com_Printf(S_COLOR_YELLOW"WARNING: %s animevents.cfg: anim %s not used by this model\n", aeb_filename, token);
1840 			//skip this entry
1841 			SkipRestOfLine( text_p );
1842 			continue;
1843 		}
1844 
1845 		token = COM_Parse( text_p );
1846 		eventType = (animEventType_t)GetIDForString(animEventTypeTable, token);
1847 		if ( eventType == AEV_NONE || eventType == (animEventType_t)-1 )
1848 		{//Unrecognized ANIM EVENT TYOE, or we're skipping this line, keep going till you get a good one
1849 			//Com_Printf(S_COLOR_YELLOW"WARNING: Unknown token %s in animEvent file %s\n", token, aeb_filename );
1850 			continue;
1851 		}
1852 
1853 		//set our start frame
1854 		keyFrame = animations[animNum].firstFrame;
1855 		// Get offset to frame within sequence
1856 		token = COM_Parse( text_p );
1857 		if ( !token )
1858 		{
1859 			break;
1860 		}
1861 		keyFrame += atoi( token );
1862 
1863 		//see if this frame already has an event of this type on it, if so, overwrite it
1864 		curAnimEvent = CheckAnimFrameForEventType( animEvents, keyFrame, eventType );
1865 		if ( curAnimEvent == -1 )
1866 		{//this anim frame doesn't already have an event of this type on it
1867 			curAnimEvent = lastAnimEvent;
1868 		}
1869 
1870 		//now that we know which event index we're going to plug the data into, start doing it
1871 		animEvents[curAnimEvent].eventType = eventType;
1872 		animEvents[curAnimEvent].keyFrame = keyFrame;
1873 
1874 		//now read out the proper data based on the type
1875 		switch ( animEvents[curAnimEvent].eventType )
1876 		{
1877 		case AEV_SOUNDCHAN:		//# animID AEV_SOUNDCHAN framenum CHANNEL soundpath randomlow randomhi chancetoplay
1878 			token = COM_Parse( text_p );
1879 			if ( !token )
1880 				break;
1881 
1882 				 if ( !Q_stricmp( token, "CHAN_VOICE_ATTEN" ) )
1883 				animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_VOICE_ATTEN;
1884 			else if ( !Q_stricmp( token, "CHAN_VOICE_GLOBAL" ) )
1885 				animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_VOICE_GLOBAL;
1886 			else if ( !Q_stricmp( token, "CHAN_ANNOUNCER" ) )
1887 				animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_ANNOUNCER;
1888 			else if ( !Q_stricmp( token, "CHAN_BODY" ) )
1889 				animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_BODY;
1890 			else if ( !Q_stricmp( token, "CHAN_WEAPON" ) )
1891 				animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_WEAPON;
1892 			else if ( !Q_stricmp( token, "CHAN_VOICE" ) )
1893 				animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_VOICE;
1894 			else
1895 				animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_AUTO;
1896 
1897 			//fall through to normal sound
1898 		case AEV_SOUND:			//# animID AEV_SOUND framenum soundpath randomlow randomhi chancetoplay
1899 			//get soundstring
1900 			token = COM_Parse( text_p );
1901 			if ( !token )
1902 			{
1903 				break;
1904 			}
1905 			strcpy(stringData, token);
1906 			//get lowest value
1907 			token = COM_Parse( text_p );
1908 			if ( !token )
1909 			{//WARNING!  BAD TABLE!
1910 				break;
1911 			}
1912 			lowestVal = atoi( token );
1913 			//get highest value
1914 			token = COM_Parse( text_p );
1915 			if ( !token )
1916 			{//WARNING!  BAD TABLE!
1917 				break;
1918 			}
1919 			highestVal = atoi( token );
1920 			//Now precache all the sounds
1921 			//NOTE: If we can be assured sequential handles, we can store sound indices
1922 			//		instead of strings, unfortunately, if these sounds were previously
1923 			//		registered, we cannot be guaranteed sequential indices.  Thus an array
1924 			if(lowestVal && highestVal)
1925 			{
1926 				//assert(highestVal - lowestVal < MAX_RANDOM_ANIM_SOUNDS);
1927 				if ((highestVal-lowestVal) >= MAX_RANDOM_ANIM_SOUNDS)
1928 				{
1929 					highestVal = lowestVal + (MAX_RANDOM_ANIM_SOUNDS-1);
1930 				}
1931 				for ( n = lowestVal, num = AED_SOUNDINDEX_START; n <= highestVal && num <= AED_SOUNDINDEX_END; n++, num++ )
1932 				{
1933 					if (stringData[0] == '*')
1934 					{ //FIXME? Would be nice to make custom sounds work with animEvents.
1935 						animEvents[curAnimEvent].eventData[num] = 0;
1936 					}
1937 					else
1938 					{
1939 						animEvents[curAnimEvent].eventData[num] = trap->S_RegisterSound( va( stringData, n ) );
1940 					}
1941 				}
1942 				animEvents[curAnimEvent].eventData[AED_SOUND_NUMRANDOMSNDS] = num - 1;
1943 			}
1944 			else
1945 			{
1946 				if (stringData[0] == '*')
1947 				{ //FIXME? Would be nice to make custom sounds work with animEvents.
1948 					animEvents[curAnimEvent].eventData[AED_SOUNDINDEX_START] = 0;
1949 				}
1950 				else
1951 				{
1952 					animEvents[curAnimEvent].eventData[AED_SOUNDINDEX_START] = trap->S_RegisterSound( stringData );
1953 				}
1954 #ifndef FINAL_BUILD
1955 				if ( !animEvents[curAnimEvent].eventData[AED_SOUNDINDEX_START] &&
1956 					 stringData[0] != '*')
1957 				{//couldn't register it - file not found
1958 					Com_Printf( S_COLOR_RED "ParseAnimationSndBlock: sound %s does not exist (animevents.cfg %s)!\n", stringData, aeb_filename );
1959 				}
1960 #endif
1961 				animEvents[curAnimEvent].eventData[AED_SOUND_NUMRANDOMSNDS] = 0;
1962 			}
1963 			//get probability
1964 			token = COM_Parse( text_p );
1965 			if ( !token )
1966 			{//WARNING!  BAD TABLE!
1967 				break;
1968 			}
1969 			animEvents[curAnimEvent].eventData[AED_SOUND_PROBABILITY] = atoi( token );
1970 
1971 			//last part - cheat and check and see if it's a special overridable saber sound we know of...
1972 			if ( !Q_stricmpn( "sound/weapons/saber/saberhup", stringData, 28 ) )
1973 			{//a saber swing
1974 				animEvents[curAnimEvent].eventType = AEV_SABER_SWING;
1975 				animEvents[curAnimEvent].eventData[AED_SABER_SWING_SABERNUM] = 0;//since we don't know which one they meant if we're hacking this, always use first saber
1976 				animEvents[curAnimEvent].eventData[AED_SABER_SWING_PROBABILITY] = animEvents[curAnimEvent].eventData[AED_SOUND_PROBABILITY];
1977 				if ( lowestVal < 4 )
1978 				{//fast swing
1979 					animEvents[curAnimEvent].eventData[AED_SABER_SWING_TYPE] = 0;//SWING_FAST;
1980 				}
1981 				else if ( lowestVal < 7 )
1982 				{//medium swing
1983 					animEvents[curAnimEvent].eventData[AED_SABER_SWING_TYPE] = 1;//SWING_MEDIUM;
1984 				}
1985 				else
1986 				{//strong swing
1987 					animEvents[curAnimEvent].eventData[AED_SABER_SWING_TYPE] = 2;//SWING_STRONG;
1988 				}
1989 			}
1990 			else if ( !Q_stricmpn( "sound/weapons/saber/saberspin", stringData, 29 ) )
1991 			{//a saber spin
1992 				animEvents[curAnimEvent].eventType = AEV_SABER_SPIN;
1993 				animEvents[curAnimEvent].eventData[AED_SABER_SPIN_SABERNUM] = 0;//since we don't know which one they meant if we're hacking this, always use first saber
1994 				animEvents[curAnimEvent].eventData[AED_SABER_SPIN_PROBABILITY] = animEvents[curAnimEvent].eventData[AED_SOUND_PROBABILITY];
1995 				if ( stringData[29] == 'o' )
1996 				{//saberspinoff
1997 					animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 0;
1998 				}
1999 				else if ( stringData[29] == '1' )
2000 				{//saberspin1
2001 					animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 2;
2002 				}
2003 				else if ( stringData[29] == '2' )
2004 				{//saberspin2
2005 					animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 3;
2006 				}
2007 				else if ( stringData[29] == '3' )
2008 				{//saberspin3
2009 					animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 4;
2010 				}
2011 				else if ( stringData[29] == '%' )
2012 				{//saberspin%d
2013 					animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 5;
2014 				}
2015 				else
2016 				{//just plain saberspin
2017 					animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 1;
2018 				}
2019 			}
2020 			break;
2021 		case AEV_FOOTSTEP:		//# animID AEV_FOOTSTEP framenum footstepType
2022 			//get footstep type
2023 			token = COM_Parse( text_p );
2024 			if ( !token )
2025 			{
2026 				break;
2027 			}
2028 			animEvents[curAnimEvent].eventData[AED_FOOTSTEP_TYPE] = GetIDForString(footstepTypeTable, token);
2029 			//get probability
2030 			token = COM_Parse( text_p );
2031 			if ( !token )
2032 			{//WARNING!  BAD TABLE!
2033 				break;
2034 			}
2035 			animEvents[curAnimEvent].eventData[AED_FOOTSTEP_PROBABILITY] = atoi( token );
2036 			break;
2037 		case AEV_EFFECT:		//# animID AEV_EFFECT framenum effectpath boltName
2038 			//get effect index
2039 			token = COM_Parse( text_p );
2040 			if ( !token )
2041 			{
2042 				break;
2043 			}
2044 			animEvents[curAnimEvent].eventData[AED_EFFECTINDEX] = trap->FX_RegisterEffect( token );
2045 			//get bolt index
2046 			token = COM_Parse( text_p );
2047 			if ( !token )
2048 			{
2049 				break;
2050 			}
2051 			if ( Q_stricmp( "none", token ) != 0 && Q_stricmp( "NULL", token ) != 0 )
2052 			{//actually are specifying a bolt to use
2053 				if (!animEvents[curAnimEvent].stringData)
2054 				{ //eh, whatever. no dynamic stuff, so this will do.
2055 					animEvents[curAnimEvent].stringData = (char *) BG_Alloc(2048);
2056 				}
2057 				strcpy(animEvents[curAnimEvent].stringData, token);
2058 			}
2059 			//NOTE: this string will later be used to add a bolt and store the index, as below:
2060 			//animEvent->eventData[AED_BOLTINDEX] = trap->G2API_AddBolt( &cent->gent->ghoul2[cent->gent->playerModel], animEvent->stringData );
2061 			//get probability
2062 			token = COM_Parse( text_p );
2063 			if ( !token )
2064 			{//WARNING!  BAD TABLE!
2065 				break;
2066 			}
2067 			animEvents[curAnimEvent].eventData[AED_EFFECT_PROBABILITY] = atoi( token );
2068 			break;
2069 		case AEV_FIRE:			//# animID AEV_FIRE framenum altfire chancetofire
2070 			//get altfire
2071 			token = COM_Parse( text_p );
2072 			if ( !token )
2073 			{//WARNING!  BAD TABLE!
2074 				break;
2075 			}
2076 			animEvents[curAnimEvent].eventData[AED_FIRE_ALT] = atoi( token );
2077 			//get probability
2078 			token = COM_Parse( text_p );
2079 			if ( !token )
2080 			{//WARNING!  BAD TABLE!
2081 				break;
2082 			}
2083 			animEvents[curAnimEvent].eventData[AED_FIRE_PROBABILITY] = atoi( token );
2084 			break;
2085 		case AEV_MOVE:			//# animID AEV_MOVE framenum forwardpush rightpush uppush
2086 			//get forward push
2087 			token = COM_Parse( text_p );
2088 			if ( !token )
2089 			{//WARNING!  BAD TABLE!
2090 				break;
2091 			}
2092 			animEvents[curAnimEvent].eventData[AED_MOVE_FWD] = atoi( token );
2093 			//get right push
2094 			token = COM_Parse( text_p );
2095 			if ( !token )
2096 			{//WARNING!  BAD TABLE!
2097 				break;
2098 			}
2099 			animEvents[curAnimEvent].eventData[AED_MOVE_RT] = atoi( token );
2100 			//get upwards push
2101 			token = COM_Parse( text_p );
2102 			if ( !token )
2103 			{//WARNING!  BAD TABLE!
2104 				break;
2105 			}
2106 			animEvents[curAnimEvent].eventData[AED_MOVE_UP] = atoi( token );
2107 			break;
2108 		default:				//unknown?
2109 			SkipRestOfLine( text_p );
2110 			continue;
2111 			break;
2112 		}
2113 
2114 		if ( curAnimEvent == lastAnimEvent )
2115 		{
2116 			lastAnimEvent++;
2117 		}
2118 	}
2119 }
2120 
2121 /*
2122 ======================
2123 BG_ParseAnimationEvtFile
2124 
2125 Read a configuration file containing animation events
2126 models/players/kyle/animevents.cfg, etc
2127 
2128 This file's presence is not required
2129 
2130 ======================
2131 */
2132 bgLoadedEvents_t bgAllEvents[MAX_ANIM_FILES];
2133 int bgNumAnimEvents = 1;
2134 static int bg_animParseIncluding = 0;
BG_ParseAnimationEvtFile(const char * as_filename,int animFileIndex,int eventFileIndex)2135 int BG_ParseAnimationEvtFile( const char *as_filename, int animFileIndex, int eventFileIndex )
2136 {
2137 	const char	*text_p;
2138 	int			len;
2139 	const char	*token;
2140 	char		text[80000];
2141 	char		sfilename[MAX_QPATH];
2142 	fileHandle_t	f;
2143 	int			i, j, upper_i, lower_i;
2144 	int				usedIndex = -1;
2145 	animevent_t	*legsAnimEvents;
2146 	animevent_t	*torsoAnimEvents;
2147 	animation_t		*animations;
2148 	int				forcedIndex;
2149 
2150 	assert(animFileIndex < MAX_ANIM_FILES);
2151 	assert(eventFileIndex < MAX_ANIM_FILES);
2152 
2153 	if (eventFileIndex == -1)
2154 	{
2155 		forcedIndex = 0;
2156 	}
2157 	else
2158 	{
2159 		forcedIndex = eventFileIndex;
2160 	}
2161 
2162 	if (bg_animParseIncluding <= 0)
2163 	{ //if we should be parsing an included file, skip this part
2164 		if ( bgAllEvents[forcedIndex].eventsParsed )
2165 		{//already cached this one
2166 			return forcedIndex;
2167 		}
2168 	}
2169 
2170 	legsAnimEvents = bgAllEvents[forcedIndex].legsAnimEvents;
2171 	torsoAnimEvents = bgAllEvents[forcedIndex].torsoAnimEvents;
2172 	animations = bgAllAnims[animFileIndex].anims;
2173 
2174 	if (bg_animParseIncluding <= 0)
2175 	{ //if we should be parsing an included file, skip this part
2176 		//Go through and see if this filename is already in the table.
2177 		i = 0;
2178 		while (i < bgNumAnimEvents && forcedIndex != 0)
2179 		{
2180 			if (!Q_stricmp(as_filename, bgAllEvents[i].filename))
2181 			{ //looks like we have it already.
2182 				return i;
2183 			}
2184 			i++;
2185 		}
2186 	}
2187 
2188 	// Load and parse animevents.cfg file
2189 	Com_sprintf( sfilename, sizeof( sfilename ), "%sanimevents.cfg", as_filename );
2190 
2191 	if (bg_animParseIncluding <= 0)
2192 	{ //should already be done if we're including
2193 		//initialize anim event array
2194 		for( i = 0; i < MAX_ANIM_EVENTS; i++ )
2195 		{
2196 			//Type of event
2197 			torsoAnimEvents[i].eventType = AEV_NONE;
2198 			legsAnimEvents[i].eventType = AEV_NONE;
2199 			//Frame to play event on
2200 			torsoAnimEvents[i].keyFrame = -1;
2201 			legsAnimEvents[i].keyFrame = -1;
2202 			//we allow storage of one string, temporarily (in case we have to look up an index later, then make sure to set stringData to NULL so we only do the look-up once)
2203 			torsoAnimEvents[i].stringData = NULL;
2204 			legsAnimEvents[i].stringData = NULL;
2205 			//Unique IDs, can be soundIndex of sound file to play OR effect index or footstep type, etc.
2206 			for ( j = 0; j < AED_ARRAY_SIZE; j++ )
2207 			{
2208 				torsoAnimEvents[i].eventData[j] = -1;
2209 				legsAnimEvents[i].eventData[j] = -1;
2210 			}
2211 		}
2212 	}
2213 
2214 	// load the file
2215 	len = trap->FS_Open( sfilename, &f, FS_READ );
2216 	if ( len <= 0 )
2217 	{//no file
2218 		goto fin;
2219 	}
2220 	if ( len >= sizeof( text ) - 1 )
2221 	{
2222 		trap->FS_Close(f);
2223 #ifndef FINAL_BUILD
2224 		Com_Error(ERR_DROP, "File %s too long\n", sfilename );
2225 #else
2226 		Com_Printf( "File %s too long\n", sfilename );
2227 #endif
2228 		goto fin;
2229 	}
2230 
2231 	trap->FS_Read( text, len, f );
2232 	text[len] = 0;
2233 	trap->FS_Close( f );
2234 
2235 	// parse the text
2236 	text_p = text;
2237 	upper_i =0;
2238 	lower_i =0;
2239 
2240 	COM_BeginParseSession ("BG_ParseAnimationEvtFile");
2241 
2242 	// read information for batches of sounds (UPPER or LOWER)
2243 	while ( 1 )
2244 	{
2245 		// Get base frame of sequence
2246 		token = COM_Parse( &text_p );
2247 		if ( !token || !token[0] )
2248 		{
2249 			break;
2250 		}
2251 
2252 		if ( !Q_stricmp(token,"include") )	// grab from another animevents.cfg
2253 		{//NOTE: you REALLY should NOT do this after the main block of UPPERSOUNDS and LOWERSOUNDS
2254 			const char	*include_filename = COM_Parse( &text_p );
2255 			if ( include_filename != NULL )
2256 			{
2257 				char fullIPath[MAX_QPATH];
2258 				strcpy(fullIPath, va("models/players/%s/", include_filename));
2259 				bg_animParseIncluding++;
2260 				BG_ParseAnimationEvtFile( fullIPath, animFileIndex, forcedIndex );
2261 				bg_animParseIncluding--;
2262 			}
2263 		}
2264 
2265 		if ( !Q_stricmp(token,"UPPEREVENTS") )	// A batch of upper sounds
2266 		{
2267 			ParseAnimationEvtBlock( as_filename, torsoAnimEvents, animations, &upper_i, &text_p );
2268 		}
2269 
2270 		else if ( !Q_stricmp(token,"LOWEREVENTS") )	// A batch of lower sounds
2271 		{
2272 			ParseAnimationEvtBlock( as_filename, legsAnimEvents, animations, &lower_i, &text_p );
2273 		}
2274 	}
2275 
2276 	usedIndex = forcedIndex;
2277 fin:
2278 	//Mark this anim set so that we know we tried to load he sounds, don't care if the load failed
2279 	if (bg_animParseIncluding <= 0)
2280 	{ //if we should be parsing an included file, skip this part
2281 		bgAllEvents[forcedIndex].eventsParsed = qtrue;
2282 		strcpy(bgAllEvents[forcedIndex].filename, as_filename);
2283 		if (forcedIndex)
2284 		{
2285 			bgNumAnimEvents++;
2286 		}
2287 	}
2288 
2289 	return usedIndex;
2290 }
2291 #endif
2292 
2293 /*
2294 ======================
2295 BG_ParseAnimationFile
2296 
2297 Read a configuration file containing animation counts and rates
2298 models/players/visor/animation.cfg, etc
2299 
2300 ======================
2301 */
BG_ParseAnimationFile(const char * filename,animation_t * animset,qboolean isHumanoid)2302 int BG_ParseAnimationFile(const char *filename, animation_t *animset, qboolean isHumanoid)
2303 {
2304 	char		*text_p;
2305 	int			len;
2306 	int			i;
2307 	char		*token;
2308 	float		fps;
2309 	int			usedIndex = -1;
2310 	int			nextIndex = bgNumAllAnims;
2311 	qboolean	dynAlloc = qfalse;
2312 	///qboolean	wasLoaded = qfalse;
2313 	static char BGPAFtext[60000];
2314 	fileHandle_t	f;
2315 	int				animNum;
2316 
2317 	BGPAFtext[0] = '\0';
2318 
2319 	if (!isHumanoid)
2320 	{
2321 		i = 0;
2322 		while (i < bgNumAllAnims)
2323 		{ //see if it's been loaded already
2324 			if (!Q_stricmp(bgAllAnims[i].filename, filename))
2325 			{
2326 				animset = bgAllAnims[i].anims;
2327 				return i; //alright, we already have it.
2328 			}
2329 			i++;
2330 		}
2331 
2332 		//Looks like it has not yet been loaded. Allocate space for the anim set if we need to, and continue along.
2333 		if (!animset)
2334 		{
2335 			if (strstr(filename, "players/_humanoid/"))
2336 			{ //then use the static humanoid set.
2337 				animset = bgHumanoidAnimations;
2338 				nextIndex = 0;
2339 			}
2340 			else if (strstr(filename, "players/rockettrooper/"))
2341 			{ //rockettrooper always index 1
2342 				nextIndex = 1;
2343 				animset = BG_AnimsetAlloc();
2344 				dynAlloc = qtrue; //so we know to free this memory in case we have to return early. Don't want any leaks.
2345 
2346 				if (!animset)
2347 				{
2348 					assert(!"Anim set alloc failed!");
2349 					return -1;
2350 				}
2351 			}
2352 			else
2353 			{
2354 				animset = BG_AnimsetAlloc();
2355 				dynAlloc = qtrue; //so we know to free this memory in case we have to return early. Don't want any leaks.
2356 
2357 				if (!animset)
2358 				{
2359 					assert(!"Anim set alloc failed!");
2360 					return -1;
2361 				}
2362 			}
2363 		}
2364 	}
2365 #ifdef _DEBUG
2366 	else
2367 	{
2368 		assert(animset);
2369 	}
2370 #endif
2371 
2372 	// load the file
2373 	if (!BGPAFtextLoaded || !isHumanoid)
2374 	{ //rww - We are always using the same animation config now. So only load it once.
2375 		len = trap->FS_Open( filename, &f, FS_READ );
2376 		if ( (len <= 0) || (len >= sizeof( BGPAFtext ) - 1) )
2377 		{
2378 			trap->FS_Close( f );
2379 			if (dynAlloc)
2380 			{
2381 				BG_AnimsetFree(animset);
2382 			}
2383 			if (len > 0)
2384 			{
2385 				Com_Error(ERR_DROP, "%s exceeds the allowed game-side animation buffer!", filename);
2386 			}
2387 			return -1;
2388 		}
2389 
2390 		trap->FS_Read( BGPAFtext, len, f );
2391 
2392 		BGPAFtext[len] = 0;
2393 		trap->FS_Close( f );
2394 	}
2395 	else
2396 	{
2397 		if (dynAlloc)
2398 		{
2399 			assert(!"Should not have allocated dynamically for humanoid");
2400 			BG_AnimsetFree(animset);
2401 		}
2402 		return 0; //humanoid index
2403 	}
2404 
2405 	// parse the text
2406 	text_p = BGPAFtext;
2407 
2408 	//FIXME: have some way of playing anims backwards... negative numFrames?
2409 
2410 	//initialize anim array so that from 0 to MAX_ANIMATIONS, set default values of 0 1 0 100
2411 	for(i = 0; i < MAX_ANIMATIONS; i++)
2412 	{
2413 		animset[i].firstFrame = 0;
2414 		animset[i].numFrames = 0;
2415 		animset[i].loopFrames = -1;
2416 		animset[i].frameLerp = 100;
2417 	}
2418 
2419 	// read information for each frame
2420 	while(1)
2421 	{
2422 		token = COM_Parse( (const char **)(&text_p) );
2423 
2424 		if ( !token || !token[0])
2425 		{
2426 			break;
2427 		}
2428 
2429 		animNum = GetIDForString(animTable, token);
2430 		if(animNum == -1)
2431 		{
2432 //#ifndef FINAL_BUILD
2433 #ifdef _DEBUG
2434 			if (strcmp(token,"ROOT"))
2435 			{
2436 				Com_Printf(S_COLOR_RED"WARNING: Unknown token %s in %s\n", token, filename);
2437 			}
2438 			while (token[0])
2439 			{
2440 				token = COM_ParseExt( (const char **) &text_p, qfalse );	//returns empty string when next token is EOL
2441 			}
2442 #endif
2443 			continue;
2444 		}
2445 
2446 		token = COM_Parse( (const char **)(&text_p) );
2447 		if ( !token )
2448 		{
2449 			break;
2450 		}
2451 		animset[animNum].firstFrame = atoi( token );
2452 
2453 		token = COM_Parse( (const char **)(&text_p) );
2454 		if ( !token )
2455 		{
2456 			break;
2457 		}
2458 		animset[animNum].numFrames = atoi( token );
2459 
2460 		token = COM_Parse( (const char **)(&text_p) );
2461 		if ( !token )
2462 		{
2463 			break;
2464 		}
2465 		animset[animNum].loopFrames = atoi( token );
2466 
2467 		token = COM_Parse( (const char **)(&text_p) );
2468 		if ( !token )
2469 		{
2470 			break;
2471 		}
2472 		fps = atof( token );
2473 		if ( fps == 0 )
2474 		{
2475 			fps = 1;//Don't allow divide by zero error
2476 		}
2477 		if ( fps < 0 )
2478 		{//backwards
2479 			animset[animNum].frameLerp = floor(1000.0f / fps);
2480 		}
2481 		else
2482 		{
2483 			animset[animNum].frameLerp = ceil(1000.0f / fps);
2484 		}
2485 	}
2486 /*
2487 #ifdef _DEBUG
2488 	//Check the array, and print the ones that have nothing in them.
2489 	for(i = 0; i < MAX_ANIMATIONS; i++)
2490 	{
2491 		if (animTable[i].name != NULL)		// This animation reference exists.
2492 		{
2493 			if (animset[i].firstFrame <= 0 && animset[i].numFrames <=0)
2494 			{	// This is an empty animation reference.
2495 				Com_Printf("***ANIMTABLE reference #%d (%s) is empty!\n", i, animTable[i].name);
2496 			}
2497 		}
2498 	}
2499 #endif // _DEBUG
2500 */
2501 #ifdef CONVENIENT_ANIMATION_FILE_DEBUG_THING
2502 	SpewDebugStuffToFile();
2503 #endif
2504 
2505 //	wasLoaded = BGPAFtextLoaded;
2506 
2507 	if (isHumanoid)
2508 	{
2509 		bgAllAnims[0].anims = animset;
2510 		strcpy(bgAllAnims[0].filename, filename);
2511 		BGPAFtextLoaded = qtrue;
2512 
2513 		usedIndex = 0;
2514 	}
2515 	else
2516 	{
2517 		bgAllAnims[nextIndex].anims = animset;
2518 		strcpy(bgAllAnims[nextIndex].filename, filename);
2519 
2520 		usedIndex = bgNumAllAnims;
2521 
2522 		if (nextIndex > 1)
2523 		{ //don't bother increasing the number if this ended up as a humanoid/rockettrooper load.
2524 			bgNumAllAnims++;
2525 		}
2526 		else
2527 		{
2528 			BGPAFtextLoaded = qtrue;
2529 			usedIndex = nextIndex;
2530 		}
2531 	}
2532 
2533 	/*
2534 	if (!wasLoaded && BGPAFtextLoaded)
2535 	{ //just loaded humanoid skel - we always want the rockettrooper to be after it, in slot 1
2536 #ifdef _DEBUG
2537 		assert(BG_ParseAnimationFile("models/players/rockettrooper/animation.cfg", NULL, qfalse) == 1);
2538 #else
2539 		BG_ParseAnimationFile("models/players/rockettrooper/animation.cfg", NULL, qfalse);
2540 #endif
2541 	}
2542 	*/
2543 
2544 	return usedIndex;
2545 }
2546 
2547 /*
2548 ===================
2549 LEGS Animations
2550 Base animation for overall body
2551 ===================
2552 */
BG_StartLegsAnim(playerState_t * ps,int anim)2553 static void BG_StartLegsAnim( playerState_t *ps, int anim )
2554 {
2555 	if ( ps->pm_type >= PM_DEAD )
2556 	{
2557 		//vehicles are allowed to do this.. IF it's a vehicle death anim
2558 		if (ps->clientNum < MAX_CLIENTS || anim != BOTH_VT_DEATH1)
2559 		{
2560 			return;
2561 		}
2562 	}
2563 	if ( ps->legsTimer > 0 )
2564 	{
2565 		return;		// a high priority animation is running
2566 	}
2567 
2568 	if (ps->legsAnim == anim)
2569 	{
2570 		BG_FlipPart(ps, SETANIM_LEGS);
2571 	}
2572 #ifdef _GAME
2573 	else if (g_entities[ps->clientNum].s.legsAnim == anim)
2574 	{ //toggled anim to one anim then back to the one we were at previously in
2575 		//one frame, indicating that anim should be restarted.
2576 		BG_FlipPart(ps, SETANIM_LEGS);
2577 	}
2578 #endif
2579 	ps->legsAnim = anim;
2580 
2581 	/*
2582 	if ( pm->debugLevel ) {
2583 		Com_Printf("%d:  StartLegsAnim %d, on client#%d\n", pm->cmd.serverTime, anim, pm->ps->clientNum);
2584 	}
2585 	*/
2586 }
2587 
PM_ContinueLegsAnim(int anim)2588 void PM_ContinueLegsAnim( int anim ) {
2589 	if ( ( pm->ps->legsAnim ) == anim ) {
2590 		return;
2591 	}
2592 	if ( pm->ps->legsTimer > 0 ) {
2593 		return;		// a high priority animation is running
2594 	}
2595 
2596 	BG_StartLegsAnim( pm->ps, anim );
2597 }
2598 
PM_ForceLegsAnim(int anim)2599 void PM_ForceLegsAnim( int anim) {
2600 	if (BG_InSpecialJump(pm->ps->legsAnim) &&
2601 		pm->ps->legsTimer > 0 &&
2602 		!BG_InSpecialJump(anim))
2603 	{
2604 		return;
2605 	}
2606 
2607 	if (BG_InRoll(pm->ps, pm->ps->legsAnim) &&
2608 		pm->ps->legsTimer > 0 &&
2609 		!BG_InRoll(pm->ps, anim))
2610 	{
2611 		return;
2612 	}
2613 
2614 	pm->ps->legsTimer = 0;
2615 	BG_StartLegsAnim( pm->ps, anim );
2616 }
2617 
2618 
2619 
2620 /*
2621 ===================
2622 TORSO Animations
2623 Override animations for upper body
2624 ===================
2625 */
BG_StartTorsoAnim(playerState_t * ps,int anim)2626 void BG_StartTorsoAnim( playerState_t *ps, int anim )
2627 {
2628 	if ( ps->pm_type >= PM_DEAD )
2629 	{
2630 		return;
2631 	}
2632 
2633 	if (ps->torsoAnim == anim)
2634 	{
2635 		BG_FlipPart(ps, SETANIM_TORSO);
2636 	}
2637 #ifdef _GAME
2638 	else if (g_entities[ps->clientNum].s.torsoAnim == anim)
2639 	{ //toggled anim to one anim then back to the one we were at previously in
2640 		//one frame, indicating that anim should be restarted.
2641 		BG_FlipPart(ps, SETANIM_TORSO);
2642 	}
2643 #endif
2644 	ps->torsoAnim = anim;
2645 }
2646 
PM_StartTorsoAnim(int anim)2647 void PM_StartTorsoAnim( int anim )
2648 {
2649     BG_StartTorsoAnim(pm->ps, anim);
2650 }
2651 
2652 
2653 /*
2654 -------------------------
2655 PM_SetLegsAnimTimer
2656 -------------------------
2657 */
BG_SetLegsAnimTimer(playerState_t * ps,int time)2658 void BG_SetLegsAnimTimer(playerState_t *ps, int time)
2659 {
2660 	ps->legsTimer = time;
2661 
2662 	if (ps->legsTimer < 0 && time != -1 )
2663 	{//Cap timer to 0 if was counting down, but let it be -1 if that was intentional.  NOTENOTE Yeah this seems dumb, but it mirrors SP.
2664 		ps->legsTimer = 0;
2665 	}
2666 }
2667 
PM_SetLegsAnimTimer(int time)2668 void PM_SetLegsAnimTimer(int time)
2669 {
2670 	BG_SetLegsAnimTimer(pm->ps, time);
2671 }
2672 
2673 /*
2674 -------------------------
2675 PM_SetTorsoAnimTimer
2676 -------------------------
2677 */
BG_SetTorsoAnimTimer(playerState_t * ps,int time)2678 void BG_SetTorsoAnimTimer(playerState_t *ps, int time )
2679 {
2680 	ps->torsoTimer = time;
2681 
2682 	if (ps->torsoTimer < 0 && time != -1 )
2683 	{//Cap timer to 0 if was counting down, but let it be -1 if that was intentional.  NOTENOTE Yeah this seems dumb, but it mirrors SP.
2684 		ps->torsoTimer = 0;
2685 	}
2686 }
2687 
PM_SetTorsoAnimTimer(int time)2688 void PM_SetTorsoAnimTimer(int time )
2689 {
2690 	BG_SetTorsoAnimTimer(pm->ps, time);
2691 }
2692 
BG_SaberStartTransAnim(int clientNum,int saberAnimLevel,int weapon,int anim,float * animSpeed,int broken)2693 void BG_SaberStartTransAnim( int clientNum, int saberAnimLevel, int weapon, int anim, float *animSpeed, int broken )
2694 {
2695 	if ( anim >= BOTH_A1_T__B_ && anim <= BOTH_ROLL_STAB )
2696 	{
2697 		if ( weapon == WP_SABER )
2698 		{
2699 			saberInfo_t *saber = BG_MySaber( clientNum, 0 );
2700 			if ( saber
2701 				&& saber->animSpeedScale != 1.0f )
2702 			{
2703 				*animSpeed *= saber->animSpeedScale;
2704 			}
2705 			saber = BG_MySaber( clientNum, 1 );
2706 			if ( saber
2707 				&& saber->animSpeedScale != 1.0f )
2708 			{
2709 				*animSpeed *= saber->animSpeedScale;
2710 			}
2711 		}
2712 	}
2713 
2714 	if ( ( (anim) >= BOTH_T1_BR__R &&
2715 		(anim) <= BOTH_T1_BL_TL ) ||
2716 		( (anim) >= BOTH_T2_BR__R &&
2717 		(anim) <= BOTH_T2_BL_TL ) ||
2718 		( (anim) >= BOTH_T3_BR__R &&
2719 		(anim) <= BOTH_T3_BL_TL ) )
2720 	{
2721 		if ( saberAnimLevel == FORCE_LEVEL_1 )
2722 		{
2723 			*animSpeed *= 1.5f;
2724 		}
2725 		else if ( saberAnimLevel == FORCE_LEVEL_3 )
2726 		{
2727 			*animSpeed *= 0.75f;
2728 		}
2729 
2730 		if (broken & (1<<BROKENLIMB_RARM))
2731 		{
2732 			*animSpeed *= 0.5f;
2733 		}
2734 		else if (broken & (1<<BROKENLIMB_LARM))
2735 		{
2736 			*animSpeed *= 0.65f;
2737 		}
2738 	}
2739 	else if (broken && PM_InSaberAnim(anim))
2740 	{
2741 		if (broken & (1<<BROKENLIMB_RARM))
2742 		{
2743 			*animSpeed *= 0.5f;
2744 		}
2745 		else if (broken & (1<<BROKENLIMB_LARM))
2746 		{
2747 			*animSpeed *= 0.65f;
2748 		}
2749 	}
2750 }
2751 
2752 /*
2753 -------------------------
2754 PM_SetAnimFinal
2755 -------------------------
2756 */
2757 qboolean PM_RunningAnim( int anim );
2758 qboolean PM_WalkingAnim( int anim );
2759 
BG_SetAnimFinal(playerState_t * ps,animation_t * animations,int setAnimParts,int anim,int setAnimFlags)2760 void BG_SetAnimFinal(playerState_t *ps, animation_t *animations,
2761 					 int setAnimParts,int anim,int setAnimFlags)
2762 {
2763 	float editAnimSpeed = 1;
2764 
2765 	if (!animations)
2766 	{
2767 		return;
2768 	}
2769 
2770 	assert(anim > -1);
2771 	assert(animations[anim].firstFrame > 0 || animations[anim].numFrames > 0);
2772 
2773 	BG_SaberStartTransAnim(ps->clientNum, ps->fd.saberAnimLevel, ps->weapon, anim, &editAnimSpeed, ps->brokenLimbs);
2774 
2775 	// Set torso anim
2776 	if (setAnimParts & SETANIM_TORSO)
2777 	{
2778 		// Don't reset if it's already running the anim
2779 		if( !(setAnimFlags & SETANIM_FLAG_RESTART) && (ps->torsoAnim) == anim )
2780 		{
2781 			goto setAnimLegs;
2782 		}
2783 		// or if a more important anim is running
2784 		if( !(setAnimFlags & SETANIM_FLAG_OVERRIDE) && ((ps->torsoTimer > 0)||(ps->torsoTimer == -1)) )
2785 		{
2786 			goto setAnimLegs;
2787 		}
2788 
2789 		BG_StartTorsoAnim(ps, anim);
2790 
2791 		if (setAnimFlags & SETANIM_FLAG_HOLD)
2792 		{
2793 			if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
2794 			{	// Make sure to only wait in full 1/20 sec server frame intervals.
2795 				int dur;
2796 				int speedDif;
2797 
2798 				dur = (animations[anim].numFrames-1) * fabs((float)(animations[anim].frameLerp));
2799 				speedDif = dur - (dur * editAnimSpeed);
2800 				dur += speedDif;
2801 				if (dur > 1)
2802 				{
2803 					ps->torsoTimer = dur-1;
2804 				}
2805 				else
2806 				{
2807 					ps->torsoTimer = fabs((float)(animations[anim].frameLerp));
2808 				}
2809 			}
2810 			else
2811 			{
2812 				ps->torsoTimer = ((animations[anim].numFrames ) * fabs((float)(animations[anim].frameLerp)));
2813 			}
2814 
2815 			if (ps->fd.forcePowersActive & (1 << FP_RAGE))
2816 			{
2817 				ps->torsoTimer /= 1.7;
2818 			}
2819 		}
2820 	}
2821 
2822 setAnimLegs:
2823 	// Set legs anim
2824 	if (setAnimParts & SETANIM_LEGS)
2825 	{
2826 		// Don't reset if it's already running the anim
2827 		if( !(setAnimFlags & SETANIM_FLAG_RESTART) && (ps->legsAnim) == anim )
2828 		{
2829 			goto setAnimDone;
2830 		}
2831 		// or if a more important anim is running
2832 		if( !(setAnimFlags & SETANIM_FLAG_OVERRIDE) && ((ps->legsTimer > 0)||(ps->legsTimer == -1)) )
2833 		{
2834 			goto setAnimDone;
2835 		}
2836 
2837 		BG_StartLegsAnim(ps, anim);
2838 
2839 		if (setAnimFlags & SETANIM_FLAG_HOLD)
2840 		{
2841 			if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
2842 			{	// Make sure to only wait in full 1/20 sec server frame intervals.
2843 				int dur;
2844 				int speedDif;
2845 
2846 				dur = (animations[anim].numFrames-1) * fabs((float)(animations[anim].frameLerp));
2847 				speedDif = dur - (dur * editAnimSpeed);
2848 				dur += speedDif;
2849 				if (dur > 1)
2850 				{
2851 					ps->legsTimer = dur-1;
2852 				}
2853 				else
2854 				{
2855 					ps->legsTimer = fabs((float)(animations[anim].frameLerp));
2856 				}
2857 			}
2858 			else
2859 			{
2860 				ps->legsTimer = ((animations[anim].numFrames ) * fabs((float)(animations[anim].frameLerp)));
2861 			}
2862 
2863 			if (PM_RunningAnim(anim) ||
2864 				PM_WalkingAnim(anim)) //these guys are ok, they don't actually reference pm
2865 			{
2866 				if (ps->fd.forcePowersActive & (1 << FP_RAGE))
2867 				{
2868 					ps->legsTimer /= 1.3;
2869 				}
2870 				else if (ps->fd.forcePowersActive & (1 << FP_SPEED))
2871 				{
2872 					ps->legsTimer /= 1.7;
2873 				}
2874 			}
2875 		}
2876 	}
2877 
2878 setAnimDone:
2879 	return;
2880 }
2881 
PM_SetAnimFinal(int setAnimParts,int anim,int setAnimFlags)2882 void PM_SetAnimFinal(int setAnimParts,int anim,int setAnimFlags)
2883 {
2884 	BG_SetAnimFinal(pm->ps, pm->animations, setAnimParts, anim, setAnimFlags);
2885 }
2886 
2887 
BG_HasAnimation(int animIndex,int animation)2888 qboolean BG_HasAnimation(int animIndex, int animation)
2889 {
2890 	animation_t *animations;
2891 
2892 	//must be a valid anim number
2893 	if ( animation < 0 || animation >= MAX_ANIMATIONS )
2894 	{
2895 		return qfalse;
2896 	}
2897 
2898 	//Must have a file index entry
2899 	if( animIndex < 0 || animIndex > bgNumAllAnims )
2900 		return qfalse;
2901 
2902 	animations = bgAllAnims[animIndex].anims;
2903 
2904 	//No frames, no anim
2905 	if ( animations[animation].numFrames == 0 )
2906 		return qfalse;
2907 
2908 	//Has the sequence
2909 	return qtrue;
2910 }
2911 
BG_PickAnim(int animIndex,int minAnim,int maxAnim)2912 int BG_PickAnim( int animIndex, int minAnim, int maxAnim )
2913 {
2914 	int anim;
2915 	int count = 0;
2916 
2917 	do
2918 	{
2919 		anim = Q_irand(minAnim, maxAnim);
2920 		count++;
2921 	}
2922 	while ( !BG_HasAnimation( animIndex, anim ) && count < 1000 );
2923 
2924 	if (count == 1000)
2925 	{ //guess we just don't have a death anim then.
2926 		return -1;
2927 	}
2928 
2929 	return anim;
2930 }
2931 
2932 //I want to be able to use this on a playerstate even when we are not the focus
2933 //of a pmove too so I have ported it to true BGishness.
2934 //Please do not reference pm in this function or any functions that it calls,
2935 //or I will cry. -rww
BG_SetAnim(playerState_t * ps,animation_t * animations,int setAnimParts,int anim,int setAnimFlags)2936 void BG_SetAnim(playerState_t *ps, animation_t *animations, int setAnimParts,int anim,int setAnimFlags)
2937 {
2938 	if (!animations)
2939 	{
2940 		animations = bgAllAnims[0].anims;
2941 	}
2942 
2943 	if (animations[anim].firstFrame == 0 && animations[anim].numFrames == 0)
2944 	{
2945 		if (anim == BOTH_RUNBACK1 ||
2946 			anim == BOTH_WALKBACK1 ||
2947 			anim == BOTH_RUN1)
2948 		{ //hack for droids
2949 			anim = BOTH_WALK2;
2950 		}
2951 
2952 		if (animations[anim].firstFrame == 0 && animations[anim].numFrames == 0)
2953 		{ //still? Just return then I guess.
2954 			return;
2955 		}
2956 	}
2957 
2958 	/*
2959 	if (BG_InSpecialJump(anim))
2960 	{
2961 		setAnimFlags |= SETANIM_FLAG_RESTART;
2962 	}
2963 	*/
2964 	//Don't know why I put this here originally but it's messing stuff up now and it isn't needed.
2965 
2966 //	if (BG_InRoll(ps, ps->legsAnim))
2967 //	{ //never interrupt a roll
2968 //		return;
2969 //	}
2970 
2971 	if (setAnimFlags&SETANIM_FLAG_OVERRIDE)
2972 	{
2973 		if (setAnimParts & SETANIM_TORSO)
2974 		{
2975 			if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ps->torsoAnim) != anim )
2976 			{
2977 				BG_SetTorsoAnimTimer(ps, 0);
2978 			}
2979 		}
2980 		if (setAnimParts & SETANIM_LEGS)
2981 		{
2982 			if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ps->legsAnim) != anim )
2983 			{
2984 				BG_SetLegsAnimTimer(ps, 0);
2985 			}
2986 		}
2987 	}
2988 
2989 	BG_SetAnimFinal(ps, animations, setAnimParts, anim, setAnimFlags);
2990 }
2991 
PM_SetAnim(int setAnimParts,int anim,int setAnimFlags)2992 void PM_SetAnim(int setAnimParts,int anim,int setAnimFlags)
2993 {
2994 	BG_SetAnim(pm->ps, pm->animations, setAnimParts, anim, setAnimFlags);
2995 }
2996 
2997