USING "globals.sch" USING "rage_builtins.sch" USING "net_include.sch" USING "ambient_globals.sch" USING "commands_player.sch" USING "commands_audio.sch" USING "script_clock.sch" USING "candidate_public.sch" USING "beast_secret_shared.sch" #IF FEATURE_SP_DLC_BEAST_SECRET //╒═════════════════════════════════════════════════════════════════════════════╕ //╞═══════════════════════════ The Beast Finale ════════════════════════╡ //╘═════════════════════════════════════════════════════════════════════════════╛ CONST_INT BF_BIT_REQUESTED_ASSETS 0 CONST_INT BF_BIT_CREATED_BEAST 1 CONST_INT BF_BIT_BEAST_WAITING 2 CONST_INT BF_BIT_BEAST_LEAVING 3 CONST_INT BF_BIT_BEAST_WINDOW_PASSED 4 CONST_INT BF_BIT_BEAST_INJURED 5 CONST_INT BF_BIT_BEAST_FIGHT_ACTIVE 6 CONST_INT BF_BIT_BEAST_DEAD 7 CONST_INT BF_BIT_SOUND_PLAYING 8 CONST_INT BF_BIT_KNOCKED_DOWN 9 CONST_INT BF_BIT_ALLOWED_TO_RUN_LAST_FRAME 10 CONST_FLOAT BF_STREAM_IN_RANGE_SQR 5625.0 //75^2 CONST_FLOAT BF_STREAM_OUT_RANGE_SQR 6400.0 //80^2 CONST_FLOAT BF_LEAVE_TIMER_RANGE_SQR 3600.0 //60^2 CONST_INT BF_VISIBLE_TIME 9000 CONST_INT BF_BUSH_SLIDE_TIME 400 CONST_INT BF_STUCK_UNDER_CAR_TIME 500 CONST_INT BF_MAX_DEAD_FRAMES 10 //Frames to wait until cancelling fight #IF IS_DEBUG_BUILD FUNC STRING Get_Beast_Fight_State_String(BeastFightState eBFS) SWITCH eBFS CASE BFS_Intro RETURN "Intro" BREAK CASE BFS_Approach_Player RETURN "Approach player" BREAK CASE BFS_Attack_Player RETURN "Attack player" BREAK CASE BFS_Let_Player_Get_Up RETURN "Let player get up" BREAK CASE BFS_Call_Backup RETURN "Call backup" BREAK CASE BFS_Let_Dogs_Attack RETURN "Let dogs attack" BREAK CASE BFS_Run_Away RETURN "Running away" BREAK CASE BFS_Death RETURN "Death" BREAK ENDSWITCH RETURN "Unknown" ENDFUNC #ENDIF PROC Set_Beast_State(BeastFightState eBFS, INT iStageTimerValue = 0) CPRINTLN(debug_hunting, "->Beast switching from state ",Get_Beast_Fight_State_String(sBeastFinaleVars.eBeastFightingState)," to: ",Get_Beast_Fight_State_String(eBFS)) sBeastFinaleVars.eBeastFightingState = eBFS sBeastFinaleVars.iProg = 0 sBeastFinaleVars.iTimerStage = GET_GAME_TIMER() + iStageTimerValue ENDPROC PROC Reset_Beast_Finale_Variables() //Unset "ready" flag CLEAR_BITMASK(g_iBeastSetupInt, BH_Bit_Fight_Init) sBeastFinaleVars.iState = 0 sBeastFinaleVars.iSoundID = -1 sBeastFinaleVars.iTimer = -1 //Beast peyote Z set-up Set_Beast_Peyote_Vectors_Z() //Beast Hunt X Set-up Set_Beast_Hunt_Vectors_X() //Beast fight y set-up Set_Beast_Fight_Vectors_y() sBeastFinaleVars.relGroupHashBeast = INT_TO_ENUM(REL_GROUP_HASH, HASH("DLC_SFX1/BEAST")) sBeastFinaleVars.sFightMusic = Build_Beast_String_31("OWE","HALL","SIC","EN_START_MU") //"HALLOWEEN_START_MUSIC" sBeastFinaleVars.sFightMusicStop = Build_Beast_String_31("WEEN_F","HALLO","P_MUSIC","AST_STO") //"HALLOWEEN_FAST_STOP_MUSIC" //Taunts for when the player is down. sBeastFinaleVars.sTauntAnimDicts[0] = Build_Long_Beast_String_63( "NUCKL", "M@MP_PLA", "NMALE@K", "E_CRUNCH", "ANI", "TCELE", "BRATIO", "YER_IN") //"ANIM@MP_PLAYER_INTCELEBRATIONMALE@KNUCKLE_CRUNCH" sBeastFinaleVars.sTauntAnims[0] = Build_Beast_String_23("UCK", "KN", "UNCH", "LE_CR") //"KNUCKLE_CRUNCH" sBeastFinaleVars.sTauntAnimDicts[1] = Build_Long_Beast_String_63( "ALE@FAC", "IM@MP", "ATIONM", "E_PALM", "AN", "ER_INTC", "ELEBR", "_PLAY") //"ANIM@MP_PLAYER_INTCELEBRATIONMALE@FACE_PALM" sBeastFinaleVars.sTauntAnims[1] = Build_Beast_String_23("CE", "FA", "LM", "_PA") //"FACE_PALM" sBeastFinaleVars.sTauntAnimDicts[2] = Build_Long_Beast_String_63( "B_ON_E", "M@MP_PLA", "E@THUM", "ARS", "ANI", "LEBRATI", "ONMAL", "YER_INTCE") //"ANIM@MP_PLAYER_INTCELEBRATIONMALE@THUMB_ON_EARS" sBeastFinaleVars.sTauntAnims[2] = Build_Beast_String_23("MB_", "THU", "ARS", "ON_E") //"THUMB_ON_EARS" sBeastFinaleVars.sTauntAnimDicts[3] = Build_Beast_String_63("E_STRA", "MOV", "OLL", "FE@R") //"MOVE_STRAFE@ROLL" sBeastFinaleVars.sTauntAnims[3] = Build_Beast_String_23("ATRO","COMB","D_P1_180","LL_BW") //"COMBATROLL_BWD_P1_180" sBeastFinaleVars.sTransformAnimDict = Build_Beast_String_31("M@MP_F","ANI","T@INTRO","M_EVEN") //"ANIM@MP_FM_EVENT@INTRO" sBeastFinaleVars.sTransformAnim = Build_Beast_String_31("ST_T","BEA","FORM","RANS") //"BEAST_TRANSFORM" sBeastFinaleVars.sBeastSfx = Build_Beast_String_31("C_SF", "DL", "AST", "X1/BE") //"DLC_SFX1/BEAST" sBeastFinaleVars.sKneelingAnim = Build_Beast_String_31("DIC@ST","AMB@ME","EEL@IDLE_A","ANDING@KN") //"AMB@MEDIC@STANDING@KNEEL@IDLE_A" sBeastFinaleVars.sRelGroup = Build_Beast_String_31("L_GR","RE","AST","OUP_BE") sBeastFinaleVars.sBeastCalls = Build_Beast_String_31("ST_C","BEA","LS","AL") //"BEAST_CALLS" sBeastFinaleVars.sFMEvents = Build_Beast_String_31("NTS_S","FM_EVE","TCH_SOUNDS","ASQUA") //"FM_EVENTS_SASQUATCH_SOUNDS") ENDPROC PROC Request_Beast_Finale_Assets() INT i CPRINTLN(DEBUG_HUNTING, "Requesting beast finale assets.") REQUEST_SCRIPT_AUDIO_BANK(sBeastFinaleVars.sBeastSfx) //"DLC_SFX1/BEAST" MODEL_NAMES eBeastModel = Get_Beast_Model() MODEL_NAMES eLionModel = Get_Beast_Hint_Model_A(BHT_LION) MODEL_NAMES eRottweilerModel = Get_Rottweiler_Model() REQUEST_MODEL(eBeastModel) REQUEST_MODEL(eLionModel) REQUEST_MODEL(eRottweilerModel) REQUEST_ANIM_DICT(sBeastFinaleVars.sKneelingAnim) //"AMB@MEDIC@STANDING@KNEEL@IDLE_A") REQUEST_ANIM_DICT(sBeastFinaleVars.sTransformAnimDict) REPEAT BF_NUM_TAUNT_ANIMS i REQUEST_ANIM_DICT(sBeastFinaleVars.sTauntAnimDicts[i]) ENDREPEAT ADD_RELATIONSHIP_GROUP(sBeastFinaleVars.sRelGroup, sBeastFinaleVars.relGroupHashBeast) SET_BIT(sBeastFinaleVars.iState, BF_BIT_REQUESTED_ASSETS) ENDPROC FUNC BOOL Have_Beast_Finale_Assets_Loaded() INT i REPEAT BF_NUM_TAUNT_ANIMS i IF NOT HAS_ANIM_DICT_LOADED(sBeastFinaleVars.sTauntAnimDicts[i]) RETURN FALSE ENDIF ENDREPEAT MODEL_NAMES eBeastModel = Get_Beast_Model() MODEL_NAMES eLionModel = Get_Beast_Hint_Model_A(BHT_LION) MODEL_NAMES eRottweilerModel = Get_Rottweiler_Model() IF REQUEST_SCRIPT_AUDIO_BANK(sBeastFinaleVars.sBeastSfx) //"DLC_SFX1/BEAST" AND HAS_MODEL_LOADED(eBeastModel) AND HAS_MODEL_LOADED(eLionModel) AND HAS_MODEL_LOADED(eRottweilerModel) AND HAS_ANIM_DICT_LOADED(sBeastFinaleVars.sKneelingAnim) //"AMB@MEDIC@STANDING@KNEEL@IDLE_A") AND HAS_ANIM_DICT_LOADED(sBeastFinaleVars.sTransformAnimDict) AND DOES_RELATIONSHIP_GROUP_EXIST(sBeastFinaleVars.relGroupHashBeast) RETURN TRUE ENDIF RETURN FALSE ENDFUNC PROC Release_Beast_Finale_Assets() INT i CPRINTLN(DEBUG_HUNTING, "Releasing beast finale assets.") RELEASE_SCRIPT_AUDIO_BANK() MODEL_NAMES eBeastModel = Get_Beast_Model() MODEL_NAMES eLionModel = Get_Beast_Hint_Model_A(BHT_LION) MODEL_NAMES eRottweilerModel = Get_Rottweiler_Model() SET_MODEL_AS_NO_LONGER_NEEDED(eBeastModel) SET_MODEL_AS_NO_LONGER_NEEDED(eLionModel) SET_MODEL_AS_NO_LONGER_NEEDED(eRottweilerModel) REMOVE_ANIM_DICT(sBeastFinaleVars.sKneelingAnim) //"AMB@MEDIC@STANDING@KNEEL@IDLE_A") REMOVE_ANIM_DICT(sBeastFinaleVars.sTransformAnimDict) REPEAT BF_NUM_TAUNT_ANIMS i REMOVE_ANIM_DICT(sBeastFinaleVars.sTauntAnimDicts[i]) ENDREPEAT REMOVE_RELATIONSHIP_GROUP(sBeastFinaleVars.relGroupHashBeast) CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_REQUESTED_ASSETS) ENDPROC PROC Cleanup_Beast_Fight(BOOL bDeleteBeast = FALSE) CPRINTLN(DEBUG_HUNTING, "Cleaning up beast fight.") IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedBeast) SET_PED_AS_NO_LONGER_NEEDED(sBeastFinaleVars.pedBeast) IF bDeleteBeast DELETE_PED(sBeastFinaleVars.pedBeast) ENDIF ENDIF INT iAnimalIndex REPEAT BF_MAX_ANIMALS_TO_SPAWN iAnimalIndex IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedAnimals[iAnimalIndex]) SET_PED_AS_NO_LONGER_NEEDED(sBeastFinaleVars.pedAnimals[iAnimalIndex]) ENDIF ENDREPEAT //Free up weather. TEXT_LABEL_23 tlWeather = Build_Beast_String_23("TR", "EX", "NY", "ASUN") //"EXTRASUNNY" SET_WEATHER_TYPE_OVERTIME_PERSIST(tlWeather, 5.0) //Free up clock. PAUSE_CLOCK(FALSE) //Stop event music CANCEL_MUSIC_EVENT(sBeastFinaleVars.sFightMusic) IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_FIGHT_ACTIVE) CPRINTLN(debug_hunting,"Triggering music stop") TRIGGER_MUSIC_EVENT(sBeastFinaleVars.sFightMusicStop) // "HALLOWEEN_FAST_STOP_MUSIC") ENDIF //Default wanted levels SET_MAX_WANTED_LEVEL(sBeastFinaleVars.iStartWantedLevel) Release_Beast_Finale_Assets() sBeastFinaleVars.iState = 0 ENDPROC PROC Fail_Beast_Fight() CPRINTLN(debug_hunting, "Beast fight failed, cleaning up") Cleanup_Beast_Fight(TRUE) //Set the bits for the failed fight CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_FIGHT_ACTIVE) CLEAR_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_FIGHT_FAILED) ENDPROC PROC Create_Beast(VECTOR vPosition, FLOAT fHeading, BOOL bForCombat) CPRINTLN(DEBUG_HUNTING, "Creating beast.") sBeastFinaleVars.pedBeast = CREATE_PED(PEDTYPE_MISSION, MP_M_FREEMODE_01, vPosition, fHeading, FALSE, FALSE) IF IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) CERRORLN(debug_hunting, "WARNING! Beast ped not alive this frame!") EXIT ENDIF Set_Male_Beast_Outfit_On_Ped(sBeastFinaleVars.pedBeast ) SET_PED_SUFFERS_CRITICAL_HITS(sBeastFinaleVars.pedBeast, FALSE) SET_PED_MAX_HEALTH(sBeastFinaleVars.pedBeast, 100000) SET_ENTITY_HEALTH(sBeastFinaleVars.pedBeast, 100000) SET_PED_MONEY(sBeastFinaleVars.pedBeast, 0) DISABLE_PED_PAIN_AUDIO(sBeastFinaleVars.pedBeast, TRUE) IF bForCombat SET_PED_RELATIONSHIP_GROUP_HASH(sBeastFinaleVars.pedBeast, sBeastFinaleVars.relGroupHashBeast) //Remove all weapons but the melee REMOVE_ALL_PED_WEAPONS(sBeastFinaleVars.pedBeast, FALSE) SET_CURRENT_PED_WEAPON(sBeastFinaleVars.pedBeast, WEAPONTYPE_UNARMED, TRUE) //Beast hates the player. SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_HATE, RELGROUPHASH_PLAYER, sBeastFinaleVars.relGroupHashBeast) SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_HATE, sBeastFinaleVars.relGroupHashBeast, RELGROUPHASH_PLAYER) //Ignores the Hillbillies. SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_IGNORE, RELGROUPHASH_AMBIENT_GANG_HILLBILLY, sBeastFinaleVars.relGroupHashBeast) SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_IGNORE, sBeastFinaleVars.relGroupHashBeast, RELGROUPHASH_AMBIENT_GANG_HILLBILLY) //Likes the guards dogs. SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, INT_TO_ENUM(REL_GROUP_HASH, HASH("GUARD_DOG")), sBeastFinaleVars.relGroupHashBeast) SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, sBeastFinaleVars.relGroupHashBeast, INT_TO_ENUM(REL_GROUP_HASH, HASH("GUARD_DOG"))) //Likes cougars. SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, INT_TO_ENUM(REL_GROUP_HASH, HASH("COUGAR")), sBeastFinaleVars.relGroupHashBeast) SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_LIKE, sBeastFinaleVars.relGroupHashBeast, INT_TO_ENUM(REL_GROUP_HASH, HASH("COUGAR"))) //Likes wild animals. SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_HATE, INT_TO_ENUM(REL_GROUP_HASH, HASH("WILD_ANIMAL")), sBeastFinaleVars.relGroupHashBeast) SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_HATE, sBeastFinaleVars.relGroupHashBeast, INT_TO_ENUM(REL_GROUP_HASH, HASH("WILD_ANIMAL"))) SET_PLAYER_MELEE_WEAPON_DAMAGE_MODIFIER(PLAYER_ID(), 150.0) //Player melee damage against the beast SET_DISABLE_HIGH_FALL_DEATH(sBeastFinaleVars.pedBeast, TRUE) SET_COMBAT_FLOAT(sBeastFinaleVars.pedBeast, CCF_FIGHT_PROFICIENCY, 1.0) SET_PED_COMBAT_ABILITY(sBeastFinaleVars.pedBeast, CAL_PROFESSIONAL) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_AGGRESSIVE, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_ALWAYS_FIGHT, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_PERFECT_ACCURACY, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_MAINTAIN_MIN_DISTANCE_TO_TARGET, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_CAN_FIGHT_ARMED_PEDS_WHEN_NOT_ARMED, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_CAN_CHARGE, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_CAN_SEE_UNDERWATER_PEDS, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedBeast, CA_DISABLE_FLEE_FROM_COMBAT, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_DontActivateRagdollFromFire, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_DontActivateRagdollFromBulletImpact, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_DontActivateRagdollFromExplosions, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_ShouldChargeNow, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_ShoutToGroupOnPlayerMelee, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_IgnoreMeleeFistWeaponDamageMult, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_AllowMeleeReactionIfMeleeProofIsOn, FALSE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_DisableExplosionReactions, TRUE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_RunFromFiresAndExplosions, FALSE) SET_ENTITY_PROOFS(sBeastFinaleVars.pedBeast, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(sBeastFinaleVars.pedBeast, TRUE) ELSE SET_ENTITY_PROOFS(sBeastFinaleVars.pedBeast, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE) SET_PED_CAN_BE_TARGETTED(sBeastFinaleVars.pedBeast, FALSE) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(sBeastFinaleVars.pedBeast, TRUE) SET_PED_CAN_RAGDOLL(sBeastFinaleVars.pedBeast, FALSE) SET_PED_CONFIG_FLAG(sBeastFinaleVars.pedBeast, PCF_DisableExplosionReactions,TRUE) sBeastFinaleVars.iSyncScene = CREATE_SYNCHRONIZED_SCENE(vPosition, << 0.000, 0.000, fHeading >>) SET_SYNCHRONIZED_SCENE_LOOPED(sBeastFinaleVars.iSyncScene, TRUE) TEXT_LABEL_23 tlAnim = Build_Beast_String_23("DL", "I", "A", "E_") //"IDLE_A" TASK_SYNCHRONIZED_SCENE (sBeastFinaleVars.pedBeast, sBeastFinaleVars.iSyncScene, sBeastFinaleVars.sKneelingAnim, tlAnim, INSTANT_BLEND_IN, INSTANT_BLEND_OUT ) ENDIF SET_BIT(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) ENDPROC PROC Play_Beast_Sound_From_Position(VECTOR vPosition) CPRINTLN(DEBUG_HUNTING, "Playing beast sound at position ", vPosition, ".") sBeastFinaleVars.iSoundID = GET_SOUND_ID() PLAY_SOUND_FROM_COORD(sBeastFinaleVars.iSoundId, sBeastFinaleVars.sBeastCalls, vPosition, sBeastFinaleVars.sFMEvents) ENDPROC PROC Destroy_Player_Vehicle() VEHICLE_INDEX vehLast = GET_LAST_DRIVEN_VEHICLE() sBeastFinaleVars.iState = sBeastFinaleVars.iState //Unreferenced variable fix IF DOES_ENTITY_EXIST(vehLast) IF NOT IS_ENTITY_DEAD(vehLast) MODEL_NAMES mVehicle = GET_ENTITY_MODEL(vehLast) CPRINTLN(debug_hunting, "Found last vehicle: ",GET_MODEL_NAME_FOR_DEBUG(mVehicle)) IF NOT (IS_THIS_MODEL_A_BICYCLE(mVehicle)) IF IS_ENTITY_AT_COORD(vehLast, g_vBeastFinaleArenaPos, g_vBeastFinaleArenaSize) CPRINTLN(debug_hunting, "Last vehicle in range") //Destroy vehicle SET_ENTITY_HEALTH(vehLast, 0) ADD_EXPLOSION(GET_ENTITY_COORDS(vehLast, false),EXP_TAG_STICKYBOMB) // SET_VEHICLE_TIMED_EXPLOSION(vehLast, PLAYER_PED_ID(),0) ENDIF ENDIF ENDIF ENDIF ENDPROC //===============Beast fighting section CONST_INT HIT_TIME 2500 CONST_INT MAX_HITS 5 PROC Maintain_Player_Hit_Combo(PED_INDEX beast, INT &iTimer, INT &iHitCount, BOOL bCheat = FALSE) //Check if a new hit took place IF DOES_ENTITY_EXIST(beast) AND NOT IS_ENTITY_DEAD(beast) AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(beast, PLAYER_PED_ID()) AND HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(beast, WEAPONTYPE_INVALID, GENERALWEAPON_TYPE_ANYMELEE) iHitCount = IMIN(MAX_HITS, iHitCount+1) iTimer = GET_GAME_TIMER() + HIT_TIME CLEAR_ENTITY_LAST_DAMAGE_ENTITY(beast) CLEAR_ENTITY_LAST_WEAPON_DAMAGE(beast) IF bCheat SET_ENTITY_HEALTH(beast, 100000) //Reset the beast health if cheating ENDIF ENDIF ENDIF //Check if we need to reduce the hit counter IF GET_GAME_TIMER() > iTimer AND iHitCount > 0 iHitCount-- iTimer = GET_GAME_TIMER() + HIT_TIME ENDIF //Draw combo counter #IF IS_DEBUG_BUILD IF iHitCount > 0 TEXT_LABEL_23 msg = "Hits:" msg += iHitCount msg += " Time:" msg += (iTimer - GET_GAME_TIMER()) Beast_Display_Onscreen_Text(0.5,0.9,msg, 0.3) ENDIF #ENDIF ENDPROC PROC Knock_Player_Weapon() IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) WEAPON_TYPE currentWeapon GET_CURRENT_PED_WEAPON(PLAYER_PED_ID(),currentWeapon,FALSE) IF currentWeapon != WEAPONTYPE_UNARMED //Remove the weapon OBJECT_INDEX weaponObj = GET_WEAPON_OBJECT_FROM_PED(PLAYER_PED_ID(),FALSE) weaponObj = weaponObj REMOVE_WEAPON_FROM_PED(PLAYER_PED_ID(),currentWeapon) SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), WEAPONTYPE_UNARMED,TRUE) ENDIF ENDIF ENDPROC PROC Stun_Player_On_Shout(FLOAT fMaxRange = 3.0, BOOL bCheating = FALSE) VECTOR vUpForce = <<0,0,0.5>> IF bCheating //Increase stun range if cheating fMaxRange = 10 vUpForce = <<0,0,8>> ENDIF IF NOT IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) AND GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast),FALSE) < fMaxRange //Check the max range IF NOT IS_PED_RAGDOLL(PLAYER_PED_ID()) //Set the player to ragdoll SET_PED_TO_RAGDOLL(PLAYER_PED_ID(), 2000, 6000, TASK_NM_BALANCE, FALSE) Knock_Player_Weapon() ENDIF VECTOR vForce = NORMALISE_VECTOR(GET_ENTITY_COORDS(PLAYER_PED_ID()) - GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast)) * (sBeastFinaleVars.fPushForce / 5) //Local multiplier CPRINTLN(debug_hunting,"Applying force of power ",vForce) APPLY_FORCE_TO_ENTITY(PLAYER_PED_ID(), APPLY_TYPE_IMPULSE, vForce + vUpForce, <<0,0,0.5>>, 0, FALSE, TRUE, TRUE) IF (bCheating) //Also drop health if cheating SET_ENTITY_HEALTH(PLAYER_PED_ID(), IMAX(GET_ENTITY_HEALTH(PLAYER_PED_ID())/2 - 300, 0)) ENDIF // Beast_Display_Onscreen_Text(0.5, 0.6, "Applying force") ENDIF ENDPROC FUNC BOOL Should_Beast_Counter_Hit() IF sBeastFinaleVars.iHitCount = MAX_HITS //If we're at max hits OR (NOT IS_PED_DEAD_OR_DYING(PLAYER_PED_ID()) AND IS_PED_ARMED(PLAYER_PED_ID(), WF_INCLUDE_MELEE)) //If we're using a melee weapon RETURN TRUE ENDIF RETURN FALSE ENDFUNC PROC Update_Beast() //Local vars VECTOR vBeastStartLoc = g_vBeastFinaleStartPoint VECTOR vJumpOffPlanePoint = g_vBeastFinaleJumpOffPoint SCRIPTTASKSTATUS status BOOL bCheating = FALSE INT i, iNumCars VEHICLE_INDEX vehNearCars[10] FLOAT fHeading SEQUENCE_INDEX si #IF IS_DEBUG_BUILD TEXT_LABEL_23 tl #ENDIF IF IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) CERRORLN(debug_hunting, "Can't update beast, entity dead") EXIT ENDIF // DISPLAY_RADAR(TRUE) //Constant updates SET_PED_RESET_FLAG(sBeastFinaleVars.pedBeast, PRF_InfiniteStamina, TRUE) SET_PED_RESET_FLAG(sBeastFinaleVars.pedBeast, PRF_PreventAllMeleeTakedowns, TRUE) SET_PED_RESET_FLAG(sBeastFinaleVars.pedBeast, PRF_IgnoreCombatManager, TRUE) SET_PED_MOVE_RATE_OVERRIDE(sBeastFinaleVars.pedBeast, 1.75) //Fail check IF sBeastFinaleVars.eBeastFightingState != BFS_Run_Away AND NOT (IS_ENTITY_DEAD(PLAYER_PED_ID()) OR IS_ENTITY_AT_COORD(PLAYER_PED_ID(), g_vBeastFinaleArenaPos,g_vBeastFinaleArenaSize)) VECTOR vPos = GET_ENTITY_COORDS(PLAYER_PED_ID(), false) CPRINTLN(debug_hunting, "Player at ",vpos," not at ",g_vBeastFinaleArenaPos," / ",g_vBeastFinaleArenaSize) Set_Beast_State(BFS_Run_Away) ENDIF //Check if player is cheating/modding bCheating = Maintain_Beast_Cheating_Check() //Check if beast has just punched the player Maintain_Apply_Beast_Punches_To_Ped(PLAYER_PED_ID(), sBeastFinaleVars.pedBeast,DEFAULT,sBeastFinaleVars.fPushForce, 500+300*sBeastFinaleVars.iHitCount) //Scaling damage with hit count Maintain_Player_Hit_Combo(sBeastFinaleVars.pedBeast, sBeastFinaleVars.iTimerHit, sBeastFinaleVars.iHitCount) //Apply constant countering IF Should_Beast_Counter_Hit() OR bCheating //Uncomment this to get the counter working SET_PED_RESET_FLAG(sBeastFinaleVars.pedBeast, PRF_ForceMeleeCounter, TRUE) CPRINTLN(debug_hunting, "Either max hit combo or player armed with melee, countering") ENDIF //Pinned under car check BOOL bUnderCar = FALSE IF IS_PED_RAGDOLL(sBeastFinaleVars.pedBeast) iNumCars = GET_PED_NEARBY_VEHICLES(sBeastFinaleVars.pedBeast, vehNearCars) FOR i = 0 to iNumCars - 1 IF NOT IS_ENTITY_DEAD(vehNearCars[i]) IF IS_ENTITY_TOUCHING_ENTITY(sBeastFinaleVars.pedBeast, vehNearCars[i]) //AND GET_ENTITY_HEIGHT_ABOVE_GROUND(sBeastFinaleVars.pedBeast) < GET_ENTITY_HEIGHT_ABOVE_GROUND(vehNearCars[i]) //Beast_Display_Onscreen_Text(0.8,0.8, "Under Car", 0.3) bUnderCar = TRUE IF sBeastFinaleVars.iUnderCarTime + BF_STUCK_UNDER_CAR_TIME < GET_GAME_TIMER() //Apply force to car VECTOR vForce = NORMALISE_VECTOR(GET_ENTITY_COORDS(vehNearCars[i]) - GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast)) vForce = vForce * sBeastFinaleVars.fPushForce APPLY_FORCE_TO_ENTITY(vehNearCars[i], APPLY_TYPE_IMPULSE, vForce, <<0,0,0>>, 0, FALSE, TRUE, TRUE) CPRINTLN(debug_hunting,"Applied force on car!") ENDIF ENDIF ENDIF ENDFOR ENDIF IF NOT bUnderCar sBeastFinaleVars.iUnderCarTime = GET_GAME_TIMER() ENDIF SWITCH sBeastFinaleVars.eBeastFightingState CASE BFS_Intro //Check if player looking at beast, trigger anim IF sBeastFinaleVars.iProg = 0 AND IS_SPHERE_VISIBLE(vBeastStartLoc, 1.0) AND NOT IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) //Draw attention, activate fight SET_GAMEPLAY_ENTITY_HINT(sBeastFinaleVars.pedBeast,<<0,0,0>>,DEFAULT, 1000,1000) TASK_PLAY_ANIM(sBeastFinaleVars.pedBeast, sBeastFinaleVars.sTransformAnimDict //"ANIM@MP_FM_EVENT@INTRO" ,sBeastFinaleVars.sTransformAnim, INSTANT_BLEND_IN, NORMAL_BLEND_OUT,DEFAULT,DEFAULT,0.2) //"BEAST_TRANSFORM" IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) Play_Beast_Sound_From_Position(GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast)) SET_BIT(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) ENDIF Destroy_Player_Vehicle() sBeastFinaleVars.iProg++ ELIF sBeastFinaleVars.iProg = 1 //Jump off plane IF NOT IS_ENTITY_PLAYING_ANIM(sBeastFinaleVars.pedBeast, sBeastFinaleVars.sTransformAnimDict, sBeastFinaleVars.sTransformAnim) OPEN_SEQUENCE_TASK(si) TASK_ACHIEVE_HEADING(NULL, GET_HEADING_BETWEEN_VECTORS_2D(g_vBeastFinaleStartPoint, vJumpOffPlanePoint) -20) TASK_JUMP(NULL, TRUE, TRUE) CLOSE_SEQUENCE_TASK(si) TASK_PERFORM_SEQUENCE(sBeastFinaleVars.pedBeast, si) CLEAR_SEQUENCE_TASK(si) Set_Beast_State(BFS_Approach_Player) ENDIF ENDIF BREAK CASE BFS_Approach_Player IF GET_SCRIPT_TASK_STATUS(sBeastFinaleVars.pedBeast,SCRIPT_TASK_PERFORM_SEQUENCE) > PERFORMING_TASK OR VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast)) < 4 //2x2 Set_Beast_State(BFS_Attack_Player, GET_RANDOM_INT_IN_RANGE(8,15)*1000) ENDIF BREAK CASE BFS_Attack_Player //Check if beast lost the combat ped task status = GET_SCRIPT_TASK_STATUS(sBeastFinaleVars.pedBeast, SCRIPT_TASK_COMBAT) IF status != PERFORMING_TASK AND status != WAITING_TO_START_TASK AND GET_GAME_TIMER() > sBeastFinaleVars.iTimer2 + 500 //Don't constantly re-task CPRINTLN(debug_hunting,"Tasking beast to combat player, was ",status) CLEAR_PED_TASKS(sBeastFinaleVars.pedBeast) TASK_COMBAT_PED(sBeastFinaleVars.pedBeast, PLAYER_PED_ID()) sBeastFinaleVars.iTimer2 = GET_GAME_TIMER() ENDIF //Check if beast should wait for the player to get up IF IS_PED_RAGDOLL(PLAYER_PED_ID()) Knock_Player_Weapon() Set_Beast_State(BFS_Let_Player_Get_Up) ENDIF //Check if we should call for backup IF GET_GAME_TIMER() > sBeastFinaleVars.iTimerStage Set_Beast_State(BFS_Call_Backup) ENDIF BREAK CASE BFS_Let_Player_Get_Up #IF IS_DEBUG_BUILD IF sBeastFinaleVars.bDebugDrawTriggers tl = "Get up timer: " tl += GET_GAME_TIMER() - sBeastFinaleVars.iTimer2 Beast_Display_Onscreen_Text(0.4,0.5,tl, 0.3) ENDIF #ENDIF IF sBeastFinaleVars.iProg = 0 CLEAR_PED_TASKS(sBeastFinaleVars.pedBeast) i = GET_RANDOM_INT_IN_RANGE(0,BF_NUM_TAUNT_ANIMS) fHeading = GET_HEADING_BETWEEN_VECTORS_2D(GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast, false), GET_ENTITY_COORDS(PLAYER_PED_ID(), false)) OPEN_SEQUENCE_TASK(si) TASK_ACHIEVE_HEADING(null,fHeading) TASK_PLAY_ANIM(null,sBeastFinaleVars.sTauntAnimDicts[i],sBeastFinaleVars.sTauntAnims[i]) CLOSE_SEQUENCE_TASK(si) TASK_PERFORM_SEQUENCE(sBeastFinaleVars.pedBeast, si) CLEAR_SEQUENCE_TASK(si) sBeastFinaleVars.iTimer2 = GET_GAME_TIMER() + 4000 sBeastFinaleVars.iProg++ ELIF sBeastFinaleVars.iProg = 1 status = GET_SCRIPT_TASK_STATUS(sBeastFinaleVars.pedBeast, SCRIPT_TASK_PLAY_ANIM) IF NOT IS_PED_RAGDOLL(PLAYER_PED_ID()) AND NOT IS_PED_GETTING_UP(PLAYER_PED_ID()) CLEAR_PED_TASKS(sBeastFinaleVars.pedBeast) Set_Beast_State(BFS_Attack_Player, GET_RANDOM_INT_IN_RANGE(7,15)*1000) ELIF GET_GAME_TIMER() > sBeastFinaleVars.iTimer2 sBeastFinaleVars.iProg = 0 ENDIF ENDIF BREAK CASE BFS_Call_Backup IF sBeastFinaleVars.iProg = 0 //Start the anim, set ped melee-proof SET_ENTITY_PROOFS(sBeastFinaleVars.pedBeast, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE) TASK_PLAY_ANIM(sBeastFinaleVars.pedBeast, sBeastFinaleVars.sTransformAnimDict, sBeastFinaleVars.sTransformAnim , NORMAL_BLEND_IN, NORMAL_BLEND_OUT, DEFAULT,DEFAULT,0.3) sBeastFinaleVars.iProg++ ELIF sBeastFinaleVars.iProg = 1 SET_PED_RESET_FLAG(sBeastFinaleVars.pedBeast, PRF_DisableMeleeHitReactions, TRUE) IF GET_SCRIPT_TASK_STATUS(sBeastFinaleVars.pedBeast,SCRIPT_TASK_PLAY_ANIM) = PERFORMING_TASK //Play beast sound when he's actually animating IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) Play_Beast_Sound_From_Position(GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast)) Stun_Player_On_Shout(3, bCheating) //Push player away SET_BIT(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) sBeastFinaleVars.iProg++ ENDIF ENDIF ELIF sBeastFinaleVars.iProg = 2 IF GET_SCRIPT_TASK_STATUS(sBeastFinaleVars.pedBeast,SCRIPT_TASK_PLAY_ANIM) > PERFORMING_TASK //Reset beast proofs SET_ENTITY_PROOFS(sBeastFinaleVars.pedBeast, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE) sBeastFinaleVars.iTimer = 0 Set_Beast_State(BFS_Attack_Player, GET_RANDOM_INT_IN_RANGE(7,15)*1000) ENDIF ENDIF BREAK CASE BFS_Run_Away IF sBeastFinaleVars.iProg = 0 //Set the beast to run away from the player CPRINTLN(debug_hunting,"Player outside of combat arena, running away") IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedBeast) TASK_SMART_FLEE_PED(sBeastFinaleVars.pedBeast, PLAYER_PED_ID(), 200, -1) ENDIF sBeastFinaleVars.iProg++ ELIF sBeastFinaleVars.iProg = 1 IF IS_ENTITY_OCCLUDED(sBeastFinaleVars.pedBeast) CPRINTLN(debug_hunting,"Fleeing beast not visible, deleting ped") Fail_Beast_Fight() sBeastFinaleVars.iProg++ ENDIF ENDIF BREAK ENDSWITCH ENDPROC PROC Update_Beast_Animal_Friends() INT iAnimalIndex REPEAT BF_MAX_ANIMALS_TO_SPAWN iAnimalIndex IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedAnimals[iAnimalIndex]) IF NOT IS_ENTITY_DEAD(sBeastFinaleVars.pedAnimals[iAnimalIndex]) SET_PED_RESET_FLAG(sBeastFinaleVars.pedAnimals[iAnimalIndex], PRF_IgnoreCombatManager, TRUE) ENDIF ENDIF ENDREPEAT ENDPROC PROC Spawn_Beast_Animal_Friend() //Pick model. MODEL_NAMES eAnimalModel IF GET_RANDOM_INT_IN_RANGE(0,100) < 10 //10% chance of mountain lion eAnimalModel = Get_Beast_Hint_Model_A(BHT_LION) ELSE eAnimalModel = Get_Rottweiler_Model() ENDIF //Pick spawn point. INT iSpawnPoint = GET_RANDOM_INT_IN_RANGE(0, BF_ANIMAL_SPAWN_POINT_COUNT) WHILE NOT WOULD_ENTITY_BE_OCCLUDED(eAnimalModel, g_vBeastFinaleAnimalSpawnVec[iSpawnPoint]) iSpawnPoint = GET_RANDOM_INT_IN_RANGE(0, BF_ANIMAL_SPAWN_POINT_COUNT) ENDWHILE CPRINTLN(DEBUG_HUNTING, "Spawning Beast animal friend. Spawn:", iSpawnPoint, " Model:", PICK_STRING(eAnimalModel = A_C_MTLION, "MTLION", "ROTTWEILER"), ".") INT iAnimalIndex REPEAT BF_MAX_ANIMALS_TO_SPAWN iAnimalIndex IF NOT DOES_ENTITY_EXIST(sBeastFinaleVars.pedAnimals[iAnimalIndex]) sBeastFinaleVars.pedAnimals[iAnimalIndex] = CREATE_PED( PEDTYPE_SPECIAL, eAnimalModel, g_vBeastFinaleAnimalSpawnVec[iSpawnPoint], g_vBeastFinaleAnimalSpawnHead[iSpawnPoint], FALSE, FALSE) SET_PED_RELATIONSHIP_GROUP_HASH(sBeastFinaleVars.pedAnimals[iAnimalIndex], sBeastFinaleVars.relGroupHashBeast) SET_COMBAT_FLOAT(sBeastFinaleVars.pedAnimals[iAnimalIndex], CCF_FIGHT_PROFICIENCY, 1.0) SET_PED_COMBAT_ABILITY(sBeastFinaleVars.pedAnimals[iAnimalIndex], CAL_PROFESSIONAL) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_DISABLE_PIN_DOWN_OTHERS, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_AGGRESSIVE, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_ALWAYS_FIGHT, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_PERFECT_ACCURACY, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_MAINTAIN_MIN_DISTANCE_TO_TARGET, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_CAN_FIGHT_ARMED_PEDS_WHEN_NOT_ARMED, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_CAN_CHARGE, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_CAN_SEE_UNDERWATER_PEDS, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_DISABLE_FLEE_FROM_COMBAT, TRUE) SET_PED_COMBAT_ATTRIBUTES(sBeastFinaleVars.pedAnimals[iAnimalIndex], CA_DISABLE_SEEK_DUE_TO_LINE_OF_SIGHT, FALSE) OPEN_SEQUENCE_TASK(sBeastFinaleVars.seqAnimalAttack[iAnimalIndex]) TASK_GO_TO_ENTITY(NULL, PLAYER_PED_ID(), -1, 4.0) TASK_COMBAT_PED(NULL, PLAYER_PED_ID()) CLOSE_SEQUENCE_TASK(sBeastFinaleVars.seqAnimalAttack[iAnimalIndex]) TASK_PERFORM_SEQUENCE(sBeastFinaleVars.pedAnimals[iAnimalIndex], sBeastFinaleVars.seqAnimalAttack[iAnimalIndex]) CLEAR_SEQUENCE_TASK(sBeastFinaleVars.seqAnimalAttack[iAnimalIndex]) EXIT ENDIF ENDREPEAT ENDPROC PROC Destroy_Beast() CPRINTLN(DEBUG_HUNTING, "Destroying beast.") IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedBeast) sBeastFinaleVars.iSyncScene = -1 IF NOT IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) CLEAR_PED_TASKS(sBeastFinaleVars.pedBeast) ENDIF DELETE_PED(sBeastFinaleVars.pedBeast) ENDIF CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) ENDPROC FUNC BOOL Is_Beast_Fight_Allowed_To_Run() RETURN IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) AND NOT IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_FIGHT_FAILED) AND NOT IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) AND GET_PLAYER_MODEL() = Get_Sasquatch_Model() AND NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR) //No Director Mode fight ENDFUNC PROC Maintain_Beast_Hidden_Trigger() IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) //Player inside streaming range. IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), g_vBeastFinaleRootPosition) < BF_STREAM_IN_RANGE_SQR IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_REQUESTED_ASSETS) Request_Beast_Finale_Assets() ELIF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) IF Have_Beast_Finale_Assets_Loaded() Create_Beast(g_vBeastFinaleRootPosition - <<0.1, -0.1, -1>>, -20.400, FALSE) //Preload fight music. PREPARE_MUSIC_EVENT(sBeastFinaleVars.sFightMusic) ENDIF //Beast created in world. ELSE //Apply beast per-frame flags IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedBeast) IF NOT IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) SET_PED_RESET_FLAG(sBeastFinaleVars.pedBeast, PRF_DisablePotentialBlastReactions, TRUE) ENDIF ENDIF //Make the beast leave if the player gets too close. IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_WAITING) IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), g_vBeastFinaleRootPosition) < BF_LEAVE_TIMER_RANGE_SQR CPRINTLN(DEBUG_HUNTING, "Player triggered wait timer.") sBeastFinaleVars.iTimer = GET_GAME_TIMER() + BF_VISIBLE_TIME SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_WAITING) ENDIF ELSE IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_LEAVING) IF GET_GAME_TIMER() > sBeastFinaleVars.iTimer OR IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_INJURED) CPRINTLN(DEBUG_HUNTING, "Beast started leaving.") IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_INJURED) Play_Beast_Sound_From_Position( GET_ENTITY_COORDS(sBeastFinaleVars.pedBeast, FALSE)) SET_BIT(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) ENDIF sBeastFinaleVars.iTimer = GET_GAME_TIMER() + BF_BUSH_SLIDE_TIME SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_LEAVING) ENDIF ELSE IF sBeastFinaleVars.iSyncScene != -1 TASK_PLAY_ANIM(sBeastFinaleVars.pedBeast, sBeastFinaleVars.sTauntAnimDicts[3], sBeastFinaleVars.sTauntAnims[3], INSTANT_BLEND_IN,INSTANT_BLEND_OUT,-1, AF_DEFAULT,0.2) sBeastFinaleVars.iSyncScene = -1 ENDIF IF GET_GAME_TIMER() > sBeastFinaleVars.iTimer CPRINTLN(DEBUG_HUNTING, "Beast sliding into the bush.") Destroy_Beast() //Release_Beast_Finale_Assets(iState) SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_WINDOW_PASSED) IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_INJURED) CPRINTLN(DEBUG_HUNTING, "The player injured the beast. Waiting for player to investigate...") //Set up some ambience: Weather, time-of-day, music. TEXT_LABEL_23 tlWeather = Build_Beast_String_23("HUN", "T", "R", "DE") //"THUNDER" SET_WEATHER_TYPE_OVERTIME_PERSIST(tlWeather, 15.0) PAUSE_CLOCK(TRUE) TRIGGER_MUSIC_EVENT(sBeastFinaleVars.sFightMusic) SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_FIGHT_ACTIVE) //Disable wanted levels and active police CLEAR_PLAYER_WANTED_LEVEL(PLAYER_ID()) sBeastFinaleVars.iStartWantedLevel = GET_MAX_WANTED_LEVEL() SET_MAX_WANTED_LEVEL(0) ELSE CPRINTLN(DEBUG_HUNTING, "The player missed the beast. Event over.") Fail_Beast_Fight() ENDIF EXIT ENDIF ENDIF ENDIF //Pass the event if the player injures the beast. IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(sBeastFinaleVars.pedBeast, PLAYER_PED_ID()) OR IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE,g_vBeastFinaleRootPosition, 5) OR VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), g_vBeastFinaleRootPosition) < 25 //5*5 CPRINTLN(DEBUG_HUNTING, "Beast damage/proximity detected.") SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_INJURED) ENDIF ENDIF ENDIF //Player outside streaming range. ELIF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), g_vBeastFinaleRootPosition) > BF_STREAM_OUT_RANGE_SQR IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) Destroy_Beast() ENDIF IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_REQUESTED_ASSETS) Release_Beast_Finale_Assets() ENDIF CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_LEAVING) ENDIF ENDIF ENDPROC PROC Update_Beast_Fight_Time() IF GET_TIMEOFDAY_HOUR(g_todCurrent) != 4 //Force fight to take place around 4:45am OR GET_TIMEOFDAY_MINUTE(g_todCurrent) < 40 OR GET_TIMEOFDAY_MINUTE(g_todCurrent) > 50 TIMEOFDAY todFight = g_todCurrent ADD_TIME_TO_TIMEOFDAY(todFight, 0, 2) //Fast forward time by 1 min per frame. SET_CLOCK_TIME(GET_TIMEOFDAY_HOUR(todFight), GET_TIMEOFDAY_MINUTE(todFight), GET_TIMEOFDAY_SECOND(todFight)) SET_CLOCK_DATE(GET_TIMEOFDAY_DAY(todFight), GET_TIMEOFDAY_MONTH(todFight), GET_TIMEOFDAY_YEAR(todFight)) ENDIF ENDPROC PROC Maintain_Beast_Fight() Update_Beast_Fight_Time() IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) sBeastFinaleVars.iDeadFrames = 0 //Wait for player to go and check The Beast's coords. IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) IF IS_ENTITY_AT_COORD(PLAYER_PED_ID(), g_vBeastFinaleCheckPos,<<3.00000,3.00000,2.000000>>) AND IS_SPHERE_VISIBLE(g_vBeastFinaleRootPosition - <<0.3, 1, -1>>,0.5) CPRINTLN(DEBUG_HUNTING, "Player went to investigate. Spwaning beast fight.") Create_Beast(g_vBeastFinaleStartPoint, -155, TRUE) Set_Beast_State(BFS_Intro) SET_BIT(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) sBeastFinaleVars.iTimer = -1//GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(4000, 20000) //No longer spawns companion by default SET_BIT(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) ENDIF //Check if player buggered off after damagint the beast IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), g_vBeastFinaleRootPosition) > BF_STREAM_OUT_RANGE_SQR CPRINTLN(debug_hunting,"Player left area after hurting beast, cancelling") Cleanup_Beast_Fight() ENDIF //Fight running. ELIF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_DEAD) Update_Beast() Update_Beast_Animal_Friends() IF GET_GAME_TIMER() > sBeastFinaleVars.iTimer AND sBeastFinaleVars.iTimer > -1 Spawn_Beast_Animal_Friend() sBeastFinaleVars.iTimer = -1 // GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(8000, 15000) ENDIF IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedBeast) IF IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) CPRINTLN(DEBUG_HUNTING, "The beast was killed. Starting transition out.") sBeastFinaleVars.iTimer = GET_GAME_TIMER() + 2000 SET_PLAYER_CONTROL(PLAYER_ID(), FALSE) TASK_PLAY_ANIM(PLAYER_PED_ID(), sBeastFinaleVars.sTransformAnimDict //"ANIM@MP_FM_EVENT@INTRO" ,sBeastFinaleVars.sTransformAnim, NORMAL_BLEND_IN, NORMAL_BLEND_OUT) SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_DEAD) ENDIF ENDIF ENDIF ELSE IF GET_GAME_TIMER() > sBeastFinaleVars.iTimer SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) //Display an unlock message that hints the player towards the Director Mode "WildBeast" character. CPRINTLN(DEBUG_HUNTING, "Event complete! Display beast unlocked feed message.") TEXT_LABEL_23 tlFeedImage = Build_Beast_String_23("R_A", "CHA", "G_UP", "CTIN") //"CHAR_ACTING_UP" TEXT_LABEL_23 tlFeedCharName = Build_Beast_String_23("_FEE", "DI", "AR", "D_CH") //"DI_FEED_CHAR" TEXT_LABEL_23 tlFeedSubtitle = Build_Beast_String_23("AIR_G", "H", "0", "ROUP_E") //"HAIR_GROUP_E0" BEGIN_TEXT_COMMAND_THEFEED_POST("") END_TEXT_COMMAND_THEFEED_POST_MESSAGETEXT_SUBTITLE_LABEL(tlFeedImage, tlFeedImage, FALSE, TEXT_ICON_BLANK, tlFeedCharName, tlFeedSubtitle) //Hack, tell scripts that the player has died to force the peyote trip to end. g_bAnimalControllerFakeDeath = TRUE Cleanup_Beast_Fight() ENDIF ENDIF ELSE //Dead time buffer: Make sure player dead for a few frames before cancelling the fight sBeastFinaleVars.iDeadFrames += 1 IF sBeastFinaleVars.iDeadFrames > BF_MAX_DEAD_FRAMES CPRINTLN(debug_hunting, "Player killed, beast fight failed!") Fail_Beast_Fight() EXIT ENDIF ENDIF ENDPROC PROC Maintain_Beast_Sound() IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) IF HAS_SOUND_FINISHED(sBeastFinaleVars.iSoundID) STOP_SOUND(sBeastFinaleVars.iSoundID) RELEASE_SOUND_ID(sBeastFinaleVars.iSoundID) sBeastFinaleVars.iSoundID = -1 CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_SOUND_PLAYING) ENDIF ENDIF ENDPROC PROC Maintain_Beast_Finale() IF Has_Beast_Secret_Data_Setup_Finished() IF NOT IS_BITMASK_SET(g_iBeastSetupInt,BH_Bit_Fight_Init) CPRINTLN(debug_hunting,"Fight data init now set-up, running the Beast Fight scripts") SET_BITMASK(g_iBeastSetupInt,BH_Bit_Fight_Init) ENDIF ELSE EXIT //Don't do anything until data setup finishes ENDIF IF Is_Beast_Fight_Allowed_To_Run() IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_ALLOWED_TO_RUN_LAST_FRAME) CPRINTLN(debug_hunting, "Beast Fight finale now allowed to run") SET_BIT(sBeastFinaleVars.iState, BF_BIT_ALLOWED_TO_RUN_LAST_FRAME) ENDIF IF NOT IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_WINDOW_PASSED) Maintain_Beast_Hidden_Trigger() ELIF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_BEAST_FIGHT_ACTIVE) Maintain_Beast_Fight() ENDIF //Manage ending the sound if it is playing. Maintain_Beast_Sound() //Don't let the player record any of this. REPLAY_PREVENT_RECORDING_AND_UI_THIS_FRAME() ELSE IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_ALLOWED_TO_RUN_LAST_FRAME) CPRINTLN(debug_hunting, "Fight not allowed now, bits: HUNT_COMPLETED:", IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED), " FIGHT_FAILED: ",IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_FIGHT_FAILED), " KILLED_AND_UNLOCKED:", IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED)) //Fail the fight if the beast not defeated IF NOT IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) Fail_Beast_Fight() ENDIF CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_ALLOWED_TO_RUN_LAST_FRAME) ENDIF ENDIF ENDPROC #IF IS_DEBUG_BUILD PROC Create_Beast_Finale_Widgets(WIDGET_GROUP_ID widgetID) CPRINTLN(DEBUG_HUNTING, "Creating beast finale widgets from ",GET_THIS_SCRIPT_NAME()) IF widgetID != NULL SET_CURRENT_WIDGET_GROUP(widgetID) ENDIF START_WIDGET_GROUP("Beast Finale") ADD_WIDGET_BOOL("Warp to location", sBeastFinaleVars.bDebugWarpToLocation) ADD_WIDGET_BOOL("Set fight ready to trigger", sBeastFinaleVars.bDebugCompleteHunt) ADD_WIDGET_BOOL("Set Beast low health", sBeastFinaleVars.bDebugSetBeastLowHealth) ADD_WIDGET_BOOL("Terminate thread", sBeastFinaleVars.bDebugTerminateThread) ADD_WIDGET_BOOL("Draw triggers", sBeastFinaleVars.bDebugDrawTriggers) ADD_WIDGET_BOOL("Start fight", sBeastFinaleVars.bDebugBeastDamaged) ADD_WIDGET_BOOL("Draw animal spawns", sBeastFinaleVars.bDebugDrawAnimalSpawns) ADD_WIDGET_BOOL("Toggle beast killed", sBeastFinaleVars.bDebugToggleBeastKilled) ADD_WIDGET_BOOL("Beast killed and unlocked", sBeastFinaleVars.bDebugBeastKilledAndUnlocked) ADD_WIDGET_FLOAT_SLIDER("Push force", sBeastFinaleVars.fPushForce,1,200,0.5) STOP_WIDGET_GROUP() IF widgetID != NULL CLEAR_CURRENT_WIDGET_GROUP(widgetID) ENDIF ENDPROC PROC Update_Beast_Finale_Widgets(BOOL bAllowTerminate = TRUE) IF sBeastFinaleVars.bDebugTerminateThread OR IS_DEBUG_KEY_JUST_PRESSED(KEY_F, KEYBOARD_MODIFIER_CTRL_SHIFT, "Terminate thread") //Also use F to kill CPRINTLN(DEBUG_HUNTING, "Beast finale thread terminating from widget.") IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) Destroy_Beast() Cleanup_Beast_Fight() ENDIF IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_REQUESTED_ASSETS) Release_Beast_Finale_Assets() ENDIF CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_LEAVING) IF bAllowTerminate TERMINATE_THIS_THREAD() ENDIF ENDIF IF sBeastFinaleVars.bDebugWarpToLocation IF IS_PLAYER_PLAYING(PLAYER_ID()) AND NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) CPRINTLN(DEBUG_HUNTING, "Starting warp to beast finale location from widget...") SET_ENTITY_COORDS(PLAYER_PED_ID(), g_vBeastFinaleCheckPos - <<1, -82, 0>>, FALSE) SET_ENTITY_HEADING(PLAYER_PED_ID(),176.0174) // WHILE IS_PLAYER_TELEPORT_ACTIVE() // WAIT(0) // ENDWHILE SET_GAMEPLAY_CAM_RELATIVE_HEADING() SET_GAMEPLAY_CAM_RELATIVE_PITCH() CPRINTLN(DEBUG_HUNTING, "Warp finished.") ENDIF sBeastFinaleVars.bDebugWarpToLocation = FALSE ENDIF IF sBeastFinaleVars.bDebugSetBeastLowHealth IF DOES_ENTITY_EXIST(sBeastFinaleVars.pedBeast) AND NOT IS_ENTITY_DEAD(sBeastFinaleVars.pedBeast) SET_ENTITY_HEALTH(sBeastFinaleVars.pedBeast, 200) ENDIF sBeastFinaleVars.bDebugSetBeastLowHealth = FALSE ENDIF IF sBeastFinaleVars.bDebugCompleteHunt sBeastFinaleVars.bDebugCompleteHunt = FALSE SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) CLEAR_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_FIGHT_FAILED) CLEAR_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) ENDIF IF sBeastFinaleVars.bDebugBeastDamaged sBeastFinaleVars.bDebugBeastDamaged = FALSE SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_WINDOW_PASSED) SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_INJURED) SET_BIT(sBeastFinaleVars.iState, BF_BIT_BEAST_FIGHT_ACTIVE) CLEAR_BIT(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) SET_ENTITY_COORDS(PLAYER_PED_ID(),g_vBeastFinaleCheckPos, FALSE) ENDIF IF sBeastFinaleVars.bDebugDrawTriggers OR sBeastFinaleVars.bDebugDrawAnimalSpawns IF NOT sBeastFinaleVars.bDebugDrawingEnabled SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) sBeastFinaleVars.bDebugDrawingEnabled = TRUE ENDIF ELSE IF sBeastFinaleVars.bDebugDrawingEnabled SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(FALSE) sBeastFinaleVars.bDebugDrawingEnabled = FALSE ENDIF ENDIF IF sBeastFinaleVars.bDebugDrawTriggers IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_CREATED_BEAST) DRAW_DEBUG_SPHERE(g_vBeastFinaleRootPosition, SQRT(BF_LEAVE_TIMER_RANGE_SQR), 0, 0, 255, 60) ENDIF IF IS_BIT_SET(sBeastFinaleVars.iState, BF_BIT_REQUESTED_ASSETS) DRAW_DEBUG_SPHERE(g_vBeastFinaleRootPosition, SQRT(BF_STREAM_OUT_RANGE_SQR), 255, 0, 0, 60) ELSE DRAW_DEBUG_SPHERE(g_vBeastFinaleRootPosition, SQRT(BF_STREAM_IN_RANGE_SQR), 0, 255, 0, 60) ENDIF ENDIF IF sBeastFinaleVars.bDebugDrawAnimalSpawns INT iSpawnIndex TEXT_LABEL tlSpawnName REPEAT BF_ANIMAL_SPAWN_POINT_COUNT iSpawnIndex tlSpawnName = "Spawn " tlSpawnName += iSpawnIndex DRAW_DEBUG_TEXT(tlSpawnName, g_vBeastFinaleAnimalSpawnVec[iSpawnIndex], 0, 0, 255) DRAW_DEBUG_SPHERE(g_vBeastFinaleAnimalSpawnVec[iSpawnIndex], 1.0, 0, 255, 0, 60) ENDREPEAT ENDIF IF sBeastFinaleVars.bDebugToggleBeastKilled IF IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) CPRINTLN(DEBUG_HUNTING, "Clearing beast as killed through widget.") CLEAR_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) ELSE CPRINTLN(DEBUG_HUNTING, "Setting beast as killed through widget.") SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) ENDIF sBeastFinaleVars.bDebugToggleBeastKilled = FALSE ENDIF sBeastFinaleVars.bDebugBeastKilledAndUnlocked = IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_KILLED_AND_UNLOCKED) ENDPROC #ENDIF //DEBUG #ENDIF //FEATURE_SP_DLC_BEAST_SECRET