#include "common.h" #include "patcher.h" #include "General.h" #include "ModelInfo.h" #include "ModelIndices.h" #include "FileMgr.h" #include "RpAnimBlend.h" #include "AnimBlendClumpData.h" #include "AnimBlendAssociation.h" #include "AnimBlendAssocGroup.h" #include "AnimManager.h" CAnimBlock CAnimManager::ms_aAnimBlocks[2]; CAnimBlendHierarchy CAnimManager::ms_aAnimations[250]; int32 CAnimManager::ms_numAnimBlocks; int32 CAnimManager::ms_numAnimations; CAnimBlendAssocGroup *CAnimManager::ms_aAnimAssocGroups; CLinkList CAnimManager::ms_animCache; AnimAssocDesc aStdAnimDescs[] = { { ANIM_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_FLAG80 }, { ANIM_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_FLAG80 }, { ANIM_SPRINT, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_FLAG80 }, { ANIM_IDLE_STANCE, ASSOC_REPEAT }, { ANIM_WALK_START, ASSOC_HAS_TRANSLATION }, { ANIM_RUN_STOP, ASSOC_DELETEFADEDOUT | ASSOC_HAS_TRANSLATION }, { ANIM_RUN_STOP_R, ASSOC_DELETEFADEDOUT | ASSOC_HAS_TRANSLATION }, { ANIM_IDLE_CAM, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_IDLE_HBHB, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_IDLE_TIRED, ASSOC_REPEAT }, { ANIM_IDLE_ARMED, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_IDLE_CHAT, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_IDLE_TAXI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_KO_SHOT_FRONT1, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FLAG800 }, { ANIM_KO_SHOT_FRONT2, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FLAG800 }, { ANIM_KO_SHOT_FRONT3, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FLAG800 }, { ANIM_KO_SHOT_FRONT4, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FLAG800 }, { ANIM_KO_SHOT_FACE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FLAG800 }, { ANIM_KO_SHOT_STOM, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_KO_SHOT_ARML, ASSOC_PARTIAL | ASSOC_FLAG800 }, { ANIM_KO_SHOT_ARMR, ASSOC_PARTIAL | ASSOC_FLAG800 }, { ANIM_KO_SHOT_LEGL, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_KO_SHOT_LEGR, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_KD_LEFT, ASSOC_PARTIAL | ASSOC_FLAG800 }, { ANIM_KD_RIGHT, ASSOC_PARTIAL | ASSOC_FLAG800 }, { ANIM_KO_SKID_FRONT, ASSOC_PARTIAL }, { ANIM_KO_SPIN_R, ASSOC_PARTIAL }, { ANIM_KO_SKID_BACK, ASSOC_PARTIAL | ASSOC_FLAG800 }, { ANIM_KO_SPIN_L, ASSOC_PARTIAL }, { ANIM_SHOT_FRONT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_SHOT_LEFT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_SHOT_BACK_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_SHOT_RIGHT_PARTIAL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_HIT_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_LEFT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_HIT_BACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_RIGHT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FLOOR_HIT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_HIT_BODYBLOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_CHEST, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_WALK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HIT_WALL, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FLOOR_HIT_F, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FLAG800 }, { ANIM_HIT_BEHIND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_PUNCH_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_KICK_FLOOR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_BAT_H, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_BAT_V, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_HGUN_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_WEAPON_AK_BODY, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_SNIPER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_THROW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_THROWU, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_WEAPON_START_THROW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_BOMBER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_HGUN_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_AK_RELOAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_FPS_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_BAT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_UZI, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_PUMP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_AK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_M16, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FPS_ROCKET, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_IDLE, ASSOC_REPEAT }, { ANIM_FIGHT2_IDLE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_SH_F, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FIGHT_BODYBLOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_HEAD, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_KICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_KNEE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_LHOOK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_PUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_FIGHT_ROUNDHOUSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FIGHT_LONGKICK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FIGHT_PPUNCH, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_CAR_JACKED_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_CAR_LJACKED_RHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_CAR_JACKED_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_CAR_LJACKED_LHS, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_CAR_QJACK, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_QJACKED, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_CAR_ALIGN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_ALIGNHI_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_OPEN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_DOORLOCKED_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_PULLOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_PULLOUT_LOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_GETIN_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_GETIN_LOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CLOSEDOOR_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CLOSEDOOR_LOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_ROLLDOOR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_ROLLDOOR_LOW, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_GETOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_GETOUT_LOW_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CLOSE_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_ALIGN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_ALIGNHI_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_OPEN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_DOORLOCKED_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_PULLOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_PULLOUT_LOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_GETIN_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_GETIN_LOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CLOSEDOOR_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CLOSEDOOR_LOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_SHUFFLE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_LSHUFFLE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_SIT, ASSOC_DELETEFADEDOUT }, { ANIM_CAR_LSIT, ASSOC_DELETEFADEDOUT }, { ANIM_CAR_SITP, ASSOC_DELETEFADEDOUT }, { ANIM_CAR_SITPLO, ASSOC_DELETEFADEDOUT }, { ANIM_DRIVE_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_DRIVE_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_DRIVE_LOW_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_DRIVE_LOW_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_DRIVEBY_L, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_DRIVEBY_R, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_CAR_LB, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_DRIVE_BOAT, ASSOC_DELETEFADEDOUT }, { ANIM_CAR_GETOUT_LHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_GETOUT_LOW_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CLOSE_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_HOOKERTALK, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_COACH_OPEN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_COACH_OPEN_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_COACH_IN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_COACH_IN_R, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_COACH_OUT_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_TRAIN_GETIN, ASSOC_PARTIAL }, { ANIM_TRAIN_GETOUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CRAWLOUT_RHS, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_CAR_CRAWLOUT_RHS2, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_OPEN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_GETIN_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_CLOSE_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_GETOUT_L, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_OPEN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_GETIN, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_CLOSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_VAN_GETOUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_GETUP1, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_GETUP2, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_GETUP3, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_GETUP_FRONT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_JUMP_LAUNCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_JUMP_GLIDE, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_JUMP_LAND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FALL_FALL, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_FALL_GLIDE, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_FALL_LAND, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FALL_COLLAPSE, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_EV_STEP, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_EV_DIVE, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION | ASSOC_FLAG800 }, { ANIM_XPRESS_SCRATCH, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG100 }, { ANIM_ROAD_CROSS, ASSOC_REPEAT | ASSOC_PARTIAL }, { ANIM_TURN_180, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_ARREST_GUN, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_DROWN, ASSOC_PARTIAL }, { ANIM_CPR, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_DUCK_DOWN, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_DUCK_LOW, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_RBLOCK_CSHOOT, ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, { ANIM_WEAPON_THROWU, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_HANDSUP, ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_HANDSCOWER, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_HAS_TRANSLATION }, { ANIM_FUCKU, ASSOC_DELETEFADEDOUT | ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL | ASSOC_FLAG200 }, { ANIM_PHONE_IN, ASSOC_PARTIAL }, { ANIM_PHONE_OUT, ASSOC_FADEOUTWHENDONE | ASSOC_PARTIAL }, { ANIM_PHONE_TALK, ASSOC_REPEAT | ASSOC_DELETEFADEDOUT | ASSOC_PARTIAL }, }; AnimAssocDesc aStdAnimDescsSide[] = { { ANIM_WALK, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_FLAG80 | ASSOC_HAS_X_TRANSLATION }, { ANIM_RUN, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_FLAG80 | ASSOC_HAS_X_TRANSLATION }, { ANIM_SPRINT, ASSOC_REPEAT | ASSOC_MOVEMENT | ASSOC_HAS_TRANSLATION | ASSOC_FLAG80 | ASSOC_HAS_X_TRANSLATION }, { ANIM_IDLE_STANCE, ASSOC_REPEAT }, { ANIM_WALK_START, ASSOC_HAS_TRANSLATION | ASSOC_HAS_X_TRANSLATION }, }; char const *aStdAnimations[] = { "walk_civi", "run_civi", "sprint_panic", "idle_stance", "walk_start", "run_stop", "run_stopR", "idle_cam", "idle_hbhb", "idle_tired", "idle_armed", "idle_chat", "idle_taxi", "KO_shot_front", "KO_shot_front", "KO_shot_front", "KO_shot_front", "KO_shot_face", "KO_shot_stom", "KO_shot_arml", "KO_shot_armR", "KO_shot_legl", "KO_shot_legR", "KD_left", "KD_right", "KO_skid_front", "KO_spin_R", "KO_skid_back", "KO_spin_L", "SHOT_partial", "SHOT_leftP", "SHOT_partial", "SHOT_rightP", "HIT_front", "HIT_L", "HIT_back", "HIT_R", "FLOOR_hit", "HIT_bodyblow", "HIT_chest", "HIT_head", "HIT_walk", "HIT_wall", "FLOOR_hit_f", "HIT_behind", "punchR", "KICK_floor", "WEAPON_bat_h", "WEAPON_bat_v", "WEAPON_hgun_body", "WEAPON_AK_body", "WEAPON_pump", "WEAPON_sniper", "WEAPON_throw", "WEAPON_throwu", "WEAPON_start_throw", "bomber", "WEAPON_hgun_rload", "WEAPON_AK_rload", "FPS_PUNCH", "FPS_BAT", "FPS_UZI", "FPS_PUMP", "FPS_AK", "FPS_M16", "FPS_ROCKET", "FIGHTIDLE", "FIGHT2IDLE", "FIGHTsh_F", "FIGHTbodyblow", "FIGHThead", "FIGHTkick", "FIGHTknee", "FIGHTLhook", "FIGHTpunch", "FIGHTrndhse", "FIGHTlngkck", "FIGHTppunch", "car_jackedRHS", "car_LjackedRHS", "car_jackedLHS", "car_LjackedLHS", "CAR_Qjack", "CAR_Qjacked", "CAR_align_LHS", "CAR_alignHI_LHS", "CAR_open_LHS", "CAR_doorlocked_LHS", "CAR_pullout_LHS", "CAR_pulloutL_LHS", "CAR_getin_LHS", "CAR_getinL_LHS", "CAR_closedoor_LHS", "CAR_closedoorL_LHS", "CAR_rolldoor", "CAR_rolldoorLO", "CAR_getout_LHS", "CAR_getoutL_LHS", "CAR_close_LHS", "CAR_align_RHS", "CAR_alignHI_RHS", "CAR_open_RHS", "CAR_doorlocked_RHS", "CAR_pullout_RHS", "CAR_pulloutL_RHS", "CAR_getin_RHS", "CAR_getinL_RHS", "CAR_closedoor_RHS", "CAR_closedoorL_RHS", "CAR_shuffle_RHS", "CAR_Lshuffle_RHS", "CAR_sit", "CAR_Lsit", "CAR_sitp", "CAR_sitpLO", "DRIVE_L", "Drive_R", "Drive_LO_l", "Drive_LO_R", "Driveby_L", "Driveby_R", "CAR_LB", "DRIVE_BOAT", "CAR_getout_RHS", "CAR_getoutL_RHS", "CAR_close_RHS", "car_hookertalk", "COACH_opnL", "COACH_opnR", "COACH_inL", "COACH_inR", "COACH_outL", "TRAIN_getin", "TRAIN_getout", "CAR_crawloutRHS", "CAR_crawloutRHS", "VAN_openL", "VAN_getinL", "VAN_closeL", "VAN_getoutL", "VAN_open", "VAN_getin", "VAN_close", "VAN_getout", "Getup", "Getup", "Getup", "Getup_front", "JUMP_launch", "JUMP_glide", "JUMP_land", "FALL_fall", "FALL_glide", "FALL_land", "FALL_collapse", "EV_step", "EV_dive", "XPRESSscratch", "roadcross", "TURN_180", "ARRESTgun", "DROWN", "CPR", "DUCK_down", "DUCK_low", "RBLOCK_Cshoot", "WEAPON_throwu", "handsup", "handsCOWER", "FUCKU", "PHONE_in", "PHONE_out", "PHONE_talk", }; char const *aPlayerAnimations[] = { "walk_player", "run_player", "SPRINT_civi", "IDLE_STANCE", "walk_start", }; char const *aPlayerWithRocketAnimations[] = { "walk_rocket", "run_rocket", "run_rocket", "idle_rocket", "walk_start_rocket", }; char const *aPlayer1ArmedAnimations[] = { "walk_player", "run_1armed", "SPRINT_civi", "IDLE_STANCE", "walk_start", }; char const *aPlayer2ArmedAnimations[] = { "walk_player", "run_armed", "run_armed", "idle_stance", "walk_start", }; char const *aPlayerBBBatAnimations[] = { "walk_player", "run_player", "run_player", "IDLE_STANCE", "walk_start", }; char const *aShuffleAnimations[] = { "WALK_shuffle", "RUN_civi", "SPRINT_civi", "IDLE_STANCE", }; char const *aOldAnimations[] = { "walk_old", "run_civi", "sprint_civi", "idle_stance", }; char const *aGang1Animations[] = { "walk_gang1", "run_gang1", "sprint_civi", "idle_stance", }; char const *aGang2Animations[] = { "walk_gang2", "run_gang1", "sprint_civi", "idle_stance", }; char const *aFatAnimations[] = { "walk_fat", "run_civi", "woman_runpanic", "idle_stance", }; char const *aOldFatAnimations[] = { "walk_fatold", "run_fatold", "woman_runpanic", "idle_stance", }; char const *aStdWomanAnimations[] = { "woman_walknorm", "woman_run", "woman_runpanic", "woman_idlestance", }; char const *aWomanShopAnimations[] = { "woman_walkshop", "woman_run", "woman_run", "woman_idlestance", }; char const *aBusyWomanAnimations[] = { "woman_walkbusy", "woman_run", "woman_runpanic", "woman_idlestance", }; char const *aSexyWomanAnimations[] = { "woman_walksexy", "woman_run", "woman_runpanic", "woman_idlestance", }; char const *aOldWomanAnimations[] = { "woman_walkold", "woman_run", "woman_runpanic", "woman_idlestance", }; char const *aFatWomanAnimations[] = { "walk_fat", "woman_run", "woman_runpanic", "woman_idlestance", }; char const *aPanicChunkyAnimations[] = { "run_fatold", "woman_runpanic", "woman_runpanic", "idle_stance", }; char const *aPlayerStrafeBackAnimations[] = { "walk_player_back", "run_player_back", "run_player_back", "IDLE_STANCE", "walk_start_back", }; char const *aPlayerStrafeLeftAnimations[] = { "walk_player_left", "run_left", "run_left", "IDLE_STANCE", "walk_start_left", }; char const *aPlayerStrafeRightAnimations[] = { "walk_player_right", "run_right", "run_right", "IDLE_STANCE", "walk_start_right", }; char const *aRocketStrafeBackAnimations[] = { "walk_rocket_back", "run_rocket_back", "run_rocket_back", "idle_rocket", "walkst_rocket_back", }; char const *aRocketStrafeLeftAnimations[] = { "walk_rocket_left", "run_rocket_left", "run_rocket_left", "idle_rocket", "walkst_rocket_left", }; char const *aRocketStrafeRightAnimations[] = { "walk_rocket_right", "run_rocket_right", "run_rocket_right", "idle_rocket", "walkst_rocket_right", }; const AnimAssocDefinition CAnimManager::ms_aAnimAssocDefinitions[NUM_ANIM_ASSOC_GROUPS] = { { "man", "ped", MI_COP, 173, aStdAnimations, aStdAnimDescs }, { "player", "ped", MI_COP, 5, aPlayerAnimations, aStdAnimDescs }, { "playerrocket", "ped", MI_COP, 5, aPlayerWithRocketAnimations, aStdAnimDescs }, { "player1armed", "ped", MI_COP, 5, aPlayer1ArmedAnimations, aStdAnimDescs }, { "player2armed", "ped", MI_COP, 5, aPlayer2ArmedAnimations, aStdAnimDescs }, { "playerBBBat", "ped", MI_COP, 5, aPlayerBBBatAnimations, aStdAnimDescs }, { "shuffle", "ped", MI_COP, 4, aShuffleAnimations, aStdAnimDescs }, { "oldman", "ped", MI_COP, 4, aOldAnimations, aStdAnimDescs }, { "gang1", "ped", MI_COP, 4, aGang1Animations, aStdAnimDescs }, { "gang2", "ped", MI_COP, 4, aGang2Animations, aStdAnimDescs }, { "fatman", "ped", MI_COP, 4, aFatAnimations, aStdAnimDescs }, { "oldfatman", "ped", MI_COP, 4, aOldFatAnimations, aStdAnimDescs }, { "woman", "ped", MI_COP, 4, aStdWomanAnimations, aStdAnimDescs }, { "shopping", "ped", MI_COP, 4, aWomanShopAnimations, aStdAnimDescs }, { "busywoman", "ped", MI_COP, 4, aBusyWomanAnimations, aStdAnimDescs }, { "sexywoman", "ped", MI_COP, 4, aSexyWomanAnimations, aStdAnimDescs }, { "oldwoman", "ped", MI_COP, 4, aOldWomanAnimations, aStdAnimDescs }, { "fatwoman", "ped", MI_COP, 4, aFatWomanAnimations, aStdAnimDescs }, { "panicchunky", "ped", MI_COP, 4, aPanicChunkyAnimations, aStdAnimDescs }, { "playerback", "ped", MI_COP, 5, aPlayerStrafeBackAnimations, aStdAnimDescs }, { "playerleft", "ped", MI_COP, 5, aPlayerStrafeLeftAnimations, aStdAnimDescsSide }, { "playerright", "ped", MI_COP, 5, aPlayerStrafeRightAnimations, aStdAnimDescsSide }, { "rocketback", "ped", MI_COP, 5, aRocketStrafeBackAnimations, aStdAnimDescs }, { "rocketleft", "ped", MI_COP, 5, aRocketStrafeLeftAnimations, aStdAnimDescsSide }, { "rocketright", "ped", MI_COP, 5, aRocketStrafeRightAnimations, aStdAnimDescsSide }, }; void CAnimManager::Initialise(void) { ms_numAnimations = 0; ms_numAnimBlocks = 0; ms_animCache.Init(25); // dumpanimdata(); } void CAnimManager::Shutdown(void) { int i; ms_animCache.Shutdown(); for(i = 0; i < ms_numAnimations; i++) ms_aAnimations[i].Shutdown(); delete[] ms_aAnimAssocGroups; } void CAnimManager::UncompressAnimation(CAnimBlendHierarchy *hier) { if(!hier->compressed){ if(hier->linkPtr){ hier->linkPtr->Remove(); ms_animCache.head.Insert(hier->linkPtr); } }else{ CLink *link = ms_animCache.Insert(hier); if(link == nil){ ms_animCache.tail.prev->item->RemoveUncompressedData(); ms_animCache.Remove(ms_animCache.tail.prev); link = ms_animCache.Insert(hier); } hier->linkPtr = link; hier->Uncompress(); } } CAnimBlock* CAnimManager::GetAnimationBlock(const char *name) { int i; for(i = 0; i < ms_numAnimBlocks; i++) if(strcasecmp(ms_aAnimBlocks[i].name, name) == 0) return &ms_aAnimBlocks[i]; return nil; } CAnimBlendHierarchy* CAnimManager::GetAnimation(const char *name, CAnimBlock *animBlock) { int i; CAnimBlendHierarchy *hier = &ms_aAnimations[animBlock->firstIndex]; for(i = 0; i < animBlock->numAnims; i++){ if(!CGeneral::faststricmp(hier->name, name)) return hier; hier++; } return nil; } const char* CAnimManager::GetAnimGroupName(AssocGroupId groupId) { return ms_aAnimAssocDefinitions[groupId].name; } CAnimBlendAssociation* CAnimManager::CreateAnimAssociation(AssocGroupId groupId, AnimationId animId) { return ms_aAnimAssocGroups[groupId].CopyAnimation(animId); } CAnimBlendAssociation* CAnimManager::GetAnimAssociation(AssocGroupId groupId, AnimationId animId) { return ms_aAnimAssocGroups[groupId].GetAnimation(animId); } CAnimBlendAssociation* CAnimManager::GetAnimAssociation(AssocGroupId groupId, const char *name) { return ms_aAnimAssocGroups[groupId].GetAnimation(name); } CAnimBlendAssociation* CAnimManager::AddAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId) { CAnimBlendAssociation *anim = CreateAnimAssociation(groupId, animId); CAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump); if(anim->IsMovement()){ CAnimBlendAssociation *syncanim = nil; CAnimBlendLink *link; for(link = clumpData->link.next; link; link = link->next){ syncanim = CAnimBlendAssociation::FromLink(link); if(syncanim->IsMovement()) break; } if(link){ anim->SyncAnimation(syncanim); anim->flags |= ASSOC_RUNNING; }else anim->Start(0.0f); }else anim->Start(0.0f); clumpData->link.Prepend(&anim->link); return anim; } CAnimBlendAssociation* CAnimManager::AddAnimationAndSync(RpClump *clump, CAnimBlendAssociation *syncanim, AssocGroupId groupId, AnimationId animId) { CAnimBlendAssociation *anim = CreateAnimAssociation(groupId, animId); CAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump); if (anim->IsMovement() && syncanim){ anim->SyncAnimation(syncanim); anim->flags |= ASSOC_RUNNING; }else anim->Start(0.0f); clumpData->link.Prepend(&anim->link); return anim; } CAnimBlendAssociation* CAnimManager::BlendAnimation(RpClump *clump, AssocGroupId groupId, AnimationId animId, float delta) { int removePrevAnim = 0; CAnimBlendClumpData *clumpData = *RPANIMBLENDCLUMPDATA(clump); CAnimBlendAssociation *anim = GetAnimAssociation(groupId, animId); bool isMovement = anim->IsMovement(); bool isPartial = anim->IsPartial(); CAnimBlendLink *link; CAnimBlendAssociation *found = nil, *movementAnim = nil; for(link = clumpData->link.next; link; link = link->next){ anim = CAnimBlendAssociation::FromLink(link); if(isMovement && anim->IsMovement()) movementAnim = anim; if(anim->animId == animId) found = anim; else{ if(isPartial == anim->IsPartial()){ if(anim->blendAmount > 0.0f){ float blendDelta = -delta*anim->blendAmount; if(blendDelta < anim->blendDelta || !isPartial) anim->blendDelta = blendDelta; }else{ anim->blendDelta = -1.0f; } anim->flags |= ASSOC_DELETEFADEDOUT; removePrevAnim = 1; } } } if(found){ found->blendDelta = (1.0f - found->blendAmount)*delta; if(!found->IsRunning() && found->currentTime == found->hierarchy->totalLength) found->Start(0.0f); }else{ found = AddAnimationAndSync(clump, movementAnim, groupId, animId); if(!removePrevAnim && !isPartial){ found->blendAmount = 1.0f; return found; } found->blendAmount = 0.0f; found->blendDelta = delta; } UncompressAnimation(found->hierarchy); return found; } void CAnimManager::LoadAnimFiles(void) { int i, j; LoadAnimFile("ANIM\\PED.IFP"); // Create all assoc groups ms_aAnimAssocGroups = new CAnimBlendAssocGroup[NUM_ANIM_ASSOC_GROUPS]; for(i = 0; i < NUM_ANIM_ASSOC_GROUPS; i++){ CBaseModelInfo *mi = CModelInfo::GetModelInfo(ms_aAnimAssocDefinitions[i].modelIndex); RpClump *clump = (RpClump*)mi->CreateInstance(); RpAnimBlendClumpInit(clump); CAnimBlendAssocGroup *group = &CAnimManager::ms_aAnimAssocGroups[i]; const AnimAssocDefinition *def = &CAnimManager::ms_aAnimAssocDefinitions[i]; group->CreateAssociations(def->blockName, clump, def->animNames, def->numAnims); for(j = 0; j < group->numAssociations; j++) group->GetAnimation(j)->flags |= def->animDescs[j].flags; RpClumpDestroy(clump); } } void CAnimManager::LoadAnimFile(const char *filename) { int fd; fd = CFileMgr::OpenFile(filename, "rb"); assert(fd > 0); LoadAnimFile(fd, true); CFileMgr::CloseFile(fd); } void CAnimManager::LoadAnimFile(int fd, bool compress) { #define ROUNDSIZE(x) if((x) & 3) (x) += 4 - ((x)&3) struct IfpHeader { char ident[4]; uint32 size; }; IfpHeader anpk, info, name, dgan, cpan, anim; int numANPK; char buf[256]; int i, j, k, l; float *fbuf = (float*)buf; CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader)); if(strncmp(anpk.ident, "ANLF", 4) == 0){ ROUNDSIZE(anpk.size); CFileMgr::Read(fd, buf, anpk.size); numANPK = *(int*)buf; }else if(strncmp(anpk.ident, "ANPK", 4) == 0){ CFileMgr::Seek(fd, -8, 1); numANPK = 1; } for(i = 0; i < numANPK; i++){ // block name CFileMgr::Read(fd, (char*)&anpk, sizeof(IfpHeader)); ROUNDSIZE(anpk.size); CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader)); ROUNDSIZE(info.size); CFileMgr::Read(fd, buf, info.size); CAnimBlock *animBlock = &ms_aAnimBlocks[ms_numAnimBlocks++]; strncpy(animBlock->name, buf+4, 24); animBlock->numAnims = *(int*)buf; animBlock->firstIndex = ms_numAnimations; for(j = 0; j < animBlock->numAnims; j++){ CAnimBlendHierarchy *hier = &ms_aAnimations[ms_numAnimations++]; // animation name CFileMgr::Read(fd, (char*)&name, sizeof(IfpHeader)); ROUNDSIZE(name.size); CFileMgr::Read(fd, buf, name.size); hier->SetName(buf); // DG info has number of nodes/sequences CFileMgr::Read(fd, (char*)&dgan, sizeof(IfpHeader)); ROUNDSIZE(dgan.size); CFileMgr::Read(fd, (char*)&info, sizeof(IfpHeader)); ROUNDSIZE(info.size); CFileMgr::Read(fd, buf, info.size); hier->numSequences = *(int*)buf; hier->sequences = new CAnimBlendSequence[hier->numSequences]; CAnimBlendSequence *seq = hier->sequences; for(k = 0; k < hier->numSequences; k++, seq++){ // Each node has a name and key frames CFileMgr::Read(fd, (char*)&cpan, sizeof(IfpHeader)); ROUNDSIZE(dgan.size); CFileMgr::Read(fd, (char*)&anim, sizeof(IfpHeader)); ROUNDSIZE(anim.size); CFileMgr::Read(fd, buf, anim.size); int numFrames = *(int*)(buf+28); #ifdef PED_SKIN if(anim.size == 44) seq->SetBoneTag(*(int*)(buf+40)); #endif seq->SetName(buf); if(numFrames == 0) continue; CFileMgr::Read(fd, (char*)&info, sizeof(info)); if(strncmp(info.ident, "KR00", 4) == 0){ seq->SetNumFrames(numFrames, false); KeyFrame *kf = seq->GetKeyFrame(0); for(l = 0; l < numFrames; l++, kf++){ CFileMgr::Read(fd, buf, 0x14); kf->rotation.x = -fbuf[0]; kf->rotation.y = -fbuf[1]; kf->rotation.z = -fbuf[2]; kf->rotation.w = fbuf[3]; kf->deltaTime = fbuf[4]; // absolute time here } }else if(strncmp(info.ident, "KRT0", 4) == 0){ seq->SetNumFrames(numFrames, true); KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0); for(l = 0; l < numFrames; l++, kf++){ CFileMgr::Read(fd, buf, 0x20); kf->rotation.x = -fbuf[0]; kf->rotation.y = -fbuf[1]; kf->rotation.z = -fbuf[2]; kf->rotation.w = fbuf[3]; kf->translation.x = fbuf[4]; kf->translation.y = fbuf[5]; kf->translation.z = fbuf[6]; kf->deltaTime = fbuf[7]; // absolute time here } }else if(strncmp(info.ident, "KRTS", 4) == 0){ seq->SetNumFrames(numFrames, true); KeyFrameTrans *kf = (KeyFrameTrans*)seq->GetKeyFrame(0); for(l = 0; l < numFrames; l++, kf++){ CFileMgr::Read(fd, buf, 0x2C); kf->rotation.x = -fbuf[0]; kf->rotation.y = -fbuf[1]; kf->rotation.z = -fbuf[2]; kf->rotation.w = fbuf[3]; kf->translation.x = fbuf[4]; kf->translation.y = fbuf[5]; kf->translation.z = fbuf[6]; // scaling ignored kf->deltaTime = fbuf[10]; // absolute time here } } // convert absolute time to deltas for(l = seq->numFrames-1; l > 0; l--){ KeyFrame *kf1 = seq->GetKeyFrame(l); KeyFrame *kf2 = seq->GetKeyFrame(l-1); kf1->deltaTime -= kf2->deltaTime; } } hier->RemoveQuaternionFlips(); if(compress) hier->RemoveUncompressedData(); else hier->CalcTotalTime(); } } } void CAnimManager::RemoveLastAnimFile(void) { int i; ms_numAnimBlocks--; ms_numAnimations = ms_aAnimBlocks[ms_numAnimBlocks].firstIndex; for(i = 0; i < ms_aAnimBlocks[ms_numAnimBlocks].numAnims; i++) ms_aAnimations[ms_aAnimBlocks[ms_numAnimBlocks].firstIndex + i].RemoveAnimSequences(); } STARTPATCHES InjectHook(0x403380, CAnimManager::Initialise, PATCH_JUMP); InjectHook(0x4033B0, CAnimManager::Shutdown, PATCH_JUMP); InjectHook(0x403410, CAnimManager::UncompressAnimation, PATCH_JUMP); InjectHook(0x4034A0, CAnimManager::GetAnimationBlock, PATCH_JUMP); InjectHook(0x4034F0, (CAnimBlendHierarchy *(*)(const char*, CAnimBlock*))CAnimManager::GetAnimation, PATCH_JUMP); InjectHook(0x4035B0, CAnimManager::GetAnimGroupName, PATCH_JUMP); InjectHook(0x4035C0, CAnimManager::CreateAnimAssociation, PATCH_JUMP); InjectHook(0x4035E0, (CAnimBlendAssociation *(*)(AssocGroupId, AnimationId))CAnimManager::GetAnimAssociation, PATCH_JUMP); InjectHook(0x403600, (CAnimBlendAssociation *(*)(AssocGroupId, const char*))CAnimManager::GetAnimAssociation, PATCH_JUMP); InjectHook(0x403620, CAnimManager::AddAnimation, PATCH_JUMP); InjectHook(0x4036A0, CAnimManager::AddAnimationAndSync, PATCH_JUMP); InjectHook(0x403710, CAnimManager::BlendAnimation, PATCH_JUMP); InjectHook(0x4038F0, CAnimManager::LoadAnimFiles, PATCH_JUMP); InjectHook(0x403A10, (void (*)(const char *))CAnimManager::LoadAnimFile, PATCH_JUMP); InjectHook(0x403A40, (void (*)(int, bool))CAnimManager::LoadAnimFile, PATCH_JUMP); InjectHook(0x404320, CAnimManager::RemoveLastAnimFile, PATCH_JUMP); ENDPATCHES