codemp/game/bg_panimate.c

Go to the documentation of this file.
00001 // BG_PAnimate.c
00002 
00003 #include "q_shared.h"
00004 #include "bg_public.h"
00005 #include "bg_strap.h"
00006 #include "bg_local.h"
00007 #include "anims.h"
00008 #include "../cgame/animtable.h"
00009 #ifdef QAGAME
00010 #include "g_local.h"
00011 #endif
00012 
00013 #ifdef CGAME
00014 #include "../namespace_begin.h"
00015 extern sfxHandle_t trap_S_RegisterSound( const char *sample);
00016 extern int trap_FX_RegisterEffect( const char *file);
00017 #include "../namespace_end.h"
00018 #endif
00019 
00020 extern saberInfo_t *BG_MySaber( int clientNum, int saberNum );
00021 /*
00022 ==============================================================================
00023 BEGIN: Animation utility functions (sequence checking)
00024 ==============================================================================
00025 */
00026 //Called regardless of pm validity:
00027 
00028 // VVFIXME - Most of these functions are totally stateless and stupid. Don't
00029 // need multiple copies of this, but it's much easier (and less likely to
00030 // break in the future) if I keep separate namespace versions now.
00031 #include "../namespace_begin.h"
00032 
00033 qboolean BG_SaberStanceAnim( int anim )
00034 {
00035         switch ( anim )
00036         {
00037         case BOTH_STAND1://not really a saberstance anim, actually... "saber off" stance
00038         case BOTH_STAND2://single-saber, medium style
00039         case BOTH_SABERFAST_STANCE://single-saber, fast style
00040         case BOTH_SABERSLOW_STANCE://single-saber, strong style
00041         case BOTH_SABERSTAFF_STANCE://saber staff style
00042         case BOTH_SABERDUAL_STANCE://dual saber style
00043                 return qtrue;
00044                 break;
00045         }
00046         return qfalse;
00047 }
00048 
00049 qboolean BG_CrouchAnim( int anim )
00050 {
00051         switch ( anim )
00052         {
00053         case BOTH_SIT1:                         //# Normal chair sit.
00054         case BOTH_SIT2:                         //# Lotus position.
00055         case BOTH_SIT3:                         //# Sitting in tired position: elbows on knees
00056         case BOTH_CROUCH1:                      //# Transition from standing to crouch
00057         case BOTH_CROUCH1IDLE:          //# Crouching idle
00058         case BOTH_CROUCH1WALK:          //# Walking while crouched
00059         case BOTH_CROUCH1WALKBACK:      //# Walking while crouched
00060         case BOTH_CROUCH2TOSTAND1:      //# going from crouch2 to stand1
00061         case BOTH_CROUCH3:                      //# Desann crouching down to Kyle (cin 9)
00062         case BOTH_KNEES1:                       //# Tavion on her knees
00063         case BOTH_CROUCHATTACKBACK1://FIXME: not if in middle of anim?
00064         case BOTH_ROLL_STAB:
00065                 return qtrue;
00066                 break;
00067         }
00068         return qfalse;
00069 }
00070 
00071 qboolean BG_InSpecialJump( int anim )
00072 {
00073         switch ( (anim) )
00074         {
00075         case BOTH_WALL_RUN_RIGHT:
00076         case BOTH_WALL_RUN_RIGHT_STOP:
00077         case BOTH_WALL_RUN_RIGHT_FLIP:
00078         case BOTH_WALL_RUN_LEFT:
00079         case BOTH_WALL_RUN_LEFT_STOP:
00080         case BOTH_WALL_RUN_LEFT_FLIP:
00081         case BOTH_WALL_FLIP_RIGHT:
00082         case BOTH_WALL_FLIP_LEFT:
00083         case BOTH_FLIP_BACK1:
00084         case BOTH_FLIP_BACK2:
00085         case BOTH_FLIP_BACK3:
00086         case BOTH_WALL_FLIP_BACK1:
00087         case BOTH_BUTTERFLY_LEFT:
00088         case BOTH_BUTTERFLY_RIGHT:
00089         case BOTH_BUTTERFLY_FL1:
00090         case BOTH_BUTTERFLY_FR1:
00091         case BOTH_FJSS_TR_BL:
00092         case BOTH_FJSS_TL_BR:
00093         case BOTH_FORCELEAP2_T__B_:
00094         case BOTH_JUMPFLIPSLASHDOWN1://#
00095         case BOTH_JUMPFLIPSTABDOWN://#
00096         case BOTH_JUMPATTACK6:
00097         case BOTH_JUMPATTACK7:
00098         case BOTH_ARIAL_LEFT:
00099         case BOTH_ARIAL_RIGHT:
00100         case BOTH_ARIAL_F1:
00101         case BOTH_CARTWHEEL_LEFT:
00102         case BOTH_CARTWHEEL_RIGHT:
00103 
00104         case BOTH_FORCELONGLEAP_START:
00105         case BOTH_FORCELONGLEAP_ATTACK:
00106         case BOTH_FORCEWALLRUNFLIP_START:
00107         case BOTH_FORCEWALLRUNFLIP_END:
00108         case BOTH_FORCEWALLRUNFLIP_ALT:
00109         case BOTH_FLIP_ATTACK7:
00110         case BOTH_FLIP_HOLD7:
00111         case BOTH_FLIP_LAND:
00112         case BOTH_A7_SOULCAL:
00113                 return qtrue;
00114         }
00115         if ( BG_InReboundJump( anim ) )
00116         {
00117                 return qtrue;
00118         }
00119         if ( BG_InReboundHold( anim ) )
00120         {
00121                 return qtrue;
00122         }
00123         if ( BG_InReboundRelease( anim ) )
00124         {
00125                 return qtrue;
00126         }
00127         if ( BG_InBackFlip( anim ) )
00128         {
00129                 return qtrue;
00130         }
00131         return qfalse;
00132 }
00133 
00134 qboolean BG_InSaberStandAnim( int anim )
00135 {
00136         switch ( (anim) )
00137         {
00138         case BOTH_SABERFAST_STANCE:
00139         case BOTH_STAND2:
00140         case BOTH_SABERSLOW_STANCE:
00141         case BOTH_SABERDUAL_STANCE:
00142         case BOTH_SABERSTAFF_STANCE:
00143                 return qtrue;
00144         default:
00145                 return qfalse;
00146         }
00147 }
00148 
00149 qboolean BG_InReboundJump( int anim )
00150 {
00151         switch ( anim )
00152         {
00153         case BOTH_FORCEWALLREBOUND_FORWARD:
00154         case BOTH_FORCEWALLREBOUND_LEFT:
00155         case BOTH_FORCEWALLREBOUND_BACK:
00156         case BOTH_FORCEWALLREBOUND_RIGHT:
00157                 return qtrue;
00158                 break;
00159         }
00160         return qfalse;
00161 }
00162 
00163 qboolean BG_InReboundHold( int anim )
00164 {
00165         switch ( anim )
00166         {
00167         case BOTH_FORCEWALLHOLD_FORWARD:
00168         case BOTH_FORCEWALLHOLD_LEFT:
00169         case BOTH_FORCEWALLHOLD_BACK:
00170         case BOTH_FORCEWALLHOLD_RIGHT:
00171                 return qtrue;
00172                 break;
00173         }
00174         return qfalse;
00175 }
00176 
00177 qboolean BG_InReboundRelease( int anim )
00178 {
00179         switch ( anim )
00180         {
00181         case BOTH_FORCEWALLRELEASE_FORWARD:
00182         case BOTH_FORCEWALLRELEASE_LEFT:
00183         case BOTH_FORCEWALLRELEASE_BACK:
00184         case BOTH_FORCEWALLRELEASE_RIGHT:
00185                 return qtrue;
00186                 break;
00187         }
00188         return qfalse;
00189 }
00190 
00191 qboolean BG_InBackFlip( int anim )
00192 {
00193         switch ( anim )
00194         {
00195         case BOTH_FLIP_BACK1:
00196         case BOTH_FLIP_BACK2:
00197         case BOTH_FLIP_BACK3:
00198                 return qtrue;
00199                 break;
00200         }
00201         return qfalse;
00202 }
00203 
00204 qboolean BG_DirectFlippingAnim( int anim )
00205 {
00206         switch ( (anim) )
00207         {
00208         case BOTH_FLIP_F:                       //# Flip forward
00209         case BOTH_FLIP_B:                       //# Flip backwards
00210         case BOTH_FLIP_L:                       //# Flip left
00211         case BOTH_FLIP_R:                       //# Flip right
00212                 return qtrue;
00213                 break;
00214         }
00215 
00216         return qfalse;
00217 }
00218 
00219 qboolean BG_SaberInAttackPure( int move )
00220 {
00221         if ( move >= LS_A_TL2BR && move <= LS_A_T2B )
00222         {
00223                 return qtrue;
00224         }
00225         return qfalse;
00226 }
00227 qboolean BG_SaberInAttack( int move )
00228 {
00229         if ( move >= LS_A_TL2BR && move <= LS_A_T2B )
00230         {
00231                 return qtrue;
00232         }
00233         switch ( move )
00234         {
00235         case LS_A_BACK:
00236         case LS_A_BACK_CR:
00237         case LS_A_BACKSTAB:
00238         case LS_ROLL_STAB:
00239         case LS_A_LUNGE:
00240         case LS_A_JUMP_T__B_:
00241         case LS_A_FLIP_STAB:
00242         case LS_A_FLIP_SLASH:
00243         case LS_JUMPATTACK_DUAL:
00244         case LS_JUMPATTACK_ARIAL_LEFT:
00245         case LS_JUMPATTACK_ARIAL_RIGHT:
00246         case LS_JUMPATTACK_CART_LEFT:
00247         case LS_JUMPATTACK_CART_RIGHT:
00248         case LS_JUMPATTACK_STAFF_LEFT:
00249         case LS_JUMPATTACK_STAFF_RIGHT:
00250         case LS_BUTTERFLY_LEFT:
00251         case LS_BUTTERFLY_RIGHT:
00252         case LS_A_BACKFLIP_ATK:
00253         case LS_SPINATTACK_DUAL:
00254         case LS_SPINATTACK:
00255         case LS_LEAP_ATTACK:
00256         case LS_SWOOP_ATTACK_RIGHT:
00257         case LS_SWOOP_ATTACK_LEFT:
00258         case LS_TAUNTAUN_ATTACK_RIGHT:
00259         case LS_TAUNTAUN_ATTACK_LEFT:
00260         case LS_KICK_F:
00261         case LS_KICK_B:
00262         case LS_KICK_R:
00263         case LS_KICK_L:
00264         case LS_KICK_S:
00265         case LS_KICK_BF:
00266         case LS_KICK_RL:
00267         case LS_KICK_F_AIR:
00268         case LS_KICK_B_AIR:
00269         case LS_KICK_R_AIR:
00270         case LS_KICK_L_AIR:
00271         case LS_STABDOWN:
00272         case LS_STABDOWN_STAFF:
00273         case LS_STABDOWN_DUAL:
00274         case LS_DUAL_SPIN_PROTECT:
00275         case LS_STAFF_SOULCAL:
00276         case LS_A1_SPECIAL:
00277         case LS_A2_SPECIAL:
00278         case LS_A3_SPECIAL:
00279         case LS_UPSIDE_DOWN_ATTACK:
00280         case LS_PULL_ATTACK_STAB:
00281         case LS_PULL_ATTACK_SWING:
00282         case LS_SPINATTACK_ALORA:
00283         case LS_DUAL_FB:
00284         case LS_DUAL_LR:
00285         case LS_HILT_BASH:
00286                 return qtrue;
00287                 break;
00288         }
00289         return qfalse;
00290 }
00291 
00292 qboolean BG_SaberInKata( int saberMove )
00293 {
00294         switch ( saberMove )
00295         {
00296         case LS_A1_SPECIAL:
00297         case LS_A2_SPECIAL:
00298         case LS_A3_SPECIAL:
00299         case LS_DUAL_SPIN_PROTECT:
00300         case LS_STAFF_SOULCAL:
00301                 return qtrue;
00302         }
00303         return qfalse;
00304 }
00305 
00306 qboolean BG_InKataAnim(int anim)
00307 {
00308         switch (anim)
00309         {
00310         case BOTH_A6_SABERPROTECT:
00311         case BOTH_A7_SOULCAL:
00312         case BOTH_A1_SPECIAL:
00313         case BOTH_A2_SPECIAL:
00314         case BOTH_A3_SPECIAL:
00315                 return qtrue;
00316         }
00317         return qfalse;
00318 }
00319 
00320 qboolean BG_SaberInSpecial( int move )
00321 {
00322         switch( move )
00323         {
00324         case LS_A_BACK:
00325         case LS_A_BACK_CR:
00326         case LS_A_BACKSTAB:
00327         case LS_ROLL_STAB:
00328         case LS_A_LUNGE:
00329         case LS_A_JUMP_T__B_:
00330         case LS_A_FLIP_STAB:
00331         case LS_A_FLIP_SLASH:
00332         case LS_JUMPATTACK_DUAL:
00333         case LS_JUMPATTACK_ARIAL_LEFT:
00334         case LS_JUMPATTACK_ARIAL_RIGHT:
00335         case LS_JUMPATTACK_CART_LEFT:
00336         case LS_JUMPATTACK_CART_RIGHT:
00337         case LS_JUMPATTACK_STAFF_LEFT:
00338         case LS_JUMPATTACK_STAFF_RIGHT:
00339         case LS_BUTTERFLY_LEFT:
00340         case LS_BUTTERFLY_RIGHT:
00341         case LS_A_BACKFLIP_ATK:
00342         case LS_SPINATTACK_DUAL:
00343         case LS_SPINATTACK:
00344         case LS_LEAP_ATTACK:
00345         case LS_SWOOP_ATTACK_RIGHT:
00346         case LS_SWOOP_ATTACK_LEFT:
00347         case LS_TAUNTAUN_ATTACK_RIGHT:
00348         case LS_TAUNTAUN_ATTACK_LEFT:
00349         case LS_KICK_F:
00350         case LS_KICK_B:
00351         case LS_KICK_R:
00352         case LS_KICK_L:
00353         case LS_KICK_S:
00354         case LS_KICK_BF:
00355         case LS_KICK_RL:
00356         case LS_KICK_F_AIR:
00357         case LS_KICK_B_AIR:
00358         case LS_KICK_R_AIR:
00359         case LS_KICK_L_AIR:
00360         case LS_STABDOWN:
00361         case LS_STABDOWN_STAFF:
00362         case LS_STABDOWN_DUAL:
00363         case LS_DUAL_SPIN_PROTECT:
00364         case LS_STAFF_SOULCAL:
00365         case LS_A1_SPECIAL:
00366         case LS_A2_SPECIAL:
00367         case LS_A3_SPECIAL:
00368         case LS_UPSIDE_DOWN_ATTACK:
00369         case LS_PULL_ATTACK_STAB:
00370         case LS_PULL_ATTACK_SWING:
00371         case LS_SPINATTACK_ALORA:
00372         case LS_DUAL_FB:
00373         case LS_DUAL_LR:
00374         case LS_HILT_BASH:
00375                 return qtrue;
00376         }
00377         return qfalse;
00378 }
00379 
00380 qboolean BG_KickMove( int move )
00381 {
00382         switch( move )
00383         {
00384         case LS_KICK_F:
00385         case LS_KICK_B:
00386         case LS_KICK_R:
00387         case LS_KICK_L:
00388         case LS_KICK_S:
00389         case LS_KICK_BF:
00390         case LS_KICK_RL:
00391         case LS_KICK_F_AIR:
00392         case LS_KICK_B_AIR:
00393         case LS_KICK_R_AIR:
00394         case LS_KICK_L_AIR:
00395         case LS_HILT_BASH:
00396                 return qtrue;
00397         }
00398         return qfalse;
00399 }
00400 
00401 qboolean BG_SaberInIdle( int move )
00402 {
00403         switch ( move )
00404         {
00405         case LS_NONE:
00406         case LS_READY:
00407         case LS_DRAW:
00408         case LS_PUTAWAY:
00409                 return qtrue;
00410                 break;
00411         }
00412         return qfalse;
00413 }
00414 
00415 qboolean BG_InExtraDefenseSaberMove( int move )
00416 {
00417         switch ( move )
00418         {
00419         case LS_SPINATTACK_DUAL:
00420         case LS_SPINATTACK:
00421         case LS_DUAL_SPIN_PROTECT:
00422         case LS_STAFF_SOULCAL:
00423         case LS_A1_SPECIAL:
00424         case LS_A2_SPECIAL:
00425         case LS_A3_SPECIAL:
00426         case LS_JUMPATTACK_DUAL:
00427                 return qtrue;
00428                 break;
00429         }
00430         return qfalse;
00431 }
00432 
00433 qboolean BG_FlippingAnim( int anim )
00434 {
00435         switch ( anim )
00436         {
00437         case BOTH_FLIP_F:                       //# Flip forward
00438         case BOTH_FLIP_B:                       //# Flip backwards
00439         case BOTH_FLIP_L:                       //# Flip left
00440         case BOTH_FLIP_R:                       //# Flip right
00441         case BOTH_WALL_RUN_RIGHT_FLIP:
00442         case BOTH_WALL_RUN_LEFT_FLIP:
00443         case BOTH_WALL_FLIP_RIGHT:
00444         case BOTH_WALL_FLIP_LEFT:
00445         case BOTH_FLIP_BACK1:
00446         case BOTH_FLIP_BACK2:
00447         case BOTH_FLIP_BACK3:
00448         case BOTH_WALL_FLIP_BACK1:
00449         //Not really flips, but...
00450         case BOTH_WALL_RUN_RIGHT:
00451         case BOTH_WALL_RUN_LEFT:
00452         case BOTH_WALL_RUN_RIGHT_STOP:
00453         case BOTH_WALL_RUN_LEFT_STOP:
00454         case BOTH_BUTTERFLY_LEFT:
00455         case BOTH_BUTTERFLY_RIGHT:
00456         case BOTH_BUTTERFLY_FL1:
00457         case BOTH_BUTTERFLY_FR1:
00458         //
00459         case BOTH_ARIAL_LEFT:
00460         case BOTH_ARIAL_RIGHT:
00461         case BOTH_ARIAL_F1:
00462         case BOTH_CARTWHEEL_LEFT:
00463         case BOTH_CARTWHEEL_RIGHT:
00464         case BOTH_JUMPFLIPSLASHDOWN1:
00465         case BOTH_JUMPFLIPSTABDOWN:
00466         case BOTH_JUMPATTACK6:
00467         case BOTH_JUMPATTACK7:
00468         //JKA
00469         case BOTH_FORCEWALLRUNFLIP_END:
00470         case BOTH_FORCEWALLRUNFLIP_ALT:
00471         case BOTH_FLIP_ATTACK7:
00472         case BOTH_A7_SOULCAL:
00473                 return qtrue;
00474                 break;
00475         }
00476         return qfalse;
00477 }
00478 
00479 qboolean BG_SpinningSaberAnim( int anim )
00480 {
00481         switch ( anim )
00482         {
00483         //level 1 - FIXME: level 1 will have *no* spins
00484         case BOTH_T1_BR_BL:
00485         case BOTH_T1__R__L:
00486         case BOTH_T1__R_BL:
00487         case BOTH_T1_TR_BL:
00488         case BOTH_T1_BR_TL:
00489         case BOTH_T1_BR__L:
00490         case BOTH_T1_TL_BR:
00491         case BOTH_T1__L_BR:
00492         case BOTH_T1__L__R:
00493         case BOTH_T1_BL_BR:
00494         case BOTH_T1_BL__R:
00495         case BOTH_T1_BL_TR:
00496         //level 2
00497         case BOTH_T2_BR__L:
00498         case BOTH_T2_BR_BL:
00499         case BOTH_T2__R_BL:
00500         case BOTH_T2__L_BR:
00501         case BOTH_T2_BL_BR:
00502         case BOTH_T2_BL__R:
00503         //level 3
00504         case BOTH_T3_BR__L:
00505         case BOTH_T3_BR_BL:
00506         case BOTH_T3__R_BL:
00507         case BOTH_T3__L_BR:
00508         case BOTH_T3_BL_BR:
00509         case BOTH_T3_BL__R:
00510         //level 4
00511         case BOTH_T4_BR__L:
00512         case BOTH_T4_BR_BL:
00513         case BOTH_T4__R_BL:
00514         case BOTH_T4__L_BR:
00515         case BOTH_T4_BL_BR:
00516         case BOTH_T4_BL__R:
00517         //level 5
00518         case BOTH_T5_BR_BL:
00519         case BOTH_T5__R__L:
00520         case BOTH_T5__R_BL:
00521         case BOTH_T5_TR_BL:
00522         case BOTH_T5_BR_TL:
00523         case BOTH_T5_BR__L:
00524         case BOTH_T5_TL_BR:
00525         case BOTH_T5__L_BR:
00526         case BOTH_T5__L__R:
00527         case BOTH_T5_BL_BR:
00528         case BOTH_T5_BL__R:
00529         case BOTH_T5_BL_TR:
00530         //level 6
00531         case BOTH_T6_BR_TL:
00532         case BOTH_T6__R_TL:
00533         case BOTH_T6__R__L:
00534         case BOTH_T6__R_BL:
00535         case BOTH_T6_TR_TL:
00536         case BOTH_T6_TR__L:
00537         case BOTH_T6_TR_BL:
00538         case BOTH_T6_T__TL:
00539         case BOTH_T6_T__BL:
00540         case BOTH_T6_TL_BR:
00541         case BOTH_T6__L_BR:
00542         case BOTH_T6__L__R:
00543         case BOTH_T6_TL__R:
00544         case BOTH_T6_TL_TR:
00545         case BOTH_T6__L_TR:
00546         case BOTH_T6__L_T_:
00547         case BOTH_T6_BL_T_:
00548         case BOTH_T6_BR__L:
00549         case BOTH_T6_BR_BL:
00550         case BOTH_T6_BL_BR:
00551         case BOTH_T6_BL__R:
00552         case BOTH_T6_BL_TR:
00553         //level 7
00554         case BOTH_T7_BR_TL:
00555         case BOTH_T7_BR__L:
00556         case BOTH_T7_BR_BL:
00557         case BOTH_T7__R__L:
00558         case BOTH_T7__R_BL:
00559         case BOTH_T7_TR__L:
00560         case BOTH_T7_T___R:
00561         case BOTH_T7_TL_BR:
00562         case BOTH_T7__L_BR:
00563         case BOTH_T7__L__R:
00564         case BOTH_T7_BL_BR:
00565         case BOTH_T7_BL__R:
00566         case BOTH_T7_BL_TR:
00567         case BOTH_T7_TL_TR:
00568         case BOTH_T7_T__BR:
00569         case BOTH_T7__L_TR:
00570         case BOTH_V7_BL_S7:
00571         //special
00572         //case BOTH_A2_STABBACK1:
00573         case BOTH_ATTACK_BACK:
00574         case BOTH_CROUCHATTACKBACK1:
00575         case BOTH_BUTTERFLY_LEFT:
00576         case BOTH_BUTTERFLY_RIGHT:
00577         case BOTH_FJSS_TR_BL:
00578         case BOTH_FJSS_TL_BR:
00579         case BOTH_JUMPFLIPSLASHDOWN1:
00580         case BOTH_JUMPFLIPSTABDOWN:
00581                 return qtrue;
00582                 break;
00583         }
00584         return qfalse;
00585 }
00586 
00587 qboolean BG_SaberInSpecialAttack( int anim )
00588 {
00589         switch ( anim )
00590         {
00591         case BOTH_A2_STABBACK1:
00592         case BOTH_ATTACK_BACK:
00593         case BOTH_CROUCHATTACKBACK1:
00594         case BOTH_ROLL_STAB:
00595         case BOTH_BUTTERFLY_LEFT:
00596         case BOTH_BUTTERFLY_RIGHT:
00597         case BOTH_BUTTERFLY_FL1:
00598         case BOTH_BUTTERFLY_FR1:
00599         case BOTH_FJSS_TR_BL:
00600         case BOTH_FJSS_TL_BR:
00601         case BOTH_LUNGE2_B__T_:
00602         case BOTH_FORCELEAP2_T__B_:
00603         case BOTH_JUMPFLIPSLASHDOWN1://#
00604         case BOTH_JUMPFLIPSTABDOWN://#
00605         case BOTH_JUMPATTACK6:
00606         case BOTH_JUMPATTACK7:
00607         case BOTH_SPINATTACK6:
00608         case BOTH_SPINATTACK7:
00609         case BOTH_FORCELONGLEAP_ATTACK:
00610         case BOTH_VS_ATR_S:
00611         case BOTH_VS_ATL_S:
00612         case BOTH_VT_ATR_S:
00613         case BOTH_VT_ATL_S:
00614         case BOTH_A7_KICK_F:
00615         case BOTH_A7_KICK_B:
00616         case BOTH_A7_KICK_R:
00617         case BOTH_A7_KICK_L:
00618         case BOTH_A7_KICK_S:
00619         case BOTH_A7_KICK_BF:
00620         case BOTH_A7_KICK_RL:
00621         case BOTH_A7_KICK_F_AIR:
00622         case BOTH_A7_KICK_B_AIR:
00623         case BOTH_A7_KICK_R_AIR:
00624         case BOTH_A7_KICK_L_AIR:
00625         case BOTH_STABDOWN:
00626         case BOTH_STABDOWN_STAFF:
00627         case BOTH_STABDOWN_DUAL:
00628         case BOTH_A6_SABERPROTECT:
00629         case BOTH_A7_SOULCAL:
00630         case BOTH_A1_SPECIAL:
00631         case BOTH_A2_SPECIAL:
00632         case BOTH_A3_SPECIAL:
00633         case BOTH_FLIP_ATTACK7:
00634         case BOTH_PULL_IMPALE_STAB:
00635         case BOTH_PULL_IMPALE_SWING:
00636         case BOTH_ALORA_SPIN_SLASH:
00637         case BOTH_A6_FB:
00638         case BOTH_A6_LR:        
00639         case BOTH_A7_HILT:
00640                 return qtrue;
00641         }
00642         return qfalse;
00643 }
00644 
00645 qboolean BG_KickingAnim( int anim )
00646 {
00647         switch ( anim )
00648         {
00649         case BOTH_A7_KICK_F:
00650         case BOTH_A7_KICK_B:
00651         case BOTH_A7_KICK_R:
00652         case BOTH_A7_KICK_L:
00653         case BOTH_A7_KICK_S:
00654         case BOTH_A7_KICK_BF:
00655         case BOTH_A7_KICK_RL:
00656         case BOTH_A7_KICK_F_AIR:
00657         case BOTH_A7_KICK_B_AIR:
00658         case BOTH_A7_KICK_R_AIR:
00659         case BOTH_A7_KICK_L_AIR:
00660         case BOTH_A7_HILT:
00661         //NOT kicks, but do kick traces anyway
00662         case BOTH_GETUP_BROLL_B:
00663         case BOTH_GETUP_BROLL_F:
00664         case BOTH_GETUP_FROLL_B:
00665         case BOTH_GETUP_FROLL_F:
00666                 return qtrue;
00667                 break;
00668         }
00669         return qfalse;
00670 }
00671 
00672 int BG_InGrappleMove(int anim)
00673 {
00674         switch (anim)
00675         {
00676         case BOTH_KYLE_GRAB:
00677         case BOTH_KYLE_MISS:
00678                 return 1; //grabbing at someone
00679         case BOTH_KYLE_PA_1:
00680         case BOTH_KYLE_PA_2:
00681                 return 2; //beating the shit out of someone
00682         case BOTH_PLAYER_PA_1:
00683         case BOTH_PLAYER_PA_2:
00684         case BOTH_PLAYER_PA_FLY:
00685                 return 3; //getting the shit beaten out of you
00686                 break;
00687         }
00688 
00689         return 0;
00690 }
00691 
00692 int BG_BrokenParryForAttack( int move )
00693 {
00694         //Our attack was knocked away by a knockaway parry
00695         //FIXME: need actual anims for this
00696         //FIXME: need to know which side of the saber was hit!  For now, we presume the saber gets knocked away from the center
00697         switch ( saberMoveData[move].startQuad )
00698         {
00699         case Q_B:
00700                 return LS_V1_B_;
00701                 break;
00702         case Q_BR:
00703                 return LS_V1_BR;
00704                 break;
00705         case Q_R:
00706                 return LS_V1__R;
00707                 break;
00708         case Q_TR:
00709                 return LS_V1_TR;
00710                 break;
00711         case Q_T:
00712                 return LS_V1_T_;
00713                 break;
00714         case Q_TL:
00715                 return LS_V1_TL;
00716                 break;
00717         case Q_L:
00718                 return LS_V1__L;
00719                 break;
00720         case Q_BL:
00721                 return LS_V1_BL;
00722                 break;
00723         }
00724         return LS_NONE;
00725 }
00726 
00727 int BG_BrokenParryForParry( int move )
00728 {
00729         //FIXME: need actual anims for this
00730         //FIXME: need to know which side of the saber was hit!  For now, we presume the saber gets knocked away from the center
00731         switch ( move )
00732         {
00733         case LS_PARRY_UP:
00734                 //Hmm... since we don't know what dir the hit came from, randomly pick knock down or knock back
00735                 if ( Q_irand( 0, 1 ) )
00736                 {
00737                         return LS_H1_B_;
00738                 }
00739                 else
00740                 {
00741                         return LS_H1_T_;
00742                 }
00743                 break;
00744         case LS_PARRY_UR:
00745                 return LS_H1_TR;
00746                 break;
00747         case LS_PARRY_UL:
00748                 return LS_H1_TL;
00749                 break;
00750         case LS_PARRY_LR:
00751                 return LS_H1_BR;
00752                 break;
00753         case LS_PARRY_LL:
00754                 return LS_H1_BL;
00755                 break;
00756         case LS_READY:
00757                 return LS_H1_B_;//???
00758                 break;
00759         }
00760         return LS_NONE;
00761 }
00762 
00763 int BG_KnockawayForParry( int move )
00764 {
00765         //FIXME: need actual anims for this
00766         //FIXME: need to know which side of the saber was hit!  For now, we presume the saber gets knocked away from the center
00767         switch ( move )
00768         {
00769         case BLOCKED_TOP://LS_PARRY_UP:
00770                 return LS_K1_T_;//push up
00771                 break;
00772         case BLOCKED_UPPER_RIGHT://LS_PARRY_UR:
00773         default://case LS_READY:
00774                 return LS_K1_TR;//push up, slightly to right
00775                 break;
00776         case BLOCKED_UPPER_LEFT://LS_PARRY_UL:
00777                 return LS_K1_TL;//push up and to left
00778                 break;
00779         case BLOCKED_LOWER_RIGHT://LS_PARRY_LR:
00780                 return LS_K1_BR;//push down and to left
00781                 break;
00782         case BLOCKED_LOWER_LEFT://LS_PARRY_LL:
00783                 return LS_K1_BL;//push down and to right
00784                 break;
00785         }
00786         //return LS_NONE;
00787 }
00788 
00789 qboolean BG_InRoll( playerState_t *ps, int anim )
00790 {
00791         switch ( (anim) )
00792         {
00793         case BOTH_GETUP_BROLL_B:
00794         case BOTH_GETUP_BROLL_F:
00795         case BOTH_GETUP_BROLL_L:
00796         case BOTH_GETUP_BROLL_R:
00797         case BOTH_GETUP_FROLL_B:
00798         case BOTH_GETUP_FROLL_F:
00799         case BOTH_GETUP_FROLL_L:
00800         case BOTH_GETUP_FROLL_R:
00801         case BOTH_ROLL_F:
00802         case BOTH_ROLL_B:
00803         case BOTH_ROLL_R:
00804         case BOTH_ROLL_L:
00805                 if ( ps->legsTimer > 0 )
00806                 {
00807                         return qtrue;
00808                 }
00809                 break;
00810         }
00811         return qfalse;
00812 }
00813 
00814 qboolean BG_InSpecialDeathAnim( int anim )
00815 {
00816         switch( anim )
00817         {
00818         case BOTH_DEATH_ROLL:           //# Death anim from a roll
00819         case BOTH_DEATH_FLIP:           //# Death anim from a flip
00820         case BOTH_DEATH_SPIN_90_R:      //# Death anim when facing 90 degrees right
00821         case BOTH_DEATH_SPIN_90_L:      //# Death anim when facing 90 degrees left
00822         case BOTH_DEATH_SPIN_180:       //# Death anim when facing backwards
00823         case BOTH_DEATH_LYING_UP:       //# Death anim when lying on back
00824         case BOTH_DEATH_LYING_DN:       //# Death anim when lying on front
00825         case BOTH_DEATH_FALLING_DN:     //# Death anim when falling on face
00826         case BOTH_DEATH_FALLING_UP:     //# Death anim when falling on back
00827         case BOTH_DEATH_CROUCHED:       //# Death anim when crouched
00828                 return qtrue;
00829                 break;
00830         default:
00831                 return qfalse;
00832                 break;
00833         }
00834 }
00835 
00836 qboolean BG_InDeathAnim ( int anim )
00837 {//Purposely does not cover stumbledeath and falldeath...
00838         switch( anim )
00839         {
00840         case BOTH_DEATH1:               //# First Death anim
00841         case BOTH_DEATH2:                       //# Second Death anim
00842         case BOTH_DEATH3:                       //# Third Death anim
00843         case BOTH_DEATH4:                       //# Fourth Death anim
00844         case BOTH_DEATH5:                       //# Fifth Death anim
00845         case BOTH_DEATH6:                       //# Sixth Death anim
00846         case BOTH_DEATH7:                       //# Seventh Death anim
00847         case BOTH_DEATH8:                       //# 
00848         case BOTH_DEATH9:                       //# 
00849         case BOTH_DEATH10:                      //# 
00850         case BOTH_DEATH11:                      //#
00851         case BOTH_DEATH12:                      //# 
00852         case BOTH_DEATH13:                      //# 
00853         case BOTH_DEATH14:                      //# 
00854         case BOTH_DEATH14_UNGRIP:       //# Desann's end death (cin #35)
00855         case BOTH_DEATH14_SITUP:                //# Tavion sitting up after having been thrown (cin #23)
00856         case BOTH_DEATH15:                      //# 
00857         case BOTH_DEATH16:                      //# 
00858         case BOTH_DEATH17:                      //# 
00859         case BOTH_DEATH18:                      //# 
00860         case BOTH_DEATH19:                      //# 
00861         case BOTH_DEATH20:                      //# 
00862         case BOTH_DEATH21:                      //# 
00863         case BOTH_DEATH22:                      //# 
00864         case BOTH_DEATH23:                      //# 
00865         case BOTH_DEATH24:                      //# 
00866         case BOTH_DEATH25:                      //# 
00867 
00868         case BOTH_DEATHFORWARD1:                //# First Death in which they get thrown forward
00869         case BOTH_DEATHFORWARD2:                //# Second Death in which they get thrown forward
00870         case BOTH_DEATHFORWARD3:                //# Tavion's falling in cin# 23
00871         case BOTH_DEATHBACKWARD1:       //# First Death in which they get thrown backward
00872         case BOTH_DEATHBACKWARD2:       //# Second Death in which they get thrown backward
00873 
00874         case BOTH_DEATH1IDLE:           //# Idle while close to death
00875         case BOTH_LYINGDEATH1:          //# Death to play when killed lying down
00876         case BOTH_STUMBLEDEATH1:                //# Stumble forward and fall face first death
00877         case BOTH_FALLDEATH1:           //# Fall forward off a high cliff and splat death - start
00878         case BOTH_FALLDEATH1INAIR:      //# Fall forward off a high cliff and splat death - loop
00879         case BOTH_FALLDEATH1LAND:       //# Fall forward off a high cliff and splat death - hit bottom
00880         //# #sep case BOTH_ DEAD POSES # Should be last frame of corresponding previous anims
00881         case BOTH_DEAD1:                                //# First Death finished pose
00882         case BOTH_DEAD2:                                //# Second Death finished pose
00883         case BOTH_DEAD3:                                //# Third Death finished pose
00884         case BOTH_DEAD4:                                //# Fourth Death finished pose
00885         case BOTH_DEAD5:                                //# Fifth Death finished pose
00886         case BOTH_DEAD6:                                //# Sixth Death finished pose
00887         case BOTH_DEAD7:                                //# Seventh Death finished pose
00888         case BOTH_DEAD8:                                //# 
00889         case BOTH_DEAD9:                                //# 
00890         case BOTH_DEAD10:                       //# 
00891         case BOTH_DEAD11:                       //#
00892         case BOTH_DEAD12:                       //# 
00893         case BOTH_DEAD13:                       //# 
00894         case BOTH_DEAD14:                       //# 
00895         case BOTH_DEAD15:                       //# 
00896         case BOTH_DEAD16:                       //# 
00897         case BOTH_DEAD17:                       //# 
00898         case BOTH_DEAD18:                       //# 
00899         case BOTH_DEAD19:                       //# 
00900         case BOTH_DEAD20:                       //# 
00901         case BOTH_DEAD21:                       //# 
00902         case BOTH_DEAD22:                       //# 
00903         case BOTH_DEAD23:                       //# 
00904         case BOTH_DEAD24:                       //# 
00905         case BOTH_DEAD25:                       //# 
00906         case BOTH_DEADFORWARD1:         //# First thrown forward death finished pose
00907         case BOTH_DEADFORWARD2:         //# Second thrown forward death finished pose
00908         case BOTH_DEADBACKWARD1:                //# First thrown backward death finished pose
00909         case BOTH_DEADBACKWARD2:                //# Second thrown backward death finished pose
00910         case BOTH_LYINGDEAD1:           //# Killed lying down death finished pose
00911         case BOTH_STUMBLEDEAD1:         //# Stumble forward death finished pose
00912         case BOTH_FALLDEAD1LAND:                //# Fall forward and splat death finished pose
00913         //# #sep case BOTH_ DEAD TWITCH/FLOP # React to being shot from death poses
00914         case BOTH_DEADFLOP1:            //# React to being shot from First Death finished pose
00915         case BOTH_DEADFLOP2:            //# React to being shot from Second Death finished pose
00916         case BOTH_DISMEMBER_HEAD1:      //#
00917         case BOTH_DISMEMBER_TORSO1:     //#
00918         case BOTH_DISMEMBER_LLEG:       //#
00919         case BOTH_DISMEMBER_RLEG:       //#
00920         case BOTH_DISMEMBER_RARM:       //#
00921         case BOTH_DISMEMBER_LARM:       //#
00922                 return qtrue;
00923                 break;
00924         default:
00925                 return BG_InSpecialDeathAnim( anim );
00926                 break;
00927         }
00928 }
00929 
00930 qboolean BG_InKnockDownOnly( int anim )
00931 {
00932         switch ( anim )
00933         {
00934         case BOTH_KNOCKDOWN1:
00935         case BOTH_KNOCKDOWN2:
00936         case BOTH_KNOCKDOWN3:
00937         case BOTH_KNOCKDOWN4:
00938         case BOTH_KNOCKDOWN5:
00939                 return qtrue;
00940         }
00941         return qfalse;
00942 }
00943 
00944 qboolean BG_InSaberLockOld( int anim )
00945 {
00946         switch ( anim )
00947         {
00948         case BOTH_BF2LOCK:
00949         case BOTH_BF1LOCK:
00950         case BOTH_CWCIRCLELOCK:
00951         case BOTH_CCWCIRCLELOCK:
00952                 return qtrue;
00953         }
00954         return qfalse;
00955 }
00956 
00957 qboolean BG_InSaberLock( int anim ) 
00958 {
00959         switch ( anim )
00960         {
00961         case BOTH_LK_S_DL_S_L_1:                //lock if I'm using single vs. a dual
00962         case BOTH_LK_S_DL_T_L_1:                //lock if I'm using single vs. a dual
00963         case BOTH_LK_S_ST_S_L_1:                //lock if I'm using single vs. a staff
00964         case BOTH_LK_S_ST_T_L_1:                //lock if I'm using single vs. a staff
00965         case BOTH_LK_S_S_S_L_1:         //lock if I'm using single vs. a single and I initiated
00966         case BOTH_LK_S_S_T_L_1:         //lock if I'm using single vs. a single and I initiated
00967         case BOTH_LK_DL_DL_S_L_1:       //lock if I'm using dual vs. dual and I initiated
00968         case BOTH_LK_DL_DL_T_L_1:       //lock if I'm using dual vs. dual and I initiated
00969         case BOTH_LK_DL_ST_S_L_1:       //lock if I'm using dual vs. a staff
00970         case BOTH_LK_DL_ST_T_L_1:       //lock if I'm using dual vs. a staff
00971         case BOTH_LK_DL_S_S_L_1:                //lock if I'm using dual vs. a single
00972         case BOTH_LK_DL_S_T_L_1:                //lock if I'm using dual vs. a single
00973         case BOTH_LK_ST_DL_S_L_1:       //lock if I'm using staff vs. dual
00974         case BOTH_LK_ST_DL_T_L_1:       //lock if I'm using staff vs. dual
00975         case BOTH_LK_ST_ST_S_L_1:       //lock if I'm using staff vs. a staff and I initiated
00976         case BOTH_LK_ST_ST_T_L_1:       //lock if I'm using staff vs. a staff and I initiated
00977         case BOTH_LK_ST_S_S_L_1:                //lock if I'm using staff vs. a single
00978         case BOTH_LK_ST_S_T_L_1:                //lock if I'm using staff vs. a single
00979         case BOTH_LK_S_S_S_L_2:
00980         case BOTH_LK_S_S_T_L_2:
00981         case BOTH_LK_DL_DL_S_L_2:
00982         case BOTH_LK_DL_DL_T_L_2:
00983         case BOTH_LK_ST_ST_S_L_2:
00984         case BOTH_LK_ST_ST_T_L_2:
00985                 return qtrue;
00986                 break;
00987         default:
00988                 return BG_InSaberLockOld( anim );
00989                 break;
00990         }
00991         //return qfalse;
00992 }
00993 
00994 //Called only where pm is valid (not all require pm, but some do):
00995 qboolean PM_InCartwheel( int anim )
00996 {
00997         switch ( anim )
00998         {
00999         case BOTH_ARIAL_LEFT:
01000         case BOTH_ARIAL_RIGHT:
01001         case BOTH_ARIAL_F1:
01002         case BOTH_CARTWHEEL_LEFT:
01003         case BOTH_CARTWHEEL_RIGHT:
01004                 return qtrue;
01005                 break;
01006         }
01007         return qfalse;
01008 }
01009 
01010 qboolean BG_InKnockDownOnGround( playerState_t *ps )
01011 {
01012         switch ( ps->legsAnim )
01013         {
01014         case BOTH_KNOCKDOWN1:
01015         case BOTH_KNOCKDOWN2:
01016         case BOTH_KNOCKDOWN3:
01017         case BOTH_KNOCKDOWN4:
01018         case BOTH_KNOCKDOWN5:
01019         case BOTH_RELEASED:
01020                 //if ( PM_AnimLength( g_entities[ps->clientNum].client->clientInfo.animFileIndex, (animNumber_t)ps->legsAnim ) - ps->legsAnimTimer > 300 )
01021                 {//at end of fall down anim
01022                         return qtrue;
01023                 }
01024                 break;
01025         case BOTH_GETUP1:
01026         case BOTH_GETUP2:
01027         case BOTH_GETUP3:
01028         case BOTH_GETUP4:
01029         case BOTH_GETUP5:
01030         case BOTH_GETUP_CROUCH_F1:
01031         case BOTH_GETUP_CROUCH_B1:
01032         case BOTH_FORCE_GETUP_F1:
01033         case BOTH_FORCE_GETUP_F2:
01034         case BOTH_FORCE_GETUP_B1:
01035         case BOTH_FORCE_GETUP_B2:
01036         case BOTH_FORCE_GETUP_B3:
01037         case BOTH_FORCE_GETUP_B4:
01038         case BOTH_FORCE_GETUP_B5:
01039         case BOTH_FORCE_GETUP_B6:
01040                 if ( BG_AnimLength( 0, (animNumber_t)ps->legsAnim ) - ps->legsTimer < 500 )
01041                 {//at beginning of getup anim
01042                         return qtrue;
01043                 }
01044                 break;
01045         case BOTH_GETUP_BROLL_B:
01046         case BOTH_GETUP_BROLL_F:
01047         case BOTH_GETUP_BROLL_L:
01048         case BOTH_GETUP_BROLL_R:
01049         case BOTH_GETUP_FROLL_B:
01050         case BOTH_GETUP_FROLL_F:
01051         case BOTH_GETUP_FROLL_L:
01052         case BOTH_GETUP_FROLL_R:
01053                 if ( BG_AnimLength( 0, (animNumber_t)ps->legsAnim ) - ps->legsTimer < 500 )
01054                 {//at beginning of getup anim
01055                         return qtrue;
01056                 }
01057                 break;
01058         case BOTH_LK_DL_ST_T_SB_1_L:
01059                 if ( ps->legsTimer < 1000 )
01060                 {
01061                         return qtrue;
01062                 }
01063                 break;
01064         case BOTH_PLAYER_PA_3_FLY:
01065                 if ( ps->legsTimer < 300 )
01066                 {
01067                         return qtrue;
01068                 }
01069                 break;
01070         }
01071         return qfalse;
01072 }
01073 
01074 qboolean BG_StabDownAnim( int anim )
01075 {
01076         switch ( anim )
01077         {
01078         case BOTH_STABDOWN:
01079         case BOTH_STABDOWN_STAFF:
01080         case BOTH_STABDOWN_DUAL:
01081                 return qtrue;
01082         }
01083         return qfalse;
01084 }
01085 
01086 int PM_SaberBounceForAttack( int move )
01087 {
01088         switch ( saberMoveData[move].startQuad )
01089         {
01090         case Q_B:
01091         case Q_BR:
01092                 return LS_B1_BR;
01093                 break;
01094         case Q_R:
01095                 return LS_B1__R;
01096                 break;
01097         case Q_TR:
01098                 return LS_B1_TR;
01099                 break;
01100         case Q_T:
01101                 return LS_B1_T_;
01102                 break;
01103         case Q_TL:
01104                 return LS_B1_TL;
01105                 break;
01106         case Q_L:
01107                 return LS_B1__L;
01108                 break;
01109         case Q_BL:
01110                 return LS_B1_BL;
01111                 break;
01112         }
01113         return LS_NONE;
01114 }
01115 
01116 int PM_SaberDeflectionForQuad( int quad )
01117 {
01118         switch ( quad )
01119         {
01120         case Q_B:
01121                 return LS_D1_B_;
01122                 break;
01123         case Q_BR:
01124                 return LS_D1_BR;
01125                 break;
01126         case Q_R:
01127                 return LS_D1__R;
01128                 break;
01129         case Q_TR:
01130                 return LS_D1_TR;
01131                 break;
01132         case Q_T:
01133                 return LS_D1_T_;
01134                 break;
01135         case Q_TL:
01136                 return LS_D1_TL;
01137                 break;
01138         case Q_L:
01139                 return LS_D1__L;
01140                 break;
01141         case Q_BL:
01142                 return LS_D1_BL;
01143                 break;
01144         }
01145         return LS_NONE;
01146 }
01147 
01148 qboolean PM_SaberInDeflect( int move )
01149 {
01150         if ( move >= LS_D1_BR && move <= LS_D1_B_ )
01151         {
01152                 return qtrue;
01153         }
01154         return qfalse;
01155 }
01156 
01157 qboolean PM_SaberInParry( int move )
01158 {
01159         if ( move >= LS_PARRY_UP && move <= LS_PARRY_LL )
01160         {
01161                 return qtrue;
01162         }
01163         return qfalse;
01164 }
01165 
01166 qboolean PM_SaberInKnockaway( int move )
01167 {
01168         if ( move >= LS_K1_T_ && move <= LS_K1_BL )
01169         {
01170                 return qtrue;
01171         }
01172         return qfalse;
01173 }
01174 
01175 qboolean PM_SaberInReflect( int move )
01176 {
01177         if ( move >= LS_REFLECT_UP && move <= LS_REFLECT_LL )
01178         {
01179                 return qtrue;
01180         }
01181         return qfalse;
01182 }
01183 
01184 qboolean PM_SaberInStart( int move )
01185 {
01186         if ( move >= LS_S_TL2BR && move <= LS_S_T2B )
01187         {
01188                 return qtrue;
01189         }
01190         return qfalse;
01191 }
01192 
01193 qboolean PM_SaberInReturn( int move )
01194 {
01195         if ( move >= LS_R_TL2BR && move <= LS_R_T2B )
01196         {
01197                 return qtrue;
01198         }
01199         return qfalse;
01200 }
01201 
01202 qboolean BG_SaberInReturn( int move )
01203 {
01204         return PM_SaberInReturn( move );
01205 }
01206 
01207 qboolean PM_InSaberAnim( int anim )
01208 {
01209         if ( (anim) >= BOTH_A1_T__B_ && (anim) <= BOTH_H1_S1_BR )
01210         {
01211                 return qtrue;
01212         }
01213         return qfalse;
01214 }
01215 
01216 qboolean PM_InKnockDown( playerState_t *ps )
01217 {
01218         switch ( (ps->legsAnim) )
01219         {
01220         case BOTH_KNOCKDOWN1:
01221         case BOTH_KNOCKDOWN2:
01222         case BOTH_KNOCKDOWN3:
01223         case BOTH_KNOCKDOWN4:
01224         case BOTH_KNOCKDOWN5:
01225                 return qtrue;
01226                 break;
01227         case BOTH_GETUP1:
01228         case BOTH_GETUP2:
01229         case BOTH_GETUP3:
01230         case BOTH_GETUP4:
01231         case BOTH_GETUP5:
01232         case BOTH_FORCE_GETUP_F1:
01233         case BOTH_FORCE_GETUP_F2:
01234         case BOTH_FORCE_GETUP_B1:
01235         case BOTH_FORCE_GETUP_B2:
01236         case BOTH_FORCE_GETUP_B3:
01237         case BOTH_FORCE_GETUP_B4:
01238         case BOTH_FORCE_GETUP_B5:
01239         case BOTH_GETUP_BROLL_B:
01240         case BOTH_GETUP_BROLL_F:
01241         case BOTH_GETUP_BROLL_L:
01242         case BOTH_GETUP_BROLL_R:
01243         case BOTH_GETUP_FROLL_B:
01244         case BOTH_GETUP_FROLL_F:
01245         case BOTH_GETUP_FROLL_L:
01246         case BOTH_GETUP_FROLL_R:
01247                 if ( ps->legsTimer )
01248                 {
01249                         return qtrue;
01250                 }
01251                 break;
01252         }
01253         return qfalse;
01254 }
01255 
01256 qboolean PM_PainAnim( int anim )
01257 {
01258         switch ( (anim) )
01259         {
01260                 case BOTH_PAIN1:                                //# First take pain anim
01261                 case BOTH_PAIN2:                                //# Second take pain anim
01262                 case BOTH_PAIN3:                                //# Third take pain anim
01263                 case BOTH_PAIN4:                                //# Fourth take pain anim
01264                 case BOTH_PAIN5:                                //# Fifth take pain anim - from behind
01265                 case BOTH_PAIN6:                                //# Sixth take pain anim - from behind
01266                 case BOTH_PAIN7:                                //# Seventh take pain anim - from behind
01267                 case BOTH_PAIN8:                                //# Eigth take pain anim - from behind
01268                 case BOTH_PAIN9:                                //# 
01269                 case BOTH_PAIN10:                       //# 
01270                 case BOTH_PAIN11:                       //# 
01271                 case BOTH_PAIN12:                       //# 
01272                 case BOTH_PAIN13:                       //# 
01273                 case BOTH_PAIN14:                       //# 
01274                 case BOTH_PAIN15:                       //# 
01275                 case BOTH_PAIN16:                       //# 
01276                 case BOTH_PAIN17:                       //# 
01277                 case BOTH_PAIN18:                       //# 
01278                 return qtrue;
01279                 break;
01280         }
01281         return qfalse;
01282 }
01283 
01284 qboolean PM_JumpingAnim( int anim )
01285 {
01286         switch ( (anim) )
01287         {
01288                 case BOTH_JUMP1:                                //# Jump - wind-up and leave ground
01289                 case BOTH_INAIR1:                       //# In air loop (from jump)
01290                 case BOTH_LAND1:                                //# Landing (from in air loop)
01291                 case BOTH_LAND2:                                //# Landing Hard (from a great height)
01292                 case BOTH_JUMPBACK1:                    //# Jump backwards - wind-up and leave ground
01293                 case BOTH_INAIRBACK1:           //# In air loop (from jump back)
01294                 case BOTH_LANDBACK1:                    //# Landing backwards(from in air loop)
01295                 case BOTH_JUMPLEFT1:                    //# Jump left - wind-up and leave ground
01296                 case BOTH_INAIRLEFT1:           //# In air loop (from jump left)
01297                 case BOTH_LANDLEFT1:                    //# Landing left(from in air loop)
01298                 case BOTH_JUMPRIGHT1:           //# Jump right - wind-up and leave ground
01299                 case BOTH_INAIRRIGHT1:          //# In air loop (from jump right)
01300                 case BOTH_LANDRIGHT1:           //# Landing right(from in air loop)
01301                 case BOTH_FORCEJUMP1:                           //# Jump - wind-up and leave ground
01302                 case BOTH_FORCEINAIR1:                  //# In air loop (from jump)
01303                 case BOTH_FORCELAND1:                           //# Landing (from in air loop)
01304                 case BOTH_FORCEJUMPBACK1:                       //# Jump backwards - wind-up and leave ground
01305                 case BOTH_FORCEINAIRBACK1:              //# In air loop (from jump back)
01306                 case BOTH_FORCELANDBACK1:                       //# Landing backwards(from in air loop)
01307                 case BOTH_FORCEJUMPLEFT1:                       //# Jump left - wind-up and leave ground
01308                 case BOTH_FORCEINAIRLEFT1:              //# In air loop (from jump left)
01309                 case BOTH_FORCELANDLEFT1:                       //# Landing left(from in air loop)
01310                 case BOTH_FORCEJUMPRIGHT1:              //# Jump right - wind-up and leave ground
01311                 case BOTH_FORCEINAIRRIGHT1:             //# In air loop (from jump right)
01312                 case BOTH_FORCELANDRIGHT1:              //# Landing right(from in air loop)
01313                 return qtrue;
01314                 break;
01315         }
01316         return qfalse;
01317 }
01318 
01319 qboolean PM_LandingAnim( int anim )
01320 {
01321         switch ( (anim) )
01322         {
01323                 case BOTH_LAND1:                                //# Landing (from in air loop)
01324                 case BOTH_LAND2:                                //# Landing Hard (from a great height)
01325                 case BOTH_LANDBACK1:                    //# Landing backwards(from in air loop)
01326                 case BOTH_LANDLEFT1:                    //# Landing left(from in air loop)
01327                 case BOTH_LANDRIGHT1:           //# Landing right(from in air loop)
01328                 case BOTH_FORCELAND1:           //# Landing (from in air loop)
01329                 case BOTH_FORCELANDBACK1:       //# Landing backwards(from in air loop)
01330                 case BOTH_FORCELANDLEFT1:       //# Landing left(from in air loop)
01331                 case BOTH_FORCELANDRIGHT1:      //# Landing right(from in air loop)
01332                 return qtrue;
01333                 break;
01334         }
01335         return qfalse;
01336 }
01337 
01338 qboolean PM_SpinningAnim( int anim )
01339 {
01340         /*
01341         switch ( anim )
01342         {
01343         //FIXME: list any other spinning anims
01344         default:
01345                 break;
01346         }
01347         */
01348         return BG_SpinningSaberAnim( anim );
01349 }
01350 
01351 qboolean PM_InOnGroundAnim ( int anim )
01352 {
01353         switch( anim )
01354         {
01355         case BOTH_DEAD1:
01356         case BOTH_DEAD2:
01357         case BOTH_DEAD3:
01358         case BOTH_DEAD4:
01359         case BOTH_DEAD5:
01360         case BOTH_DEADFORWARD1:
01361         case BOTH_DEADBACKWARD1:
01362         case BOTH_DEADFORWARD2:
01363         case BOTH_DEADBACKWARD2:
01364         case BOTH_LYINGDEATH1:
01365         case BOTH_LYINGDEAD1:
01366         case BOTH_SLEEP1:                       //# laying on back-rknee up-rhand on torso
01367         case BOTH_KNOCKDOWN1:           //# 
01368         case BOTH_KNOCKDOWN2:           //# 
01369         case BOTH_KNOCKDOWN3:           //# 
01370         case BOTH_KNOCKDOWN4:           //# 
01371         case BOTH_KNOCKDOWN5:           //# 
01372         case BOTH_GETUP1:
01373         case BOTH_GETUP2:
01374         case BOTH_GETUP3:
01375         case BOTH_GETUP4:
01376         case BOTH_GETUP5:
01377         case BOTH_GETUP_CROUCH_F1:
01378         case BOTH_GETUP_CROUCH_B1:
01379         case BOTH_FORCE_GETUP_F1:
01380         case BOTH_FORCE_GETUP_F2:
01381         case BOTH_FORCE_GETUP_B1:
01382         case BOTH_FORCE_GETUP_B2:
01383         case BOTH_FORCE_GETUP_B3:
01384         case BOTH_FORCE_GETUP_B4:
01385         case BOTH_FORCE_GETUP_B5:
01386         case BOTH_FORCE_GETUP_B6:
01387         case BOTH_GETUP_BROLL_B:
01388         case BOTH_GETUP_BROLL_F:
01389         case BOTH_GETUP_BROLL_L:
01390         case BOTH_GETUP_BROLL_R:
01391         case BOTH_GETUP_FROLL_B:
01392         case BOTH_GETUP_FROLL_F:
01393         case BOTH_GETUP_FROLL_L:
01394         case BOTH_GETUP_FROLL_R:
01395                 return qtrue;
01396                 break;
01397         }
01398 
01399         return qfalse;
01400 }
01401 
01402 qboolean PM_InRollComplete( playerState_t *ps, int anim )
01403 {
01404         switch ( (anim) )
01405         {
01406         case BOTH_ROLL_F:
01407         case BOTH_ROLL_B:
01408         case BOTH_ROLL_R:
01409         case BOTH_ROLL_L:
01410                 if ( ps->legsTimer < 1 )
01411                 {
01412                         return qtrue;
01413                 }
01414                 break;
01415         }
01416         return qfalse;
01417 }
01418 
01419 qboolean PM_CanRollFromSoulCal( playerState_t *ps )
01420 {
01421         if ( ps->legsAnim == BOTH_A7_SOULCAL
01422                 && ps->legsTimer < 700
01423                 && ps->legsTimer > 250 )
01424         {
01425                 return qtrue;
01426         }
01427         return qfalse;
01428 }
01429 
01430 qboolean BG_SuperBreakLoseAnim( int anim )
01431 {
01432         switch ( anim )
01433         {
01434         case BOTH_LK_S_DL_S_SB_1_L:     //super break I lost
01435         case BOTH_LK_S_DL_T_SB_1_L:     //super break I lost
01436         case BOTH_LK_S_ST_S_SB_1_L:     //super break I lost
01437         case BOTH_LK_S_ST_T_SB_1_L:     //super break I lost
01438         case BOTH_LK_S_S_S_SB_1_L:      //super break I lost
01439         case BOTH_LK_S_S_T_SB_1_L:      //super break I lost
01440         case BOTH_LK_DL_DL_S_SB_1_L:    //super break I lost
01441         case BOTH_LK_DL_DL_T_SB_1_L:    //super break I lost
01442         case BOTH_LK_DL_ST_S_SB_1_L:    //super break I lost
01443         case BOTH_LK_DL_ST_T_SB_1_L:    //super break I lost
01444         case BOTH_LK_DL_S_S_SB_1_L:     //super break I lost
01445         case BOTH_LK_DL_S_T_SB_1_L:     //super break I lost
01446         case BOTH_LK_ST_DL_S_SB_1_L:    //super break I lost
01447         case BOTH_LK_ST_DL_T_SB_1_L:    //super break I lost
01448         case BOTH_LK_ST_ST_S_SB_1_L:    //super break I lost
01449         case BOTH_LK_ST_ST_T_SB_1_L:    //super break I lost
01450         case BOTH_LK_ST_S_S_SB_1_L:     //super break I lost
01451         case BOTH_LK_ST_S_T_SB_1_L:     //super break I lost
01452                 return qtrue;
01453                 break;
01454         }
01455         return qfalse;
01456 }
01457 
01458 qboolean BG_SuperBreakWinAnim( int anim )
01459 {
01460         switch ( anim )
01461         {
01462         case BOTH_LK_S_DL_S_SB_1_W:     //super break I won
01463         case BOTH_LK_S_DL_T_SB_1_W:     //super break I won
01464         case BOTH_LK_S_ST_S_SB_1_W:     //super break I won
01465         case BOTH_LK_S_ST_T_SB_1_W:     //super break I won
01466         case BOTH_LK_S_S_S_SB_1_W:      //super break I won
01467         case BOTH_LK_S_S_T_SB_1_W:      //super break I won
01468         case BOTH_LK_DL_DL_S_SB_1_W:    //super break I won
01469         case BOTH_LK_DL_DL_T_SB_1_W:    //super break I won
01470         case BOTH_LK_DL_ST_S_SB_1_W:    //super break I won
01471         case BOTH_LK_DL_ST_T_SB_1_W:    //super break I won
01472         case BOTH_LK_DL_S_S_SB_1_W:     //super break I won
01473         case BOTH_LK_DL_S_T_SB_1_W:     //super break I won
01474         case BOTH_LK_ST_DL_S_SB_1_W:    //super break I won
01475         case BOTH_LK_ST_DL_T_SB_1_W:    //super break I won
01476         case BOTH_LK_ST_ST_S_SB_1_W:    //super break I won
01477         case BOTH_LK_ST_ST_T_SB_1_W:    //super break I won
01478         case BOTH_LK_ST_S_S_SB_1_W:     //super break I won
01479         case BOTH_LK_ST_S_T_SB_1_W:     //super break I won
01480                 return qtrue;
01481                 break;
01482         }
01483         return qfalse;
01484 }
01485 
01486 
01487 qboolean BG_SaberLockBreakAnim( int anim )
01488 {
01489         switch ( anim )
01490         {
01491         case BOTH_BF1BREAK:
01492         case BOTH_BF2BREAK:
01493         case BOTH_CWCIRCLEBREAK:
01494         case BOTH_CCWCIRCLEBREAK:
01495         case BOTH_LK_S_DL_S_B_1_L:      //normal break I lost
01496         case BOTH_LK_S_DL_S_B_1_W:      //normal break I won
01497         case BOTH_LK_S_DL_T_B_1_L:      //normal break I lost
01498         case BOTH_LK_S_DL_T_B_1_W:      //normal break I won
01499         case BOTH_LK_S_ST_S_B_1_L:      //normal break I lost
01500         case BOTH_LK_S_ST_S_B_1_W:      //normal break I won
01501         case BOTH_LK_S_ST_T_B_1_L:      //normal break I lost
01502         case BOTH_LK_S_ST_T_B_1_W:      //normal break I won
01503         case BOTH_LK_S_S_S_B_1_L:       //normal break I lost
01504         case BOTH_LK_S_S_S_B_1_W:       //normal break I won
01505         case BOTH_LK_S_S_T_B_1_L:       //normal break I lost
01506         case BOTH_LK_S_S_T_B_1_W:       //normal break I won
01507         case BOTH_LK_DL_DL_S_B_1_L:     //normal break I lost
01508         case BOTH_LK_DL_DL_S_B_1_W:     //normal break I won
01509         case BOTH_LK_DL_DL_T_B_1_L:     //normal break I lost
01510         case BOTH_LK_DL_DL_T_B_1_W:     //normal break I won
01511         case BOTH_LK_DL_ST_S_B_1_L:     //normal break I lost
01512         case BOTH_LK_DL_ST_S_B_1_W:     //normal break I won
01513         case BOTH_LK_DL_ST_T_B_1_L:     //normal break I lost
01514         case BOTH_LK_DL_ST_T_B_1_W:     //normal break I won
01515         case BOTH_LK_DL_S_S_B_1_L:      //normal break I lost
01516         case BOTH_LK_DL_S_S_B_1_W:      //normal break I won
01517         case BOTH_LK_DL_S_T_B_1_L:      //normal break I lost
01518         case BOTH_LK_DL_S_T_B_1_W:      //normal break I won
01519         case BOTH_LK_ST_DL_S_B_1_L:     //normal break I lost
01520         case BOTH_LK_ST_DL_S_B_1_W:     //normal break I won
01521         case BOTH_LK_ST_DL_T_B_1_L:     //normal break I lost
01522         case BOTH_LK_ST_DL_T_B_1_W:     //normal break I won
01523         case BOTH_LK_ST_ST_S_B_1_L:     //normal break I lost
01524         case BOTH_LK_ST_ST_S_B_1_W:     //normal break I won
01525         case BOTH_LK_ST_ST_T_B_1_L:     //normal break I lost
01526         case BOTH_LK_ST_ST_T_B_1_W:     //normal break I won
01527         case BOTH_LK_ST_S_S_B_1_L:      //normal break I lost
01528         case BOTH_LK_ST_S_S_B_1_W:      //normal break I won
01529         case BOTH_LK_ST_S_T_B_1_L:      //normal break I lost
01530         case BOTH_LK_ST_S_T_B_1_W:      //normal break I won
01531                 return qtrue;
01532                 break;
01533         }
01534         return (BG_SuperBreakLoseAnim(anim)||BG_SuperBreakWinAnim(anim));
01535 }
01536 
01537 
01538 qboolean BG_FullBodyTauntAnim( int anim )
01539 {
01540         switch ( anim )
01541         {
01542         case BOTH_GESTURE1:
01543         case BOTH_DUAL_TAUNT:
01544         case BOTH_STAFF_TAUNT:
01545         case BOTH_BOW:
01546         case BOTH_MEDITATE:
01547         case BOTH_SHOWOFF_FAST:
01548         case BOTH_SHOWOFF_MEDIUM:
01549         case BOTH_SHOWOFF_STRONG:
01550         case BOTH_SHOWOFF_DUAL:
01551         case BOTH_SHOWOFF_STAFF:
01552         case BOTH_VICTORY_FAST:
01553         case BOTH_VICTORY_MEDIUM:
01554         case BOTH_VICTORY_STRONG:
01555         case BOTH_VICTORY_DUAL:
01556         case BOTH_VICTORY_STAFF:
01557                 return qtrue;
01558                 break;
01559         }
01560         return qfalse;
01561 }
01562 
01563 
01564 /*
01565 =============
01566 BG_AnimLength
01567 
01568 Get the "length" of an anim given the local anim index (which skeleton)
01569 and anim number. Obviously does not take things like the length of the
01570 anim while force speeding (as an example) and whatnot into account.
01571 =============
01572 */
01573 int BG_AnimLength( int index, animNumber_t anim )
01574 {
01575         if (anim >= MAX_ANIMATIONS)
01576         {
01577                 return -1;
01578         }
01579         
01580         return bgAllAnims[index].anims[anim].numFrames * fabs((float)(bgAllAnims[index].anims[anim].frameLerp));
01581 }
01582 
01583 //just use whatever pm->animations is
01584 int PM_AnimLength( int index, animNumber_t anim )
01585 {
01586         if (anim >= MAX_ANIMATIONS || !pm->animations)
01587         {
01588                 return -1;
01589         }
01590         if ( anim < 0 )
01591         {
01592                 Com_Error(ERR_DROP,"ERROR: anim %d < 0\n", anim );
01593         }
01594         return pm->animations[anim].numFrames * fabs((float)(pm->animations[anim].frameLerp));
01595 }
01596 
01597 void PM_DebugLegsAnim(int anim)
01598 {
01599         int oldAnim = (pm->ps->legsAnim);
01600         int newAnim = (anim);
01601 
01602         if (oldAnim < MAX_TOTALANIMATIONS && oldAnim >= BOTH_DEATH1 &&
01603                 newAnim < MAX_TOTALANIMATIONS && newAnim >= BOTH_DEATH1)
01604         {
01605                 Com_Printf("OLD: %s\n", animTable[oldAnim]);
01606                 Com_Printf("NEW: %s\n", animTable[newAnim]);
01607         }
01608 }
01609 
01610 qboolean PM_SaberInTransition( int move )
01611 {
01612         if ( move >= LS_T1_BR__R && move <= LS_T1_BL__L )
01613         {
01614                 return qtrue;
01615         }
01616         return qfalse;
01617 }
01618 
01619 qboolean BG_SaberInTransitionAny( int move )
01620 {
01621         if ( PM_SaberInStart( move ) )
01622         {
01623                 return qtrue;
01624         }
01625         else if ( PM_SaberInTransition( move ) )
01626         {
01627                 return qtrue;
01628         }
01629         else if ( PM_SaberInReturn( move ) )
01630         {
01631                 return qtrue;
01632         }
01633         return qfalse;
01634 }
01635 
01636 /*
01637 ==============================================================================
01638 END: Animation utility functions (sequence checking)
01639 ==============================================================================
01640 */
01641 
01642 void BG_FlipPart(playerState_t *ps, int part)
01643 {
01644         if (part == SETANIM_TORSO)
01645         {
01646                 if (ps->torsoFlip)
01647                 {
01648                         ps->torsoFlip = qfalse;
01649                 }
01650                 else
01651                 {
01652                         ps->torsoFlip = qtrue;
01653                 }
01654         }
01655         else if (part == SETANIM_LEGS)
01656         {
01657                 if (ps->legsFlip)
01658                 {
01659                         ps->legsFlip = qfalse;
01660                 }
01661                 else
01662                 {
01663                         ps->legsFlip = qtrue;
01664                 }
01665         }
01666 }
01667 
01668 #ifdef Q3_VM
01669 char            BGPAFtext[60000];
01670 #endif
01671 qboolean        BGPAFtextLoaded = qfalse;
01672 animation_t     bgHumanoidAnimations[MAX_TOTALANIMATIONS]; //humanoid animations are the only ones that are statically allocated.
01673 
01674 //#define CONVENIENT_ANIMATION_FILE_DEBUG_THING
01675 
01676 #ifdef CONVENIENT_ANIMATION_FILE_DEBUG_THING
01677 void SpewDebugStuffToFile()
01678 {
01679         fileHandle_t f;
01680         int i = 0;
01681 
01682         trap_FS_FOpenFile("file_of_debug_stuff_MP.txt", &f, FS_WRITE);
01683 
01684         if (!f)
01685         {
01686                 return;
01687         }
01688 
01689         BGPAFtext[0] = 0;
01690 
01691         while (i < MAX_ANIMATIONS)
01692         {
01693                 strcat(BGPAFtext, va("%i %i\n", i, bgHumanoidAnimations[i].frameLerp));
01694                 i++;
01695         }
01696 
01697         trap_FS_Write(BGPAFtext, strlen(BGPAFtext), f);
01698         trap_FS_FCloseFile(f);
01699 }
01700 #endif
01701 
01702 bgLoadedAnim_t bgAllAnims[MAX_ANIM_FILES];
01703 int bgNumAllAnims = 2; //start off at 2, because 0 will always be assigned to humanoid, and 1 will always be rockettrooper
01704 
01705 //ALWAYS call on game/cgame init
01706 void BG_InitAnimsets(void)
01707 {
01708         memset(&bgAllAnims, 0, sizeof(bgAllAnims));
01709         BGPAFtextLoaded = qfalse;       // VVFIXME - The PC doesn't seem to need this, but why?
01710 }
01711 
01712 //ALWAYS call on game/cgame shutdown
01713 void BG_ClearAnimsets(void)
01714 {
01715         /*
01716         int i = 1;
01717 
01718         while (i < bgNumAllAnims)
01719         {
01720                 if (bgAllAnims[i].anims)
01721                 {
01722                         strap_TrueFree((void **)&bgAllAnims[i].anims);
01723                 }
01724                 i++;
01725         }
01726         */
01727 }
01728 
01729 animation_t *BG_AnimsetAlloc(void)
01730 {
01731         assert (bgNumAllAnims < MAX_ANIM_FILES);
01732         bgAllAnims[bgNumAllAnims].anims = (animation_t *) BG_Alloc(sizeof(animation_t)*MAX_TOTALANIMATIONS);
01733 
01734         return bgAllAnims[bgNumAllAnims].anims;
01735 }
01736 
01737 void BG_AnimsetFree(animation_t *animset)
01738 {
01739         /*
01740         if (!animset)
01741         {
01742                 return;
01743         }
01744 
01745         strap_TrueFree((void **)&animset);
01746 
01747 #ifdef _DEBUG
01748         if (animset)
01749         {
01750                 assert(!"Failed to free anim set");
01751         }
01752 #endif
01753         */
01754 }
01755 
01756 #ifndef QAGAME //none of this is actually needed serverside. Could just be moved to cgame code but it's here since it
01757                            //used to tie in a lot with the anim loading stuff.
01758 stringID_table_t animEventTypeTable[MAX_ANIM_EVENTS+1] = 
01759 {
01760         ENUM2STRING(AEV_SOUND),                 //# animID AEV_SOUND framenum soundpath randomlow randomhi chancetoplay
01761         ENUM2STRING(AEV_FOOTSTEP),              //# animID AEV_FOOTSTEP framenum footstepType
01762         ENUM2STRING(AEV_EFFECT),                //# animID AEV_EFFECT framenum effectpath boltName
01763         ENUM2STRING(AEV_FIRE),                  //# animID AEV_FIRE framenum altfire chancetofire
01764         ENUM2STRING(AEV_MOVE),                  //# animID AEV_MOVE framenum forwardpush rightpush uppush
01765         ENUM2STRING(AEV_SOUNDCHAN),             //# animID AEV_SOUNDCHAN framenum CHANNEL soundpath randomlow randomhi chancetoplay 
01766         ENUM2STRING(AEV_SABER_SWING),   //# animID AEV_SABER_SWING framenum CHANNEL randomlow randomhi chancetoplay 
01767         ENUM2STRING(AEV_SABER_SPIN),    //# animID AEV_SABER_SPIN framenum CHANNEL chancetoplay 
01768         //must be terminated
01769         NULL,-1
01770 };
01771 
01772 stringID_table_t footstepTypeTable[NUM_FOOTSTEP_TYPES+1] = 
01773 {
01774         ENUM2STRING(FOOTSTEP_R),
01775         ENUM2STRING(FOOTSTEP_L),
01776         ENUM2STRING(FOOTSTEP_HEAVY_R),
01777         ENUM2STRING(FOOTSTEP_HEAVY_L),
01778         //must be terminated
01779         NULL,-1
01780 };
01781 
01782 int CheckAnimFrameForEventType( animevent_t *animEvents, int keyFrame, animEventType_t eventType )
01783 {
01784         int i;
01785 
01786         for ( i = 0; i < MAX_ANIM_EVENTS; i++ )
01787         {
01788                 if ( animEvents[i].keyFrame == keyFrame )
01789                 {//there is an animevent on this frame already
01790                         if ( animEvents[i].eventType == eventType )
01791                         {//and it is of the same type
01792                                 return i;
01793                         }
01794                 }
01795         }
01796         //nope
01797         return -1;
01798 }
01799 
01800 void ParseAnimationEvtBlock(const char *aeb_filename, animevent_t *animEvents, animation_t *animations, int *i,const char **text_p) 
01801 {
01802         const char              *token;
01803         int                             num, n, animNum, keyFrame, lowestVal, highestVal, curAnimEvent, lastAnimEvent = 0;
01804         animEventType_t eventType;
01805         char                    stringData[MAX_QPATH];
01806 
01807         // get past starting bracket
01808         while(1) 
01809         {
01810                 token = COM_Parse( text_p );
01811                 if ( !Q_stricmp( token, "{" ) ) 
01812                 {
01813                         break;
01814                 }
01815         }
01816 
01817         //NOTE: instead of a blind increment, increase the index
01818         //                      this way if we have an event on an anim that already
01819         //                      has an event of that type, it stomps it
01820 
01821         // read information for each frame
01822         while ( 1 ) 
01823         {
01824                 if ( lastAnimEvent >= MAX_ANIM_EVENTS )
01825                 {
01826                         Com_Error( ERR_DROP, "ParseAnimationEvtBlock: number events in animEvent file %s > MAX_ANIM_EVENTS(%i)", aeb_filename, MAX_ANIM_EVENTS );
01827                         return;
01828                 }
01829                 // Get base frame of sequence
01830                 token = COM_Parse( text_p );
01831                 if ( !token || !token[0]) 
01832                 {
01833                         break;
01834                 }
01835 
01836                 if ( !Q_stricmp( token, "}" ) )         // At end of block 
01837                 {
01838                         break;
01839                 }
01840 
01841                 //Compare to same table as animations used 
01842                 //      so we don't have to use actual numbers for animation first frames,
01843                 //      just need offsets.
01844                 //This way when animation numbers change, this table won't have to be updated,
01845                 //      at least not much.
01846                 animNum = GetIDForString(animTable, token);
01847                 if(animNum == -1)
01848                 {//Unrecognized ANIM ENUM name, or we're skipping this line, keep going till you get a good one
01849                         Com_Printf(S_COLOR_YELLOW"WARNING: Unknown token %s in animEvent file %s\n", token, aeb_filename );
01850                         while (token[0])
01851                         {
01852                                 token = COM_ParseExt( text_p, qfalse ); //returns empty string when next token is EOL
01853                         }
01854                         continue;
01855                 }
01856 
01857                 if ( animations[animNum].numFrames == 0 )
01858                 {//we don't use this anim
01859                         Com_Printf(S_COLOR_YELLOW"WARNING: %s animevents.cfg: anim %s not used by this model\n", aeb_filename, token);
01860                         //skip this entry
01861                         SkipRestOfLine( text_p );
01862                         continue;
01863                 }
01864 
01865                 token = COM_Parse( text_p );
01866                 eventType = (animEventType_t)GetIDForString(animEventTypeTable, token);
01867                 if ( eventType == AEV_NONE || eventType == -1 )
01868                 {//Unrecognized ANIM EVENT TYOE, or we're skipping this line, keep going till you get a good one
01869                         //Com_Printf(S_COLOR_YELLOW"WARNING: Unknown token %s in animEvent file %s\n", token, aeb_filename );
01870                         continue;
01871                 }
01872 
01873                 //set our start frame
01874                 keyFrame = animations[animNum].firstFrame;
01875                 // Get offset to frame within sequence
01876                 token = COM_Parse( text_p );
01877                 if ( !token ) 
01878                 {
01879                         break;
01880                 }
01881                 keyFrame += atoi( token );
01882 
01883                 //see if this frame already has an event of this type on it, if so, overwrite it
01884                 curAnimEvent = CheckAnimFrameForEventType( animEvents, keyFrame, eventType );
01885                 if ( curAnimEvent == -1 )
01886                 {//this anim frame doesn't already have an event of this type on it
01887                         curAnimEvent = lastAnimEvent;
01888                 }
01889 
01890                 //now that we know which event index we're going to plug the data into, start doing it
01891                 animEvents[curAnimEvent].eventType = eventType;
01892                 animEvents[curAnimEvent].keyFrame = keyFrame;
01893 
01894                 //now read out the proper data based on the type
01895                 switch ( animEvents[curAnimEvent].eventType )
01896                 {
01897                 case AEV_SOUNDCHAN:             //# animID AEV_SOUNDCHAN framenum CHANNEL soundpath randomlow randomhi chancetoplay
01898                         token = COM_Parse( text_p );
01899                         if ( !token ) 
01900                         {
01901                                 break;
01902                         }
01903                         if ( stricmp( token, "CHAN_VOICE_ATTEN" ) == 0 )
01904                         {
01905                                 animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_VOICE_ATTEN;
01906                         }
01907                         else if ( stricmp( token, "CHAN_VOICE_GLOBAL" ) == 0 )
01908                         {
01909                                 animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_VOICE_GLOBAL;
01910                         }
01911                         else if ( stricmp( token, "CHAN_ANNOUNCER" ) == 0 )
01912                         {
01913                                 animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_ANNOUNCER;
01914                         }
01915                         else if ( stricmp( token, "CHAN_BODY" ) == 0 )
01916                         {
01917                                 animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_BODY;
01918                         }
01919                         else if ( stricmp( token, "CHAN_WEAPON" ) == 0 )
01920                         {
01921                                 animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_WEAPON;
01922                         }
01923                         else if ( stricmp( token, "CHAN_VOICE" ) == 0 )
01924                         {
01925                                 animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_VOICE;
01926                         } 
01927                         else
01928                         {
01929                                 animEvents[curAnimEvent].eventData[AED_SOUNDCHANNEL] = CHAN_AUTO;
01930                         }
01931                         //fall through to normal sound
01932                 case AEV_SOUND:                 //# animID AEV_SOUND framenum soundpath randomlow randomhi chancetoplay
01933                         //get soundstring
01934                         token = COM_Parse( text_p );
01935                         if ( !token ) 
01936                         {
01937                                 break;
01938                         }               
01939                         strcpy(stringData, token);
01940                         //get lowest value
01941                         token = COM_Parse( text_p );
01942                         if ( !token ) 
01943                         {//WARNING!  BAD TABLE!
01944                                 break;
01945                         }
01946                         lowestVal = atoi( token );
01947                         //get highest value
01948                         token = COM_Parse( text_p );
01949                         if ( !token ) 
01950                         {//WARNING!  BAD TABLE!
01951                                 break;
01952                         }
01953                         highestVal = atoi( token );
01954                         //Now precache all the sounds
01955                         //NOTE: If we can be assured sequential handles, we can store sound indices
01956                         //              instead of strings, unfortunately, if these sounds were previously
01957                         //              registered, we cannot be guaranteed sequential indices.  Thus an array
01958                         if(lowestVal && highestVal)
01959                         {
01960                                 //assert(highestVal - lowestVal < MAX_RANDOM_ANIM_SOUNDS);
01961                                 if ((highestVal-lowestVal) >= MAX_RANDOM_ANIM_SOUNDS)
01962                                 {
01963                                         highestVal = lowestVal + (MAX_RANDOM_ANIM_SOUNDS-1);
01964                                 }
01965                                 for ( n = lowestVal, num = AED_SOUNDINDEX_START; n <= highestVal && num <= AED_SOUNDINDEX_END; n++, num++ )
01966                                 {
01967                                         if (stringData[0] == '*')
01968                                         { //FIXME? Would be nice to make custom sounds work with animEvents.
01969                                                 animEvents[curAnimEvent].eventData[num] = 0;
01970                                         }
01971                                         else
01972                                         {
01973                                                 animEvents[curAnimEvent].eventData[num] = trap_S_RegisterSound( va( stringData, n ) );
01974                                         }
01975                                 }
01976                                 animEvents[curAnimEvent].eventData[AED_SOUND_NUMRANDOMSNDS] = num - 1;
01977                         }
01978                         else
01979                         {
01980                                 if (stringData[0] == '*')
01981                                 { //FIXME? Would be nice to make custom sounds work with animEvents.
01982                                         animEvents[curAnimEvent].eventData[AED_SOUNDINDEX_START] = 0;
01983                                 }
01984                                 else
01985                                 {
01986                                         animEvents[curAnimEvent].eventData[AED_SOUNDINDEX_START] = trap_S_RegisterSound( stringData );
01987                                 }
01988 #ifndef FINAL_BUILD
01989                                 if ( !animEvents[curAnimEvent].eventData[AED_SOUNDINDEX_START] &&
01990                                          stringData[0] != '*')
01991                                 {//couldn't register it - file not found
01992                                         Com_Printf( S_COLOR_RED "ParseAnimationSndBlock: sound %s does not exist (animevents.cfg %s)!\n", stringData, aeb_filename );
01993                                 }
01994 #endif
01995                                 animEvents[curAnimEvent].eventData[AED_SOUND_NUMRANDOMSNDS] = 0;
01996                         }
01997                         //get probability
01998                         token = COM_Parse( text_p );
01999                         if ( !token ) 
02000                         {//WARNING!  BAD TABLE!
02001                                 break;
02002                         }
02003                         animEvents[curAnimEvent].eventData[AED_SOUND_PROBABILITY] = atoi( token );
02004 
02005                         //last part - cheat and check and see if it's a special overridable saber sound we know of...
02006                         if ( !Q_stricmpn( "sound/weapons/saber/saberhup", stringData, 28 ) )
02007                         {//a saber swing
02008                                 animEvents[curAnimEvent].eventType = AEV_SABER_SWING;
02009                                 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
02010                                 animEvents[curAnimEvent].eventData[AED_SABER_SWING_PROBABILITY] = animEvents[curAnimEvent].eventData[AED_SOUND_PROBABILITY];
02011                                 if ( lowestVal < 4 )
02012                                 {//fast swing
02013                                         animEvents[curAnimEvent].eventData[AED_SABER_SWING_TYPE] = 0;//SWING_FAST;
02014                                 }
02015                                 else if ( lowestVal < 7 )
02016                                 {//medium swing
02017                                         animEvents[curAnimEvent].eventData[AED_SABER_SWING_TYPE] = 1;//SWING_MEDIUM;
02018                                 }
02019                                 else
02020                                 {//strong swing
02021                                         animEvents[curAnimEvent].eventData[AED_SABER_SWING_TYPE] = 2;//SWING_STRONG;
02022                                 }
02023                         }
02024                         else if ( !Q_stricmpn( "sound/weapons/saber/saberspin", stringData, 29 ) )
02025                         {//a saber spin
02026                                 animEvents[curAnimEvent].eventType = AEV_SABER_SPIN;
02027                                 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
02028                                 animEvents[curAnimEvent].eventData[AED_SABER_SPIN_PROBABILITY] = animEvents[curAnimEvent].eventData[AED_SOUND_PROBABILITY];
02029                                 if ( stringData[29] == 'o' )
02030                                 {//saberspinoff
02031                                         animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 0;
02032                                 }
02033                                 else if ( stringData[29] == '1' )
02034                                 {//saberspin1
02035                                         animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 2;
02036                                 }
02037                                 else if ( stringData[29] == '2' )
02038                                 {//saberspin2
02039                                         animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 3;
02040                                 }
02041                                 else if ( stringData[29] == '3' )
02042                                 {//saberspin3
02043                                         animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 4;
02044                                 }
02045                                 else if ( stringData[29] == '%' )
02046                                 {//saberspin%d
02047                                         animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 5;
02048                                 }
02049                                 else
02050                                 {//just plain saberspin
02051                                         animEvents[curAnimEvent].eventData[AED_SABER_SPIN_TYPE] = 1;
02052                                 }
02053                         }
02054                         break;
02055                 case AEV_FOOTSTEP:              //# animID AEV_FOOTSTEP framenum footstepType
02056                         //get footstep type
02057                         token = COM_Parse( text_p );
02058                         if ( !token ) 
02059                         {
02060                                 break;
02061                         }               
02062                         animEvents[curAnimEvent].eventData[AED_FOOTSTEP_TYPE] = GetIDForString(footstepTypeTable, token);
02063                         //get probability
02064                         token = COM_Parse( text_p );
02065                         if ( !token ) 
02066                         {//WARNING!  BAD TABLE!
02067                                 break;
02068                         }
02069                         animEvents[curAnimEvent].eventData[AED_FOOTSTEP_PROBABILITY] = atoi( token );
02070                         break;
02071                 case AEV_EFFECT:                //# animID AEV_EFFECT framenum effectpath boltName
02072                         //get effect index
02073                         token = COM_Parse( text_p );
02074                         if ( !token ) 
02075                         {
02076                                 break;
02077                         }
02078                         animEvents[curAnimEvent].eventData[AED_EFFECTINDEX] = trap_FX_RegisterEffect( token );
02079                         //get bolt index
02080                         token = COM_Parse( text_p );
02081                         if ( !token ) 
02082                         {
02083                                 break;
02084                         }               
02085                         if ( Q_stricmp( "none", token ) != 0 && Q_stricmp( "NULL", token ) != 0 )
02086                         {//actually are specifying a bolt to use
02087                                 if (!animEvents[curAnimEvent].stringData)
02088                                 { //eh, whatever. no dynamic stuff, so this will do.
02089                                         animEvents[curAnimEvent].stringData = (char *) BG_Alloc(2048);
02090                                 }
02091                                 strcpy(animEvents[curAnimEvent].stringData, token);
02092                         }
02093                         //NOTE: this string will later be used to add a bolt and store the index, as below:
02094                         //animEvent->eventData[AED_BOLTINDEX] = gi.G2API_AddBolt( &cent->gent->ghoul2[cent->gent->playerModel], animEvent->stringData );
02095                         //get probability
02096                         token = COM_Parse( text_p );
02097                         if ( !token ) 
02098                         {//WARNING!  BAD TABLE!
02099                                 break;
02100                         }
02101                         animEvents[curAnimEvent].eventData[AED_EFFECT_PROBABILITY] = atoi( token );
02102                         break;
02103                 case AEV_FIRE:                  //# animID AEV_FIRE framenum altfire chancetofire
02104                         //get altfire
02105                         token = COM_Parse( text_p );
02106                         if ( !token ) 
02107                         {//WARNING!  BAD TABLE!
02108                                 break;
02109                         }
02110                         animEvents[curAnimEvent].eventData[AED_FIRE_ALT] = atoi( token );
02111                         //get probability
02112                         token = COM_Parse( text_p );
02113                         if ( !token ) 
02114                         {//WARNING!  BAD TABLE!
02115                                 break;
02116                         }
02117                         animEvents[curAnimEvent].eventData[AED_FIRE_PROBABILITY] = atoi( token );
02118                         break;
02119                 case AEV_MOVE:                  //# animID AEV_MOVE framenum forwardpush rightpush uppush
02120                         //get forward push
02121                         token = COM_Parse( text_p );
02122                         if ( !token ) 
02123                         {//WARNING!  BAD TABLE!
02124                                 break;
02125                         }
02126                         animEvents[curAnimEvent].eventData[AED_MOVE_FWD] = atoi( token );
02127                         //get right push
02128                         token = COM_Parse( text_p );
02129                         if ( !token ) 
02130                         {//WARNING!  BAD TABLE!
02131                                 break;
02132                         }
02133                         animEvents[curAnimEvent].eventData[AED_MOVE_RT] = atoi( token );
02134                         //get upwards push
02135                         token = COM_Parse( text_p );
02136                         if ( !token ) 
02137                         {//WARNING!  BAD TABLE!
02138                                 break;
02139                         }
02140                         animEvents[curAnimEvent].eventData[AED_MOVE_UP] = atoi( token );
02141                         break;
02142                 default:                                //unknown?
02143                         SkipRestOfLine( text_p );
02144                         continue;
02145                         break;
02146                 }
02147 
02148                 if ( curAnimEvent == lastAnimEvent )
02149                 {
02150                         lastAnimEvent++;
02151                 }
02152         }       
02153 }
02154 
02155 /*
02156 ======================
02157 BG_ParseAnimationEvtFile
02158 
02159 Read a configuration file containing animation events
02160 models/players/kyle/animevents.cfg, etc
02161 
02162 This file's presence is not required
02163 
02164 ======================
02165 */
02166 bgLoadedEvents_t bgAllEvents[MAX_ANIM_FILES];
02167 int bgNumAnimEvents = 1;
02168 static int bg_animParseIncluding = 0;
02169 int BG_ParseAnimationEvtFile( const char *as_filename, int animFileIndex, int eventFileIndex ) 
02170 {
02171         const char      *text_p;
02172         int                     len;
02173         const char      *token;
02174         char            text[80000];
02175         char            sfilename[MAX_QPATH];
02176         fileHandle_t    f;
02177         int                     i, j, upper_i, lower_i;
02178         int                             usedIndex = -1;
02179         animevent_t     *legsAnimEvents;
02180         animevent_t     *torsoAnimEvents;
02181         animation_t             *animations;
02182         int                             forcedIndex;
02183         
02184         assert(animFileIndex < MAX_ANIM_FILES);
02185         assert(eventFileIndex < MAX_ANIM_FILES);
02186 
02187         if (eventFileIndex == -1)
02188         {
02189                 forcedIndex = 0;
02190         }
02191         else
02192         {
02193                 forcedIndex = eventFileIndex;
02194         }
02195 
02196         if (bg_animParseIncluding <= 0)
02197         { //if we should be parsing an included file, skip this part
02198                 if ( bgAllEvents[forcedIndex].eventsParsed )
02199                 {//already cached this one
02200                         return forcedIndex;
02201                 }
02202         }
02203 
02204         legsAnimEvents = bgAllEvents[forcedIndex].legsAnimEvents;
02205         torsoAnimEvents = bgAllEvents[forcedIndex].torsoAnimEvents;
02206         animations = bgAllAnims[animFileIndex].anims;
02207 
02208         if (bg_animParseIncluding <= 0)
02209         { //if we should be parsing an included file, skip this part
02210                 //Go through and see if this filename is already in the table.
02211                 i = 0;
02212                 while (i < bgNumAnimEvents && forcedIndex != 0)
02213                 {
02214                         if (!Q_stricmp(as_filename, bgAllEvents[i].filename))
02215                         { //looks like we have it already.
02216                                 return i;
02217                         }
02218                         i++;
02219                 }
02220         }
02221 
02222         // Load and parse animevents.cfg file
02223         Com_sprintf( sfilename, sizeof( sfilename ), "%sanimevents.cfg", as_filename );
02224 
02225         if (bg_animParseIncluding <= 0)
02226         { //should already be done if we're including
02227                 //initialize anim event array
02228                 for( i = 0; i < MAX_ANIM_EVENTS; i++ )
02229                 {
02230                         //Type of event
02231                         torsoAnimEvents[i].eventType = AEV_NONE;
02232                         legsAnimEvents[i].eventType = AEV_NONE;
02233                         //Frame to play event on
02234                         torsoAnimEvents[i].keyFrame = -1;       
02235                         legsAnimEvents[i].keyFrame = -1;
02236                         //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)
02237                         torsoAnimEvents[i].stringData = NULL;
02238                         legsAnimEvents[i].stringData = NULL;
02239                         //Unique IDs, can be soundIndex of sound file to play OR effect index or footstep type, etc.
02240                         for ( j = 0; j < AED_ARRAY_SIZE; j++ )
02241                         {
02242                                 torsoAnimEvents[i].eventData[j] = -1;
02243                                 legsAnimEvents[i].eventData[j] = -1;
02244                         }
02245                 }
02246         }
02247 
02248         // load the file
02249         len = trap_FS_FOpenFile( sfilename, &f, FS_READ );
02250         if ( len <= 0 ) 
02251         {//no file
02252                 goto fin;
02253         }
02254         if ( len >= sizeof( text ) - 1 ) 
02255         {
02256                 trap_FS_FCloseFile(f);
02257 #ifndef FINAL_BUILD
02258                 Com_Error(ERR_DROP, "File %s too long\n", sfilename );
02259 #else
02260                 Com_Printf( "File %s too long\n", sfilename );
02261 #endif
02262                 goto fin;
02263         }
02264 
02265         trap_FS_Read( text, len, f );
02266         text[len] = 0;
02267         trap_FS_FCloseFile( f );
02268 
02269         // parse the text
02270         text_p = text;
02271         upper_i =0;
02272         lower_i =0;
02273 
02274         // read information for batches of sounds (UPPER or LOWER)
02275         while ( 1 ) 
02276         {
02277                 // Get base frame of sequence
02278                 token = COM_Parse( &text_p );
02279                 if ( !token || !token[0] ) 
02280                 {
02281                         break;
02282                 }
02283 
02284                 if ( !Q_stricmp(token,"include") )      // grab from another animevents.cfg
02285                 {//NOTE: you REALLY should NOT do this after the main block of UPPERSOUNDS and LOWERSOUNDS
02286                         const char      *include_filename = COM_Parse( &text_p );
02287                         if ( include_filename != NULL )
02288                         {
02289                                 char fullIPath[MAX_QPATH];
02290                                 strcpy(fullIPath, va("models/players/%s/", include_filename));
02291                                 bg_animParseIncluding++;
02292                                 BG_ParseAnimationEvtFile( fullIPath, animFileIndex, forcedIndex );
02293                                 bg_animParseIncluding--;
02294                         }
02295                 }
02296 
02297                 if ( !Q_stricmp(token,"UPPEREVENTS") )  // A batch of upper sounds
02298                 {
02299                         ParseAnimationEvtBlock( as_filename, torsoAnimEvents, animations, &upper_i, &text_p ); 
02300                 }
02301 
02302                 else if ( !Q_stricmp(token,"LOWEREVENTS") )     // A batch of lower sounds
02303                 {
02304                         ParseAnimationEvtBlock( as_filename, legsAnimEvents, animations, &lower_i, &text_p ); 
02305                 }
02306         }
02307 
02308         usedIndex = forcedIndex;
02309 fin:
02310         //Mark this anim set so that we know we tried to load he sounds, don't care if the load failed
02311         if (bg_animParseIncluding <= 0)
02312         { //if we should be parsing an included file, skip this part
02313                 bgAllEvents[forcedIndex].eventsParsed = qtrue;
02314                 strcpy(bgAllEvents[forcedIndex].filename, as_filename);
02315                 if (forcedIndex)
02316                 {
02317                         bgNumAnimEvents++;
02318                 }
02319         }
02320 
02321         return usedIndex;
02322 }
02323 #endif
02324 
02325 /*
02326 ======================
02327 BG_ParseAnimationFile
02328 
02329 Read a configuration file containing animation coutns and rates
02330 models/players/visor/animation.cfg, etc
02331 
02332 ======================
02333 */
02334 int BG_ParseAnimationFile(const char *filename, animation_t *animset, qboolean isHumanoid) 
02335 {
02336         char            *text_p;
02337         int                     len;
02338         int                     i;
02339         char            *token;
02340         float           fps;
02341         int                     skip;
02342         int                     usedIndex = -1;
02343         int                     nextIndex = bgNumAllAnims;
02344         qboolean        dynAlloc = qfalse;
02345         qboolean        wasLoaded = qfalse;
02346 #ifndef Q3_VM
02347         char            BGPAFtext[60000];
02348 #endif
02349 
02350         fileHandle_t    f;
02351         int                             animNum;
02352 
02353         if (!isHumanoid)
02354         {
02355                 i = 0;
02356                 while (i < bgNumAllAnims)
02357                 { //see if it's been loaded already
02358                         if (!Q_stricmp(bgAllAnims[i].filename, filename))
02359                         {
02360                                 animset = bgAllAnims[i].anims;
02361                                 return i; //alright, we already have it.
02362                         }
02363                         i++;
02364                 }
02365 
02366                 //Looks like it has not yet been loaded. Allocate space for the anim set if we need to, and continue along.
02367                 if (!animset)
02368                 {
02369                         if (strstr(filename, "players/_humanoid/"))
02370                         { //then use the static humanoid set.
02371                                 animset = bgHumanoidAnimations;
02372                                 nextIndex = 0;
02373                         }
02374                         else if (strstr(filename, "players/rockettrooper/"))
02375                         { //rockettrooper always index 1
02376                                 nextIndex = 1;
02377                                 animset = BG_AnimsetAlloc();
02378                                 dynAlloc = qtrue; //so we know to free this memory in case we have to return early. Don't want any leaks.
02379 
02380                                 if (!animset)
02381                                 {
02382                                         assert(!"Anim set alloc failed!");
02383                                         return -1;
02384                                 }
02385                         }
02386                         else
02387                         {
02388                                 animset = BG_AnimsetAlloc();
02389                                 dynAlloc = qtrue; //so we know to free this memory in case we have to return early. Don't want any leaks.
02390 
02391                                 if (!animset)
02392                                 {
02393                                         assert(!"Anim set alloc failed!");
02394                                         return -1;
02395                                 }
02396                         }
02397                 }
02398         }
02399 #ifdef _DEBUG
02400         else
02401         {
02402                 assert(animset);
02403         }
02404 #endif
02405 
02406         // load the file
02407         if (!BGPAFtextLoaded || !isHumanoid)
02408         { //rww - We are always using the same animation config now. So only load it once.
02409                 len = trap_FS_FOpenFile( filename, &f, FS_READ );
02410                 if ( (len <= 0) || (len >= sizeof( BGPAFtext ) - 1) ) 
02411                 {
02412                         if (dynAlloc)
02413                         {
02414                                 BG_AnimsetFree(animset);
02415                         }
02416                         if (len > 0)
02417                         {
02418                                 Com_Error(ERR_DROP, "%s exceeds the allowed game-side animation buffer!", filename);
02419                         }
02420                         return -1;
02421                 }
02422 
02423                 trap_FS_Read( BGPAFtext, len, f );
02424                 BGPAFtext[len] = 0;
02425                 trap_FS_FCloseFile( f );
02426         }
02427         else
02428         {
02429                 if (dynAlloc)
02430                 {
02431                         assert(!"Should not have allocated dynamically for humanoid");
02432                         BG_AnimsetFree(animset);
02433                 }
02434                 return 0; //humanoid index
02435         }
02436 
02437         // parse the text
02438         text_p = BGPAFtext;
02439         skip = 0;       // quiet the compiler warning
02440 
02441         //FIXME: have some way of playing anims backwards... negative numFrames?
02442 
02443         //initialize anim array so that from 0 to MAX_ANIMATIONS, set default values of 0 1 0 100
02444         for(i = 0; i < MAX_ANIMATIONS; i++)
02445         {
02446                 animset[i].firstFrame = 0;
02447                 animset[i].numFrames = 0;
02448                 animset[i].loopFrames = -1;
02449                 animset[i].frameLerp = 100;
02450         }
02451 
02452         // read information for each frame
02453         while(1) 
02454         {
02455                 token = COM_Parse( (const char **)(&text_p) );
02456 
02457                 if ( !token || !token[0]) 
02458                 {
02459                         break;
02460                 }
02461 
02462                 animNum = GetIDForString(animTable, token);
02463                 if(animNum == -1)
02464                 {
02465 //#ifndef FINAL_BUILD
02466 #ifdef _DEBUG
02467                         Com_Printf(S_COLOR_RED"WARNING: Unknown token %s in %s\n", token, filename);
02468                         while (token[0])
02469                         {
02470                                 token = COM_ParseExt( (const char **) &text_p, qfalse );        //returns empty string when next token is EOL
02471                         }
02472 #endif
02473                         continue;
02474                 }
02475 
02476                 token = COM_Parse( (const char **)(&text_p) );
02477                 if ( !token ) 
02478                 {
02479                         break;
02480                 }
02481                 animset[animNum].firstFrame = atoi( token );
02482 
02483                 token = COM_Parse( (const char **)(&text_p) );
02484                 if ( !token ) 
02485                 {
02486                         break;
02487                 }
02488                 animset[animNum].numFrames = atoi( token );
02489 
02490                 token = COM_Parse( (const char **)(&text_p) );
02491                 if ( !token ) 
02492                 {
02493                         break;
02494                 }
02495                 animset[animNum].loopFrames = atoi( token );
02496 
02497                 token = COM_Parse( (const char **)(&text_p) );
02498                 if ( !token ) 
02499                 {
02500                         break;
02501                 }
02502                 fps = atof( token );
02503                 if ( fps == 0 ) 
02504                 {
02505                         fps = 1;//Don't allow divide by zero error
02506                 }
02507                 if ( fps < 0 )
02508                 {//backwards
02509                         animset[animNum].frameLerp = floor(1000.0f / fps);
02510                 }
02511                 else
02512                 {
02513                         animset[animNum].frameLerp = ceil(1000.0f / fps);
02514                 }
02515         }
02516 /*
02517 #ifdef _DEBUG
02518         //Check the array, and print the ones that have nothing in them.
02519         for(i = 0; i < MAX_ANIMATIONS; i++)
02520         {       
02521                 if (animTable[i].name != NULL)          // This animation reference exists.
02522                 {
02523                         if (animset[i].firstFrame <= 0 && animset[i].numFrames <=0)
02524                         {       // This is an empty animation reference.
02525                                 Com_Printf("***ANIMTABLE reference #%d (%s) is empty!\n", i, animTable[i].name);
02526                         }
02527                 }
02528         }
02529 #endif // _DEBUG
02530 */
02531 #ifdef CONVENIENT_ANIMATION_FILE_DEBUG_THING
02532         SpewDebugStuffToFile();
02533 #endif
02534 
02535         wasLoaded = BGPAFtextLoaded;
02536 
02537         if (isHumanoid)
02538         {
02539                 bgAllAnims[0].anims = animset;
02540                 strcpy(bgAllAnims[0].filename, filename);
02541                 BGPAFtextLoaded = qtrue;
02542 
02543                 usedIndex = 0;
02544         }
02545         else
02546         {
02547                 bgAllAnims[nextIndex].anims = animset;
02548                 strcpy(bgAllAnims[nextIndex].filename, filename);
02549 
02550                 usedIndex = bgNumAllAnims;
02551 
02552                 if (nextIndex > 1)
02553                 { //don't bother increasing the number if this ended up as a humanoid/rockettrooper load.
02554                         bgNumAllAnims++;
02555                 }
02556                 else
02557                 {
02558                         BGPAFtextLoaded = qtrue;
02559                         usedIndex = nextIndex;
02560                 }
02561         }
02562 
02563         /*
02564         if (!wasLoaded && BGPAFtextLoaded)
02565         { //just loaded humanoid skel - we always want the rockettrooper to be after it, in slot 1
02566 #ifdef _DEBUG
02567                 assert(BG_ParseAnimationFile("models/players/rockettrooper/animation.cfg", NULL, qfalse) == 1);
02568 #else
02569                 BG_ParseAnimationFile("models/players/rockettrooper/animation.cfg", NULL, qfalse);
02570 #endif
02571         }
02572         */
02573 
02574         return usedIndex;
02575 }
02576 
02577 /*
02578 ===================
02579 LEGS Animations
02580 Base animation for overall body
02581 ===================
02582 */
02583 static void BG_StartLegsAnim( playerState_t *ps, int anim )
02584 {
02585         if ( ps->pm_type >= PM_DEAD )
02586         {
02587                 assert(!BG_InDeathAnim(anim));
02588                 //please let me know if this assert fires on you (ideally before you close/ignore it) -rww
02589 
02590                 //vehicles are allowed to do this.. IF it's a vehicle death anim
02591                 if (ps->clientNum < MAX_CLIENTS || anim != BOTH_VT_DEATH1)
02592                 {
02593                         return;
02594                 }
02595         }
02596         if ( ps->legsTimer > 0 )
02597         {
02598                 return;         // a high priority animation is running
02599         }
02600 
02601         if (ps->legsAnim == anim)
02602         {
02603                 BG_FlipPart(ps, SETANIM_LEGS);
02604         }
02605 #ifdef QAGAME
02606         else if (g_entities[ps->clientNum].s.legsAnim == anim)
02607         { //toggled anim to one anim then back to the one we were at previously in
02608                 //one frame, indicating that anim should be restarted.
02609                 BG_FlipPart(ps, SETANIM_LEGS);
02610         }
02611 #endif
02612         ps->legsAnim = anim;
02613 
02614         /*
02615         if ( pm->debugLevel ) {
02616                 Com_Printf("%d:  StartLegsAnim %d, on client#%d\n", pm->cmd.serverTime, anim, pm->ps->clientNum);
02617         }
02618         */
02619 }
02620 
02621 void PM_ContinueLegsAnim( int anim ) {
02622         if ( ( pm->ps->legsAnim ) == anim ) {
02623                 return;
02624         }
02625         if ( pm->ps->legsTimer > 0 ) {
02626                 return;         // a high priority animation is running
02627         }
02628 
02629         BG_StartLegsAnim( pm->ps, anim );
02630 }
02631 
02632 void PM_ForceLegsAnim( int anim) {
02633         if (BG_InSpecialJump(pm->ps->legsAnim) &&
02634                 pm->ps->legsTimer > 0 &&
02635                 !BG_InSpecialJump(anim))
02636         {
02637                 return;
02638         }
02639 
02640         if (BG_InRoll(pm->ps, pm->ps->legsAnim) &&
02641                 pm->ps->legsTimer > 0 &&
02642                 !BG_InRoll(pm->ps, anim))
02643         {
02644                 return;
02645         }
02646 
02647         pm->ps->legsTimer = 0;
02648         BG_StartLegsAnim( pm->ps, anim );
02649 }
02650 
02651 
02652 
02653 /*
02654 ===================
02655 TORSO Animations
02656 Override animations for upper body
02657 ===================
02658 */
02659 void BG_StartTorsoAnim( playerState_t *ps, int anim )
02660 {
02661         if ( ps->pm_type >= PM_DEAD )
02662         {
02663                 assert(!BG_InDeathAnim(anim));
02664                 //please let me know if this assert fires on you (ideally before you close/ignore it) -rww
02665                 return;
02666         }
02667 
02668         if (ps->torsoAnim == anim)
02669         {
02670                 BG_FlipPart(ps, SETANIM_TORSO);
02671         }
02672 #ifdef QAGAME
02673         else if (g_entities[ps->clientNum].s.torsoAnim == anim)
02674         { //toggled anim to one anim then back to the one we were at previously in
02675                 //one frame, indicating that anim should be restarted.
02676                 BG_FlipPart(ps, SETANIM_TORSO);
02677         }
02678 #endif
02679         ps->torsoAnim = anim;
02680 }
02681 
02682 void PM_StartTorsoAnim( int anim )
02683 {
02684     BG_StartTorsoAnim(pm->ps, anim);
02685 }
02686 
02687 
02688 /*
02689 -------------------------
02690 PM_SetLegsAnimTimer
02691 -------------------------
02692 */
02693 void BG_SetLegsAnimTimer(playerState_t *ps, int time)
02694 {
02695         ps->legsTimer = time;
02696 
02697         if (ps->legsTimer < 0 && time != -1 )
02698         {//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.
02699                 ps->legsTimer = 0;
02700         }
02701 }
02702 
02703 void PM_SetLegsAnimTimer(int time)
02704 {
02705         BG_SetLegsAnimTimer(pm->ps, time);
02706 }
02707 
02708 /*
02709 -------------------------
02710 PM_SetTorsoAnimTimer
02711 -------------------------
02712 */
02713 void BG_SetTorsoAnimTimer(playerState_t *ps, int time )
02714 {
02715         ps->torsoTimer = time;
02716 
02717         if (ps->torsoTimer < 0 && time != -1 )
02718         {//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.
02719                 ps->torsoTimer = 0;
02720         }
02721 }
02722 
02723 void PM_SetTorsoAnimTimer(int time )
02724 {
02725         BG_SetTorsoAnimTimer(pm->ps, time);
02726 }
02727 
02728 void BG_SaberStartTransAnim( int clientNum, int saberAnimLevel, int weapon, int anim, float *animSpeed, int broken )
02729 {
02730         if ( anim >= BOTH_A1_T__B_ && anim <= BOTH_ROLL_STAB )
02731         {
02732                 if ( weapon == WP_SABER )
02733                 {
02734                         saberInfo_t *saber = BG_MySaber( clientNum, 0 );
02735                         if ( saber 
02736                                 && saber->animSpeedScale != 1.0f )
02737                         {
02738                                 *animSpeed *= saber->animSpeedScale;
02739                         }
02740                         saber = BG_MySaber( clientNum, 1 );
02741                         if ( saber
02742                                 && saber->animSpeedScale != 1.0f )
02743                         {
02744                                 *animSpeed *= saber->animSpeedScale;
02745                         }
02746                 }
02747         }
02748 
02749         if ( ( (anim) >= BOTH_T1_BR__R && 
02750                 (anim) <= BOTH_T1_BL_TL ) ||
02751                 ( (anim) >= BOTH_T2_BR__R && 
02752                 (anim) <= BOTH_T2_BL_TL ) ||
02753                 ( (anim) >= BOTH_T3_BR__R && 
02754                 (anim) <= BOTH_T3_BL_TL ) )
02755         {
02756                 if ( saberAnimLevel == FORCE_LEVEL_1 )
02757                 {
02758                         *animSpeed *= 1.5f;
02759                 }
02760                 else if ( saberAnimLevel == FORCE_LEVEL_3 )
02761                 {
02762                         *animSpeed *= 0.75f;
02763                 }
02764 
02765                 if (broken & (1<<BROKENLIMB_RARM))
02766                 {
02767                         *animSpeed *= 0.5f;
02768                 }
02769                 else if (broken & (1<<BROKENLIMB_LARM))
02770                 {
02771                         *animSpeed *= 0.65f;
02772                 }
02773         }
02774         else if (broken && PM_InSaberAnim(anim))
02775         {
02776                 if (broken & (1<<BROKENLIMB_RARM))
02777                 {
02778                         *animSpeed *= 0.5f;
02779                 }
02780                 else if (broken & (1<<BROKENLIMB_LARM))
02781                 {
02782                         *animSpeed *= 0.65f;
02783                 }
02784         }
02785 }
02786 
02787 /*
02788 -------------------------
02789 PM_SetAnimFinal
02790 -------------------------
02791 */
02792 qboolean PM_RunningAnim( int anim );
02793 qboolean PM_WalkingAnim( int anim );
02794 
02795 void BG_SetAnimFinal(playerState_t *ps, animation_t *animations,
02796                                          int setAnimParts,int anim,int setAnimFlags,
02797                                          int blendTime)         // default blendTime=350
02798 {
02799         float editAnimSpeed = 1;
02800 
02801         if (!animations)
02802         {
02803                 return;
02804         }
02805 
02806         assert(anim > -1);
02807         assert(animations[anim].firstFrame > 0 || animations[anim].numFrames > 0);
02808 
02809         //NOTE: Setting blendTime here breaks actual blending..
02810         blendTime = 0;
02811 
02812         BG_SaberStartTransAnim(ps->clientNum, ps->fd.saberAnimLevel, ps->weapon, anim, &editAnimSpeed, ps->brokenLimbs);
02813 
02814         // Set torso anim
02815         if (setAnimParts & SETANIM_TORSO)
02816         {
02817                 // Don't reset if it's already running the anim
02818                 if( !(setAnimFlags & SETANIM_FLAG_RESTART) && (ps->torsoAnim) == anim )
02819                 {
02820                         goto setAnimLegs;
02821                 }
02822                 // or if a more important anim is running
02823                 if( !(setAnimFlags & SETANIM_FLAG_OVERRIDE) && ((ps->torsoTimer > 0)||(ps->torsoTimer == -1)) )
02824                 {       
02825                         goto setAnimLegs;
02826                 }
02827 
02828                 BG_StartTorsoAnim(ps, anim);
02829 
02830                 if (setAnimFlags & SETANIM_FLAG_HOLD)
02831                 {
02832                         if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
02833                         {       // Make sure to only wait in full 1/20 sec server frame intervals.
02834                                 int dur;
02835                                 int speedDif;
02836                                 
02837                                 dur = (animations[anim].numFrames-1) * fabs((float)(animations[anim].frameLerp));
02838                                 speedDif = dur - (dur * editAnimSpeed);
02839                                 dur += speedDif;
02840                                 if (dur > 1)
02841                                 {
02842                                         ps->torsoTimer = dur-1;
02843                                 }
02844                                 else
02845                                 {
02846                                         ps->torsoTimer = fabs((float)(animations[anim].frameLerp));
02847                                 }
02848                         }
02849                         else
02850                         {
02851                                 ps->torsoTimer = ((animations[anim].numFrames ) * fabs((float)(animations[anim].frameLerp)));
02852                         }
02853 
02854                         if (ps->fd.forcePowersActive & (1 << FP_RAGE))
02855                         {
02856                                 ps->torsoTimer /= 1.7;
02857                         }
02858                 }
02859         }
02860 
02861 setAnimLegs:
02862         // Set legs anim
02863         if (setAnimParts & SETANIM_LEGS)
02864         {
02865                 // Don't reset if it's already running the anim
02866                 if( !(setAnimFlags & SETANIM_FLAG_RESTART) && (ps->legsAnim) == anim )
02867                 {
02868                         goto setAnimDone;
02869                 }
02870                 // or if a more important anim is running
02871                 if( !(setAnimFlags & SETANIM_FLAG_OVERRIDE) && ((ps->legsTimer > 0)||(ps->legsTimer == -1)) )
02872                 {       
02873                         goto setAnimDone;
02874                 }
02875 
02876                 BG_StartLegsAnim(ps, anim);
02877 
02878                 if (setAnimFlags & SETANIM_FLAG_HOLD)
02879                 {
02880                         if (setAnimFlags & SETANIM_FLAG_HOLDLESS)
02881                         {       // Make sure to only wait in full 1/20 sec server frame intervals.
02882                                 int dur;
02883                                 int speedDif;
02884                                 
02885                                 dur = (animations[anim].numFrames-1) * fabs((float)(animations[anim].frameLerp));
02886                                 speedDif = dur - (dur * editAnimSpeed);
02887                                 dur += speedDif;
02888                                 if (dur > 1)
02889                                 {
02890                                         ps->legsTimer = dur-1;
02891                                 }
02892                                 else
02893                                 {
02894                                         ps->legsTimer = fabs((float)(animations[anim].frameLerp));
02895                                 }
02896                         }
02897                         else
02898                         {
02899                                 ps->legsTimer = ((animations[anim].numFrames ) * fabs((float)(animations[anim].frameLerp)));
02900                         }
02901 
02902                         if (PM_RunningAnim(anim) ||
02903                                 PM_WalkingAnim(anim)) //these guys are ok, they don't actually reference pm
02904                         {
02905                                 if (ps->fd.forcePowersActive & (1 << FP_RAGE))
02906                                 {
02907                                         ps->legsTimer /= 1.3;
02908                                 }
02909                                 else if (ps->fd.forcePowersActive & (1 << FP_SPEED))
02910                                 {
02911                                         ps->legsTimer /= 1.7;
02912                                 }
02913                         }
02914                 }
02915         }
02916 
02917 setAnimDone:
02918         return;
02919 }
02920 
02921 void PM_SetAnimFinal(int setAnimParts,int anim,int setAnimFlags,
02922                                          int blendTime)         // default blendTime=350
02923 {
02924         BG_SetAnimFinal(pm->ps, pm->animations, setAnimParts, anim, setAnimFlags, blendTime);
02925 }
02926 
02927 
02928 qboolean BG_HasAnimation(int animIndex, int animation)
02929 {
02930         animation_t *animations;
02931 
02932         //must be a valid anim number
02933         if ( animation < 0 || animation >= MAX_ANIMATIONS )
02934         {
02935                 return qfalse;
02936         }
02937 
02938         //Must have a file index entry
02939         if( animIndex < 0 || animIndex > bgNumAllAnims )
02940                 return qfalse;
02941 
02942         animations = bgAllAnims[animIndex].anims;
02943 
02944         //No frames, no anim
02945         if ( animations[animation].numFrames == 0 )
02946                 return qfalse;
02947 
02948         //Has the sequence
02949         return qtrue;
02950 }
02951 
02952 int BG_PickAnim( int animIndex, int minAnim, int maxAnim )
02953 {
02954         int anim;
02955         int count = 0;
02956 
02957         do
02958         {
02959                 anim = Q_irand(minAnim, maxAnim);
02960                 count++;
02961         }
02962         while ( !BG_HasAnimation( animIndex, anim ) && count < 1000 );
02963 
02964         if (count == 1000)
02965         { //guess we just don't have a death anim then.
02966                 return -1;
02967         }
02968 
02969         return anim;
02970 }
02971 
02972 //I want to be able to use this on a playerstate even when we are not the focus
02973 //of a pmove too so I have ported it to true BGishness.
02974 //Please do not reference pm in this function or any functions that it calls,
02975 //or I will cry. -rww
02976 void BG_SetAnim(playerState_t *ps, animation_t *animations, int setAnimParts,int anim,int setAnimFlags, int blendTime)
02977 {
02978         if (!animations)
02979         {
02980                 animations = bgAllAnims[0].anims;
02981         }
02982 
02983         if (animations[anim].firstFrame == 0 && animations[anim].numFrames == 0)
02984         {
02985                 if (anim == BOTH_RUNBACK1 ||
02986                         anim == BOTH_WALKBACK1 ||
02987                         anim == BOTH_RUN1)
02988                 { //hack for droids
02989                         anim = BOTH_WALK2;
02990                 }
02991 
02992                 if (animations[anim].firstFrame == 0 && animations[anim].numFrames == 0)
02993                 { //still? Just return then I guess.
02994                         return;
02995                 }
02996         }
02997 
02998         /*
02999         if (BG_InSpecialJump(anim))
03000         {
03001                 setAnimFlags |= SETANIM_FLAG_RESTART;
03002         }
03003         */
03004         //Don't know why I put this here originally but it's messing stuff up now and it isn't needed.
03005 
03006 //      if (BG_InRoll(ps, ps->legsAnim))
03007 //      { //never interrupt a roll
03008 //              return;
03009 //      }
03010 
03011         if (setAnimFlags&SETANIM_FLAG_OVERRIDE)
03012         {
03013                 if (setAnimParts & SETANIM_TORSO)
03014                 {
03015                         if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ps->torsoAnim) != anim )
03016                         {
03017                                 BG_SetTorsoAnimTimer(ps, 0);
03018                         }
03019                 }
03020                 if (setAnimParts & SETANIM_LEGS)
03021                 {
03022                         if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ps->legsAnim) != anim )
03023                         {
03024                                 BG_SetLegsAnimTimer(ps, 0);
03025                         }
03026                 }
03027         }
03028 
03029         BG_SetAnimFinal(ps, animations, setAnimParts, anim, setAnimFlags, blendTime);
03030 }
03031 
03032 void PM_SetAnim(int setAnimParts,int anim,int setAnimFlags, int blendTime)
03033 {       
03034         BG_SetAnim(pm->ps, pm->animations, setAnimParts, anim, setAnimFlags, blendTime);
03035 }
03036 
03037 #include "../namespace_end.h"           // End of animation utilities