USING "globals.sch" USING "rage_builtins.sch" USING "commands_water.sch" USING "commands_player.sch" USING "script_debug.sch" USING "script_clock.sch" USING "net_include.sch" USING "script_conversion.sch" USING "candidate_public.sch" USING "beast_secret_shared.sch" #IF FEATURE_SP_DLC_BEAST_SECRET //╒═════════════════════════════════════════════════════════════════════════════╕ //╞════════════════════════════ The Beast Hunt ═════════════════════════╡ //╘═════════════════════════════════════════════════════════════════════════════╛ CONST_INT BH_BIT_BEAST_SOUND_PLAYING 1 CONST_INT BH_BIT_HINT_LOADED 2 CONST_INT BH_BIT_HUNTER_SEEN 3 CONST_INT BH_BIT_CHECKPOINT_ITEM_TRIGGERED 4 CONST_INT BH_BIT_IGNORE_1ST_NODE 5 //This was saved to point to g_savedGlobals.sFlowCustom.spInitBitset CONST_INT BH_BITSHIFT_CURRENT_CHECKPOINT 14 CONST_INT BH_BITMASK_CURRENT_CHECKPOINT (BIT14|BIT15|BIT16|BIT17) CONST_INT BH_BITSHIFT_NEXT_CHECKPOINT 18 CONST_INT BH_BITMASK_NEXT_CHECKPOINT (BIT18|BIT19|BIT20|BIT21) CONST_INT BH_BITSHIFT_CURRENT_PATH_NODE 17 CONST_INT BH_BITMASK_CURRENT_PATH_NODE (BIT17|BIT18|BIT19|BIT20|BIT21|BIT22|BIT23|BIT24) CONST_FLOAT BH_CHECKPOINT_HINT_RADIUS 200.0 CONST_FLOAT BH_CHECKPOINT_RADIUS 35.0 CONST_FLOAT BH_PATH_NODE_RADIUS 17.0 CONST_FLOAT BH_ITEM_COLLECT_RADIUS 5. CONST_INT BH_SOUND_MIN_DELAY 4000 CONST_INT BH_SOUND_RANDOM_DELAY 4000 CONST_FLOAT BH_SOUND_DIST_FROM_PLAYER 60.0 CONST_FLOAT BH_SOUND_MIN_DIST_FROM_PLAYER 30.0 CONST_FLOAT BH_SOUND_MAX_RANGE_SQR 9000000.0 CONST_INT BH_RESET_TIME_DELAY 30000 //Time until the beast hunt becomes active again after failing the fight STRUCT BeastHuntVars INT iState INT iHintTrackedPoint INT iFadeOutTimer BOOL bCouldRunLastFrame BOOL bWasSasLastFrame FLOAT fCurrentMaxRadius //Max range before resetting the current path progress INT iNumPaths //Index for maximum paths currently stored INT iBeastSoundID = -1, iNextSoundTime VECTOR vSoundPos //This is relative FLOAT fSoundDist PED_INDEX pedHint VEHICLE_INDEX vehHint #IF IS_DEBUG_BUILD BOOL bDebugWidgetsInitialised = FALSE BOOL bDebugTerminateThread BOOL bDebugPeyotesComplete BOOL bDebugTogglePeyotesComplete BOOL bDebugHunterSeen BOOL bDebugToggleHunterSeen BOOL bDebugHuntComplete BOOL bDebugToggleHuntComplete BOOL bDebugDisplayCheckpoints BOOL bDebugDisplayPaths BOOL bDebugDisplayActivePath BOOL bDebugDisplayCurrentPath BOOL bDebugDrawingEnabled BOOL bWarpAndDisplay BOOL bDebugSetCurrentPath BOOL bSpreadPathNodes BOOL bPrintPathInformation BOOL bDebugDirectPath #ENDIF ENDSTRUCT FUNC INT Get_Beast_Hunt_Current_Checkpoint() INT iValue = Get_Int_From_Bitset(g_savedGlobals.sFlowCustom.spInitBitset, BH_BITMASK_CURRENT_CHECKPOINT, BH_BITSHIFT_CURRENT_CHECKPOINT) // CDEBUG2LN(DEBUG_HUNTING, "Read beast hunt current checkpoint as ", iValue, ".") RETURN iValue ENDFUNC PROC Set_Beast_Hunt_Current_Checkpoint(INT iValue) CDEBUG2LN(DEBUG_HUNTING, "Set beast hunt current checkpoint to ", iValue, ".") Set_Int_In_Bitset(g_savedGlobals.sFlowCustom.spInitBitset, iValue, BH_BITMASK_CURRENT_CHECKPOINT, BH_BITSHIFT_CURRENT_CHECKPOINT) ENDPROC FUNC INT Get_Beast_Hunt_Next_Checkpoint() INT iValue = Get_Int_From_Bitset(g_savedGlobals.sFlowCustom.spInitBitset, BH_BITMASK_NEXT_CHECKPOINT, BH_BITSHIFT_NEXT_CHECKPOINT) // CDEBUG2LN(DEBUG_HUNTING, "Read beast hunt next checkpoint as ", iValue, ".") RETURN iValue ENDFUNC PROC Set_Beast_Hunt_Next_Checkpoint(INT iValue) CDEBUG2LN(DEBUG_HUNTING, "Set beast hunt next checkpoint to ", iValue, ".") Set_Int_In_Bitset(g_savedGlobals.sFlowCustom.spInitBitset, iValue, BH_BITMASK_NEXT_CHECKPOINT, BH_BITSHIFT_NEXT_CHECKPOINT) ENDPROC FUNC INT Get_Beast_Hunt_Current_Path_Node(INT iState) INT iValue = SHIFT_RIGHT(iState & BH_BITMASK_CURRENT_PATH_NODE, BH_BITSHIFT_CURRENT_PATH_NODE) CDEBUG3LN(DEBUG_HUNTING, "Read beast hunt current path node as ", iValue, ".") RETURN iValue ENDFUNC PROC Set_Beast_Hunt_Current_Path_Node(INT &iState, INT iValue) CDEBUG2LN(DEBUG_HUNTING, "Set beast hunt current path node to ", iValue, ".") iState -= iState & BH_BITMASK_CURRENT_PATH_NODE iState |= SHIFT_LEFT(iValue, BH_BITSHIFT_CURRENT_PATH_NODE) ENDPROC PROC Add_Beast_Hunt_Path(BeastHuntVars &sBHV, INT iFirstCP, INT iSecondCP, BOOL bIsReversible, FLOAT x1=0.0, FLOAT y1=0.0, FLOAT z1=0.0, FLOAT x2=0.0, FLOAT y2=0.0, FLOAT z2=0.0, FLOAT x3=0.0, FLOAT y3=0.0, FLOAT z3=0.0, FLOAT x4=0.0, FLOAT y4=0.0, FLOAT z4=0.0, FLOAT x5=0.0, FLOAT y5=0.0, FLOAT z5=0.0, FLOAT x6=0.0, FLOAT y6=0.0, FLOAT z6=0.0, FLOAT x7=0.0, FLOAT y7=0.0, FLOAT z7=0.0, FLOAT x8=0.0, FLOAT y8=0.0, FLOAT z8=0.0) IF (sBHV.iNumPaths >= BH_MAX_PATH_COUNT) CERRORLN(debug_hunting, "Couldn't add path, max number of paths reached: ",sBHV.iNumPaths) EXIT ENDIF IF iFirstCP >= BH_CHECKPOINT_COUNT OR iSecondCp >= BH_CHECKPOINT_COUNT OR iFirstCP <0 OR iSecondCP <0 CERRORLN(debug_hunting, "Couldn't add path, checkpoint numbers out of range: ",iFirstCP, "/", iSecondCP) EXIT ENDIF g_iBHPathIndexes[iFirstCP][iSecondCP] = sbhv.iNumPaths g_bBHPathReversed[iFirstCP][iSecondCP] = FALSE IF bIsReversible g_bBHPathReversed[iSecondCP][iFirstCP] = TRUE g_iBHPathIndexes[iSecondCP][iFirstCP] = sbhv.iNumPaths ELSE g_bBHPathReversed[iSecondCP][iFirstCP] = FALSE g_iBHPathIndexes[iSecondCP][iFirstCP] = -1 ENDIF //Add nodes 1 by 1 INT iPath = 0 IF x1!=0 AND y1!=0 AND z1!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF IF x2!=0 AND y2!=0 AND z2!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF IF x3!=0 AND y3!=0 AND z3!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF IF x4!=0 AND y4!=0 AND z4!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF IF x5!=0 AND y5!=0 AND z5!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF IF x6!=0 AND y6!=0 AND z6!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF IF x7!=0 AND y7!=0 AND z7!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF IF x8!=0 AND y8!=0 AND z8!=0 g_sBHPath[sBHV.iNumPaths].vNode[iPath] = <> iPath++ ENDIF g_sBHPath[sBHV.iNumPaths].iLength = iPath CPRINTLN(debug_hunting, "Added path ",sBHV.inumPaths," with ",iPath," nodes") sBHV.iNumPaths++ ENDPROC PROC Add_Beast_Hunt_Path_Vec4(BeastHuntVars &sBHV, INT iFirstCP, INT iSecondCP, BOOL bIsReversible, VECTOR v1, VECTOR v2, VECTOR v3, VECTOR v4) Add_Beast_Hunt_Path(sBHV, iFirstCP, iSecondCP, bIsReversible, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z, v4.x, v4.y, v4.z) ENDPROC PROC Add_Beast_Hunt_Path_Vec3(BeastHuntVars &sBHV, INT iFirstCP, INT iSecondCP, BOOL bIsReversible, VECTOR v1, VECTOR v2, VECTOR v3) Add_Beast_Hunt_Path(sBHV, iFirstCP, iSecondCP, bIsReversible, v1.x, v1.y, v1.z, v2.x, v2.y, v2.z, v3.x, v3.y, v3.z) ENDPROC PROC Pick_Next_Checkpoint(BeastHuntVars &sBeastHuntVars) INT iLast = Get_Beast_Hunt_Current_Checkpoint() INT iJustFound = Get_Beast_Hunt_Next_Checkpoint() CPRINTLN(DEBUG_HUNTING, "Picking new checkpoint. Last:", iLast, " JustFound:", iJustFound) INT iNew = iLast INT iMaxTries = 50 WHILE (iNew = iLast) | (iNew = iJustFound) | (g_iBHPathIndexes[iJustFound][iNew] = -1) #IF IS_DEBUG_BUILD | ((sBeastHuntVars.bDebugDirectPath AND iNew < iLast AND iMaxTries > 0)) #ENDIF iNew = GET_RANDOM_INT_IN_RANGE(0, BH_CHECKPOINT_COUNT) iMaxTries-- ENDWHILE CPRINTLN(DEBUG_HUNTING, "Updating checkpoints. Current:", iJustFound, " Next:", iNew) Set_Beast_Hunt_Current_Checkpoint(iJustFound) Set_Beast_Hunt_Next_Checkpoint(iNew) ENDPROC FUNC INT Get_Beast_Hunt_Current_Path_And_Checkpoints(BeastHuntVars &sBeastHuntVars, INT &iCurrent, INT &iNext) //Debug and sanity check IF Get_Beast_Hunt_Current_Checkpoint() = Get_Beast_Hunt_Next_Checkpoint() Pick_Next_Checkpoint(sBeastHuntVars) ENDIF iCurrent = Get_Beast_Hunt_Current_Checkpoint() iNext = Get_Beast_Hunt_Next_Checkpoint() RETURN g_iBHPathIndexes[iCurrent][iNext] ENDFUNC FUNC BOOL Get_Beast_Hunt_Path_Endpoints(BeastHuntVars &sBeastHuntVars, INT iPath, INT& iStart, INT& iEnd) INT i, j sBeastHuntVars.iNumPaths = sBeastHuntVars.iNumPaths REPEAT BH_CHECKPOINT_COUNT i REPEAT BH_CHECKPOINT_COUNT j IF i != j AND g_iBHPathIndexes[i][j] = iPath IF g_bBHPathReversed[i][j] iStart = j iEnd = i ELSE iStart = i iEnd = j ENDIF RETURN TRUE ENDIF ENDREPEAT ENDREPEAT RETURN FALSE ENDFUNC FUNC BOOL Is_Node_Last_In_Path(BeastHuntVars &sBeastHuntVars, INT iNode) sBeastHuntVars.iState = sBeastHuntVars.iState //Unreferenced fix INT iCurCP, iNextCP INT iPath = Get_Beast_Hunt_Current_Path_And_Checkpoints(sBeastHuntVars, iCurCP, iNextCP) IF g_bBHPathReversed[iCurCP][iNextCP] RETURN (iNode = 0) ELSE RETURN (iNode = g_sBHPath[iPath].iLength + 1) ENDIF ENDFUNC FUNC BOOL Is_Node_First_In_Path(BeastHuntVars &sBeastHuntVars, INT iNode) sBeastHuntVars.iState = sBeastHuntVars.iState //Unreferenced fix INT iCurCP, iNextCP INT iPath = Get_Beast_Hunt_Current_Path_And_Checkpoints(sBeastHuntVars, iCurCP, iNextCP) IF NOT g_bBHPathReversed[iCurCP][iNextCP] RETURN (iNode = 0) ELSE RETURN (iNode = g_sBHPath[iPath].iLength + 1) ENDIF ENDFUNC FUNC VECTOR Get_Node_Location(BeastHuntVars &sBeastHuntVars, INT iNode) INT iCurCP = Get_Beast_Hunt_Current_Checkpoint() INT iNextCP = Get_Beast_Hunt_Next_Checkpoint() INT iPath = g_iBHPathIndexes[iCurCP][iNextCP] VECTOR vRes IF Is_Node_Last_In_Path(sBeasthuntvars, iNode) //Next checkpoint vRes = g_vBHCheckpoints[iNextCP] ELIF Is_Node_First_In_Path(sBeasthuntvars, iNode) //First checkpoint vRes = g_vBHCheckpoints[iCurCP] ELSE vRes = g_sBHPath[iPath].vNode[iNode-1] ENDIF // CPRINTLN(debug_hunting,"Returning node coord ", vRes) RETURN vRes ENDFUNC FUNC INT Get_Next_Node_In_Path(BeastHuntVars &sBeastHuntVars, int iNode) INT iCurCP = Get_Beast_Hunt_Current_Checkpoint() INT iNextCP = Get_Beast_Hunt_Next_Checkpoint() INT iPath = g_iBHPathIndexes[iCurCP][iNextCP] iPath = iPath IF Is_Node_Last_In_Path(sBeastHuntVars, iNode) CERRORLN(debug_hunting, "Can't advance node ",iNode,", it is last in path", iPath," (",iCurCP,"->",iNextCP,")") RETURN iNode ELSE IF g_bBHPathReversed[iCurCP][iNextCP] RETURN iNode -1 ELSE RETURN iNode +1 ENDIF ENDIF ENDFUNC PROC Reset_Node_In_Path(BeastHuntVars &sBeastHuntVars) INT iCurCP = Get_Beast_Hunt_Current_Checkpoint() INT iNextCP = Get_Beast_Hunt_Next_Checkpoint() INT iPath = g_iBHPathIndexes[iCurCP][iNextCP] INT iNextNode = 0 IF IS_BIT_SET(sBeastHuntVars.iState, BH_BIT_IGNORE_1ST_NODE) CPRINTLN(debug_hunting,"Ignoring the 1st node in the path") iNextNode = 1 CLEAR_BIT(sBeastHuntVars.iState, BH_BIT_IGNORE_1ST_NODE) ENDIF IF g_bBHPathReversed[iCurCP][iNextCP] iNextNode = g_sBHPath[iPath].iLength + 1 - iNextNode //This is to exclude the last if we're skipping it ENDIF Set_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState, iNextNode) CPRINTLN(debug_hunting,"Reset node progress to ",Get_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState)) ENDPROC PROC Reset_Beast_Hunt_Variables(BeastHuntVars &sBeastHuntVars) CPRINTLN(debug_hunting,"Resetting hunt path data") CLEAR_BITMASK(g_iBeastSetupInt,BH_Bit_Hunt_Init) //Force recreating the node array //Reset path matrix INT i, j REPEAT BH_CHECKPOINT_COUNT i REPEAT BH_CHECKPOINT_COUNT j g_iBHPathIndexes[i][j] = -1 ENDREPEAT ENDREPEAT sBeastHuntVars.iState = 0 sBeastHuntVars.iNumPaths = 0 sBeastHuntVars.fCurrentMaxRadius = -1 //<---------------PATH SETUP INFO HERE-----------------> //First node starts as the Sasquatch hunter and becomes a hiker //on subsequent visits. g_iBHCheckpointType[0] = BHT_HUNTER g_iBHCheckpointType[1] = BHT_DEER g_iBHCheckpointType[2] = BHT_BOAR g_iBHCheckpointType[3] = BHT_HIKER g_iBHCheckpointType[4] = BHT_HIKER g_iBHCheckpointType[5] = BHT_CAR_WRECK g_iBHCheckpointType[6] = BHT_LION g_iBHCheckpointType[7] = BHT_DEER g_iBHCheckpointType[8] = BHT_HIPPIE g_iBHCheckpointType[9] = BHT_REDNECK g_iBHCheckpointType[10] = BHT_REDNECK //Beast Peyote Y Set-up Set_Beast_Peyote_Vectors_Y() //Beast Hunt Z Set-up Set_Beast_Hunt_Vectors_Z() //Beast Fight Z Set-up Set_Beast_Fight_Vectors_z() //Rest of data init continues in Finalise_Data_Init() ENDPROC PROC Finalise_Data_Init(BeastHuntVars &sBeastHuntVars) CPRINTLN(debug_hunting,"Data init complete, creating Beast Hunt path arrays") //0 From 0 to 1 Add_Beast_Hunt_Path_Vec4(sBeastHuntVars, 0, 1, TRUE, g_vBHNodes[0 ][0], g_vBHNodes[0 ][1], g_vBHNodes[0 ][2], g_vBHNodes[0 ][3]) //1 From 0 to 3 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 0, 3, TRUE, g_vBHNodes[1 ][0], g_vBHNodes[1 ][1], g_vBHNodes[1 ][2]) //2 From 0 to 4 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 0, 4, TRUE, g_vBHNodes[2 ][0], g_vBHNodes[2 ][1], g_vBHNodes[2 ][2]) //3 From 1 to 2 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 1, 2, TRUE, g_vBHNodes[3 ][0], g_vBHNodes[3 ][1], g_vBHNodes[3 ][2]) //4 From 1 to 5 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 1, 5, TRUE, g_vBHNodes[4 ][0], g_vBHNodes[4 ][1], g_vBHNodes[4 ][2]) //5 From 2 to 3 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 2, 3, TRUE, g_vBHNodes[5 ][0], g_vBHNodes[5 ][1], g_vBHNodes[5 ][2]) //6 From 3 to 5 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 3, 5, TRUE, g_vBHNodes[6 ][0], g_vBHNodes[6 ][1], g_vBHNodes[6 ][2]) //7 From 3 to 6 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 3, 6, TRUE, g_vBHNodes[7 ][0], g_vBHNodes[7 ][1], g_vBHNodes[7 ][2]) //8 From 4 to 5 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 4, 5, TRUE, g_vBHNodes[8 ][0], g_vBHNodes[8 ][1], g_vBHNodes[8 ][2]) //9 From 4 to 6 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 4, 6, TRUE, g_vBHNodes[9 ][0], g_vBHNodes[9 ][1], g_vBHNodes[9 ][2]) //10 From 5 to 6 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 5, 6, TRUE, g_vBHNodes[10][0], g_vBHNodes[10][1], g_vBHNodes[10][2]) //11 From 5 to 8 Add_Beast_Hunt_Path_Vec4(sBeastHuntVars, 5, 8, TRUE, g_vBHNodes[11][0], g_vBHNodes[11][1], g_vBHNodes[11][2], g_vBHNodes[11 ][3]) //12 From 6 to 7 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 6, 7, TRUE, g_vBHNodes[12][0], g_vBHNodes[12][1], g_vBHNodes[12][2]) //13 From 6 to 8 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 6, 8, TRUE, g_vBHNodes[13][0], g_vBHNodes[13][1], g_vBHNodes[13][2]) //14 From 7 to 8 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 7, 8, TRUE, g_vBHNodes[14][0], g_vBHNodes[14][1], g_vBHNodes[14][2]) //15 From 7 to 9 Add_Beast_Hunt_Path_Vec4(sBeastHuntVars, 7, 9, TRUE, g_vBHNodes[15][0], g_vBHNodes[15][1], g_vBHNodes[15][2], g_vBHNodes[15 ][3]) //16 From 7 to 10 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 7, 10, TRUE, g_vBHNodes[16][0], g_vBHNodes[16][1], g_vBHNodes[16][2]) //17 From 8 to 9 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 8, 9, TRUE, g_vBHNodes[17][0], g_vBHNodes[17][1], g_vBHNodes[17][2]) //18 From 8 to 10 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 8, 10, TRUE, g_vBHNodes[18][0], g_vBHNodes[18][1], g_vBHNodes[18][2]) //19 From 9 to 10 Add_Beast_Hunt_Path_Vec3(sBeastHuntVars, 9, 10, TRUE, g_vBHNodes[19][0], g_vBHNodes[19][1], g_vBHNodes[19][2]) //<----------------END PATH SETUP INFO----------------> //Get current and next checkpoint IF Get_Beast_Hunt_Current_Checkpoint() = Get_Beast_Hunt_Next_Checkpoint() Pick_Next_Checkpoint(sBeastHuntVars) ENDIF // Set_Beast_Hunt_Current_Checkpoint(0) // Set_Beast_Hunt_Next_Checkpoint(0) Set_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState, 0) //Don't skip the start point ENDPROC PROC Reset_Beast_Sound_Time(BeastHuntVars &sBHV, INT iAddTime = 0) //Sets the sound to play as soon as possible sBHV.iNextSoundTime = GET_GAME_TIMER() + iAddTime ENDPROC PROC Reset_Max_Node_Range(BeastHuntVars &sBHV, FLOAT fAddedDist = BH_CHECKPOINT_RADIUS, BOOL bKeepOldMin = FALSE) FLOAT fOld = sBHV.fCurrentMaxRadius //Recalculate max distance before node reset IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) sBHV.fCurrentMaxRadius = VDIST(GET_ENTITY_COORDS(PLAYER_PED_ID()),Get_Node_Location(sBHV, Get_Beast_Hunt_Current_Path_Node(sBHV.iState))) + fAddedDist*2 sBHV.fCurrentMaxRadius = FMAX(sBHV.fCurrentMaxRadius , BH_CHECKPOINT_RADIUS * 3) sBHV.fCurrentMaxRadius *= sBHV.fCurrentMaxRadius ENDIF IF bKeepOldMin sBHV.fCurrentMaxRadius = FMIN(sBHV.fCurrentMaxRadius, fOld) ENDIF CPRINTLN(Debug_hunting, "Max distance to node ",Get_Beast_Hunt_Current_Path_Node(sBHV.iState)," changed from ",fOld," to ",sBHV.fCurrentMaxRadius) ENDPROC PROC Release_Checkpoint_Hint_Assets(BeastHuntVars &sBHV, BOOL bDelete = FALSE) IF DOES_ENTITY_EXIST(sBHV.vehHint) CDEBUG1LN(DEBUG_HUNTING, "Releasing vehicle entity.") IF bDelete DELETE_VEHICLE(sBHV.vehHint) ELSE SET_VEHICLE_AS_NO_LONGER_NEEDED(sBHV.vehHint) ENDIF ENDIF IF DOES_ENTITY_EXIST(sBHV.pedHint) CDEBUG1LN(DEBUG_HUNTING, "Releasing deer entity.") IF bDelete DELETE_PED(sBHV.pedHint) ELSE SET_PED_AS_NO_LONGER_NEEDED(sBHV.pedHint) ENDIF ENDIF IF IS_BIT_SET(sBHV.iState, BH_BIT_HINT_LOADED) CDEBUG1LN(DEBUG_HUNTING, "Releasing all hint models.") SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_HUNTER)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_B(BHT_HUNTER)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_HIKER)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_HIPPIE)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_REDNECK)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_DEER)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_LION)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_BOAR)) SET_MODEL_AS_NO_LONGER_NEEDED(Get_Beast_Hint_Model_A(BHT_CAR_WRECK)) CLEAR_BIT(sBHV.iState, BH_BIT_HINT_LOADED) ENDIF IF sBHV.iHintTrackedPoint != 0 CPRINTLN(DEBUG_HUNTING, "Destroying tracked point.") DESTROY_TRACKED_POINT(sBHV.iHintTrackedPoint) sBHV.iHintTrackedPoint = 0 ENDIF //Stop audio scene TEXT_LABEL_31 tlMixer = Build_Beast_String_31("til_P_","Exec_U","xer_Scene","B_Mi") //"Exec_Util_P_B_Mixer_Scene" IF IS_AUDIO_SCENE_ACTIVE(tlMixer) CPRINTLN(debug_hunting,"Stopping Beast mixer scene") STOP_AUDIO_SCENE(tlMixer) ENDIF ENDPROC PROC Manage_Checkpoint_Hint(BeastHuntVars &sBHV, VECTOR vPosition, INT iHintType, BOOL bRemoveExisting = FALSE) IF iHintType = BHT_HUNTER IF IS_BIT_SET(sBHV.iState, BH_BIT_HUNTER_SEEN) iHintType = BHT_HIKER ENDIF ENDIF MODEL_NAMES eHintModelA = Get_Beast_Hint_Model_A(iHintType) MODEL_NAMES eHintModelB = Get_Beast_Hint_Model_B(iHintType) VECTOR vHintEntityPosition = <<0,0,0>> //Manage hint creation. IF NOT DOES_ENTITY_EXIST(sBHV.pedHint) AND NOT DOES_ENTITY_EXIST(sBHV.vehHint) IF NOT IS_BIT_SET(sBHV.iState, BH_BIT_HINT_LOADED) //Request models. IF eHintModelA != DUMMY_MODEL_FOR_SCRIPT REQUEST_MODEL(eHintModelA) ENDIF IF eHintModelB != DUMMY_MODEL_FOR_SCRIPT REQUEST_MODEL(eHintModelB) ENDIF SET_BIT(sBHV.iState, BH_BIT_HINT_LOADED) ELSE //Check for models loading. BOOL bLoadedAllModels = TRUE IF eHintModelA != DUMMY_MODEL_FOR_SCRIPT IF NOT HAS_MODEL_LOADED(eHintModelA) bLoadedAllModels = FALSE ENDIF ENDIF IF eHintModelB != DUMMY_MODEL_FOR_SCRIPT IF NOT HAS_MODEL_LOADED(eHintModelB) bLoadedAllModels = FALSE ENDIF ENDIF IF bLoadedAllModels //Create hint. Create_Beast_Hint_Type(iHintType, sBHV.pedHint, sBHV.vehHint, vPosition) CLEAR_BIT(sBHV.iState, BH_BIT_CHECKPOINT_ITEM_TRIGGERED) IF sBHV.iHintTrackedPoint != 0 CPRINTLN(DEBUG_HUNTING, "Destroying old tracked point.") DESTROY_TRACKED_POINT(sBHV.iHintTrackedPoint) sBHV.iHintTrackedPoint = 0 ENDIF sBHV.iHintTrackedPoint = CREATE_TRACKED_POINT() CPRINTLN(DEBUG_HUNTING, "Created tracked point with value ", sBHV.iHintTrackedPoint, ".") SET_TRACKED_POINT_INFO(sBHV.iHintTrackedPoint, vPosition, GET_MODEL_LENGTH(eHintModelA)) ENDIF ENDIF ELSE IF DOES_ENTITY_EXIST(sBHV.pedHint) vHintEntityPosition = GET_ENTITY_COORDS(sBHV.pedHint, FALSE) ELIF DOES_ENTITY_EXIST(sBHV.vehHint) vHintEntityPosition = GET_ENTITY_COORDS(sBHV.vehHint, FALSE) ELSE //This should never get hit SCRIPT_ASSERT("Manage_Checkpoint_Hint: Neither a ped or vehicle existed for the hint. Failed to query position.") ENDIF //Has the entity moved a long way from its original location? //And is the player sufficiently far away to not see a respawn? IF bRemoveExisting IF NOT ARE_VECTORS_ALMOST_EQUAL(vHintEntityPosition, vPosition, 10, TRUE) AND VDIST(GET_ENTITY_COORDS(PLAYER_PED_ID()), vHintEntityPosition) > BH_CHECKPOINT_HINT_RADIUS Release_Checkpoint_Hint_Assets(sBHV) ENDIF ENDIF ENDIF //Manage hint focus. IF NOT IS_BIT_SET(sBHV.iState, BH_BIT_CHECKPOINT_ITEM_TRIGGERED) IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) AND NOT Is_White_Faded_Out() //Don't do the hint cam when the white fade out is active IF sBHV.iHintTrackedPoint != 0 IF VDIST(vPosition, GET_ENTITY_COORDS(PLAYER_PED_ID())) < BH_ITEM_COLLECT_RADIUS SET_TRACKED_POINT_INFO(sBHV.iHintTrackedPoint ,vHintEntityPosition, GET_MODEL_LENGTH(eHintModelA)) IF IS_TRACKED_POINT_VISIBLE(sBHV.iHintTrackedPoint) SET_GAMEPLAY_COORD_HINT(vHintEntityPosition) SET_BIT(sBHV.iState, BH_BIT_CHECKPOINT_ITEM_TRIGGERED) IF iHintType = BHT_HUNTER CPRINTLN(DEBUG_HUNTING, "Flagging hunter hint as seen. He will spawn as a hiker from now on.") SET_BIT(sBHV.iState, BH_BIT_HUNTER_SEEN) ENDIF Set_Beast_Call_Made(TRUE) //Make sure the hint is heard at least once ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC PROC Manage_Beast_Checkpoint_Hints(BeastHuntVars &sBHV) INT iCurrentCheckpoint, iNextCheckpoint Get_Beast_Hunt_Current_Path_And_Checkpoints(sBHV, iCurrentCheckpoint, iNextCheckpoint) IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) VECTOR vPlayerCoords = GET_ENTITY_COORDS(PLAYER_PED_ID()) FLOAT fDistCurrCP = VDIST(vPlayerCoords, g_vBHCheckpoints[iCurrentCheckpoint]) FLOAT fDistNextCP = VDIST(vPlayerCoords, g_vBHCheckpoints[iNextCheckpoint]) IF fDistCurrCP < BH_CHECKPOINT_HINT_RADIUS AND fDistCurrCP < fDistNextCP Manage_Checkpoint_Hint(sBHV, g_vBHCheckpoints[iCurrentCheckpoint], g_iBHCheckpointType[iCurrentCheckpoint], TRUE) ENDIF IF fDistNextCP < BH_CHECKPOINT_HINT_RADIUS Manage_Checkpoint_Hint(sBHV, g_vBHCheckpoints[iNextCheckpoint], g_iBHCheckpointType[iNextCheckpoint], TRUE) ENDIF IF fDistCurrCP > (BH_CHECKPOINT_HINT_RADIUS + 10) AND fDistNextCP > (BH_CHECKPOINT_HINT_RADIUS + 10) Release_Checkpoint_Hint_Assets(sBHV) ENDIF ENDIF ENDPROC //Checks if the beast call has been made and the sound isn't currently playing FUNC BOOL Can_Play_Beast_Sound(BeastHuntVars &sBHV) IF IS_BIT_SET(sBHV.iState, BH_BIT_BEAST_SOUND_PLAYING) OR NOT Has_Beast_Call_Been_Made(DEFAULT #IF IS_DEBUG_BUILD , sBHV.bDebugDisplayPaths #ENDIF ) RETURN FALSE ENDIF RETURN TRUE ENDFUNC //Plays the Beast sound when the conditions are met, manages timer for playing the sound PROC Manage_Beast_Sound(BeastHuntVars &sBHV, VECTOR vNextPos, BOOL bIsHint = FALSE) //Manage sound IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) //Check beast call default wait IF Has_Beast_Call_Just_Been_Made() sbhv.iNextSoundTime = IMAX(sbhv.iNextSoundTime, GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(2000,4000)) CDEBUG1LN(debug_hunting,"Detected beast call - reply in ",sbhv.iNextSoundTime-GET_GAME_TIMER()) ENDIF //Check if within max range but not within a CP radius FLOAT fDist = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), vNextPos) IF fDist < sBHV.fCurrentMaxRadius AND (fDist > BH_CHECKPOINT_RADIUS * BH_CHECKPOINT_RADIUS OR NOT bIsHint) //Stop audio cue when close to the hint AND fDist < BH_SOUND_MAX_RANGE_SQR //Check timing IF GET_GAME_TIMER() > sbhv.iNextSoundTime IF Can_Play_Beast_Sound(sBHV) //Update next sound time sbhv.iNextSoundTime = GET_GAME_TIMER() + BH_SOUND_MIN_DELAY + GET_RANDOM_INT_IN_RANGE(0, BH_SOUND_RANDOM_DELAY) CDEBUG1LN(debug_hunting,"Next beast audio in ",sbhv.iNextSoundTime - GET_GAME_TIMER()) TEXT_LABEL_63 temp = Build_Beast_String_63("C_SF", "DL", "AST", "X1/BE") //Prepare sound label IF REQUEST_SCRIPT_AUDIO_BANK(temp) Set_Beast_Call_Made(FALSE) //Disable bit that plays audio //Calculate potision sBHV.fSoundDist = FMAX(BH_SOUND_MIN_DIST_FROM_PLAYER, FMIN(BH_SOUND_DIST_FROM_PLAYER, VDIST(GET_ENTITY_COORDS(PLAYER_PED_ID()), vNextPos))) sBHV.vSoundPos = GET_VECTOR_OF_LENGTH(vNextPos - GET_ENTITY_COORDS(PLAYER_PED_ID()) , sBHV.fSoundDist) CPRINTLN(debug_hunting, "Playing sound at ",sBHV.vSoundPos,", next in ",sbhv.iNextSoundTime - GET_GAME_TIMER()," ms") //Play sound sBHV.iBeastSoundID = GET_SOUND_ID() TEXT_LABEL_23 temp2 = Build_Beast_String_23("st_C","Bea","ls","al") //"Beast_Calls" temp = Build_Beast_String_63("nts_S","FM_Eve","atch_Sounds","asqu") //"FM_Events_Sasquatch_Sounds" PLAY_SOUND_FROM_COORD(sBHV.iBeastSoundID, temp2, GET_ENTITY_COORDS(PLAYER_PED_ID()) + sBHV.vSoundPos, temp) SET_BIT(sBHV.iState, BH_BIT_BEAST_SOUND_PLAYING) //Reduce the range Reset_Max_Node_Range(sBHV, BH_CHECKPOINT_RADIUS,TRUE) ENDIF ENDIF ENDIF ENDIF //Check if the sound is still playing IF IS_BIT_SET(sBHV.iState, BH_BIT_BEAST_SOUND_PLAYING) AND sBHV.iBeastSoundID != -1 IF HAS_SOUND_FINISHED(sBHV.iBeastSoundID) RELEASE_SOUND_ID(sBHV.iBeastSoundID) CLEAR_BIT(sBHV.iState, BH_BIT_BEAST_SOUND_PLAYING) sBHV.iBeastSoundID = -1 ELSE //Update sound position UPDATE_SOUND_COORD(sBHV.iBeastSoundID, GET_ENTITY_COORDS(PLAYER_PED_ID()) + sBHV.vSoundPos) #IF IS_DEBUG_BUILD IF sBHV.bDebugDisplayPaths //Debug draws #IF IS_DEBUG_BUILD Beast_Display_Onscreen_Text(0.4,0.9, "Playing sound", 0.3) #ENDIF DRAW_DEBUG_SPHERE(GET_ENTITY_COORDS(PLAYER_PED_ID()) + sBHV.vSoundPos, 1) ENDIF #ENDIF ENDIF ENDIF ENDIF ENDPROC FUNC BOOL Is_Beast_Hunt_Allowed_To_Run(BeastHuntVars &sBeastHuntVars) VEHICLE_INDEX vehTemp //Temp: Would need to check some things in iState sBeastHuntVars.iState = sBeastHuntVars.iState RETURN IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_PEYOTES_COLLECTED) AND NOT IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) AND (IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_ANIMAL)) //No Director mode hunt AND GET_PLAYER_MODEL() = Get_Sasquatch_Model() AND NOT Is_Player_In_Bad_Hunt_Vehicle(vehTemp) ENDFUNC //==========================================MAIN UPDATE======================================== //============================================================================================= PROC Maintain_Beast_Hunt(BeastHuntVars &sBeastHuntVars) IF Has_Beast_Secret_Data_Setup_Finished() IF NOT IS_BITMASK_SET(g_iBeastSetupInt,BH_Bit_Hunt_Init) Finalise_Data_Init(sBeastHuntVars) CPRINTLN(debug_hunting,"Hunting data init now set-up, running the Hunt scripts") SET_BITMASK(g_iBeastSetupInt,BH_Bit_Hunt_Init) ENDIF ELSE EXIT //Don't do anything until data setup finishes ENDIF //Only update if allowed to run BOOL bCanRun = Is_Beast_Hunt_Allowed_To_Run(sBeastHuntVars) IF NOT bCanRun //Check if we need to delete the hints IF DOES_ENTITY_EXIST(sBeastHuntVars.vehHint) OR DOES_ENTITY_EXIST(sBeastHuntVars.pedHint) IF NOT IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_ANIMAL) OR NOT (GET_PLAYER_MODEL() = Get_Sasquatch_Model()) CPRINTLN(debug_hunting,"Player no longer on trip, cleaning hints") Release_Checkpoint_Hint_Assets(sBeastHuntVars, TRUE) ENDIF ENDIF IF sBeastHuntVars.bCouldRunLastFrame CPRINTLN(debug_hunting,"Beast hunt no longer able to run.") ENDIF ELIF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF NOT sBeastHuntVars.bCouldRunLastFrame CPRINTLN(debug_hunting,"Beast hunt now active.") IF Is_White_Faded_Out() OR NOT sBeastHuntVars.bWasSasLastFrame CPRINTLN(debug_hunting,"Starting white fade-out, Waiting until dead peds settle") Do_White_Fade(255, 0) sBeastHuntVars.iFadeOutTimer = 2000 //2 seconds ENDIF //Check if we need to run the audio scene TEXT_LABEL_31 tlMixer = Build_Beast_String_31("til_P_","Exec_U","xer_Scene","B_Mi") //"Exec_Util_P_B_Mixer_Scene" IF NOT IS_AUDIO_SCENE_ACTIVE(tlMixer) //Activate the audio mixer scene START_AUDIO_SCENE(tlMixer) CPRINTLN(debug_hunting,"Started the Beast Hunt audio scene") ENDIF ENDIF FLOAT fDist //Get currenth path vars INT iStart = Get_Beast_Hunt_Current_Checkpoint() INT iNextCheckpoint = Get_Beast_Hunt_Next_Checkpoint() INT iNode = Get_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState) //Manage white fade-out wait time IF sBeastHuntVars.iFadeOutTimer > 0 sBeastHuntVars.iFadeOutTimer -= FLOOR( GET_FRAME_TIME() * 1000) //Call the fade-in when done IF sBeastHuntVars.iFadeOutTimer <= 0 Do_White_Fade(0, DEFAULT_FADE_TIME) CPRINTLN(debug_hunting,"Finished the white fade delay, fading in") ENDIF ENDIF Update_White_Fade() //Update spawning hint items at current and next checkpoint. Manage_Beast_Checkpoint_Hints(sBeastHuntVars) //Don't let the player record any of this. REPLAY_PREVENT_RECORDING_AND_UI_THIS_FRAME() //Check if on the last leg of the journey IF Is_Node_Last_In_Path(sBeastHuntVars, iNode) fDist = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), g_vBHCheckpoints[iNextCheckpoint]) //Next one is the next CP IF fDist < BH_CHECKPOINT_RADIUS*BH_CHECKPOINT_RADIUS AND IS_BIT_SET(sBeastHuntVars.iState, BH_BIT_CHECKPOINT_ITEM_TRIGGERED) Pick_Next_Checkpoint(sBeastHuntVars) Reset_Node_In_Path(sBeastHuntVars) Reset_Beast_Sound_Time(sBeastHuntVars, 4000) CLEAR_BIT(sBeastHuntVars.iState, BH_BIT_CHECKPOINT_ITEM_TRIGGERED) //If this is the last checkpoint, activate the beast fight IF iNextCheckpoint = BH_CHECKPOINT_COUNT - 1 SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) SET_BIT(sBeastHuntVars.iState,BH_BIT_IGNORE_1ST_NODE) //Ignore the 1st node when coming back from the fight Reset_Node_In_Path(sBeastHuntVars) Reset_Max_Node_Range(sBeastHuntVars) Set_Beast_Call_Made(TRUE) //Have beast call play when failing the fight EXIT ELSE CLEAR_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_FIGHT_FAILED) ENDIF ELIF fDist > sBeastHuntVars.fCurrentMaxRadius Reset_Node_In_Path(sBeastHuntVars) Reset_Max_Node_Range(sBeastHuntVars) ENDIF Manage_Beast_Sound(sBeastHuntVars, g_vBHCheckpoints[iNextCheckpoint], TRUE) ELIF Is_Node_First_In_Path(sBeastHuntVars,iNode) fDist = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()),Get_Node_Location(sBeastHuntVars, iNode)) IF fDist < BH_CHECKPOINT_RADIUS * BH_CHECKPOINT_RADIUS AND IS_BIT_SET(sBeastHuntVars.iState, BH_BIT_CHECKPOINT_ITEM_TRIGGERED) //Move to the next node CPRINTLN(DEBUG_HUNTING, "-> Reached node ",iNode) Set_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState, Get_Next_Node_In_Path(sBeastHuntVars, iNode)) Reset_Beast_Sound_Time(sBeastHuntVars, 4000) Reset_Max_Node_Range(sBeastHuntVars) CLEAR_BIT(sBeastHuntVars.iState, BH_BIT_CHECKPOINT_ITEM_TRIGGERED) ELIF fDist > sBeastHuntVars.fCurrentMaxRadius Reset_Max_Node_Range(sBeastHuntVars) ENDIF Manage_Beast_Sound(sBeastHuntVars, g_vBHCheckpoints[iStart], TRUE) ELSE fDist = VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()),Get_Node_Location(sBeastHuntVars, iNode)) // DISPLAY_TEXT_WITH_FLOAT(0.4,0.5,"NUMBER",fDist,1) //Check if player is close enough to trigger the next node IF fDist < BH_PATH_NODE_RADIUS * BH_PATH_NODE_RADIUS //Move to the next node CPRINTLN(DEBUG_HUNTING, "-> Reached node ",iNode) Set_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState, Get_Next_Node_In_Path(sBeastHuntVars, iNode)) Reset_Beast_Sound_Time(sBeastHuntVars) Reset_Max_Node_Range(sBeastHuntVars) //Check if player outside of range, reset path progress ELIF fDist > sBeastHuntVars.fCurrentMaxRadius AND NOT Is_Node_First_In_Path(sBeastHuntVars,iNode) //Reset path progress Reset_Node_In_Path(sBeastHuntVars) Reset_Max_Node_Range(sBeastHuntVars) ENDIF Manage_Beast_Sound(sBeastHuntVars, Get_Node_Location(sBeastHuntVars, iNode)) ENDIF ENDIF //Set last frame variables sBeastHuntVars.bCouldRunLastFrame = bCanRun sBeastHuntVars.bWasSasLastFrame = (GET_PLAYER_MODEL() = Get_Sasquatch_Model()) ENDPROC #IF IS_DEBUG_BUILD INT dbCheckPoint = -1, dbNode = -1, dbPath = -1 INT oldCheckPoint = -1, oldNode = -1, oldPath = -1 INT iCurrentPath VECTOR oldPos PROC Create_Beast_Hunt_Widgets(BeastHuntVars &sBeastHuntVars, WIDGET_GROUP_ID widgetID = NULL) CPRINTLN(DEBUG_HUNTING, "Creating beast hunt widgets from ",GET_THIS_SCRIPT_NAME(),". Flags:", " SP_INIT_BEAST_PEYOTES_COLLECTED:",IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_PEYOTES_COLLECTED),",", " SP_INIT_BEAST_HUNT_COMPLETED:",IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED)) IF widgetID != NULL SET_CURRENT_WIDGET_GROUP(widgetID) ENDIF START_WIDGET_GROUP("Beast Hunt") ADD_WIDGET_BOOL("Terminate thread", sBeastHuntVars.bDebugTerminateThread) ADD_WIDGET_STRING("") ADD_WIDGET_BOOL("Peyotes complete?", sBeastHuntVars.bDebugPeyotesComplete) ADD_WIDGET_BOOL("Toggle peyotes complete", sBeastHuntVars.bDebugTogglePeyotesComplete) ADD_WIDGET_STRING("") ADD_WIDGET_BOOL("Hunt complete?", sBeastHuntVars.bDebugHuntComplete) ADD_WIDGET_BOOL("Toggle hunt complete", sBeastHuntVars.bDebugToggleHuntComplete) ADD_WIDGET_STRING("") ADD_WIDGET_BOOL("Hunter hint seen?", sBeastHuntVars.bDebugHunterSeen) ADD_WIDGET_BOOL("Toggle hunter hint seen", sBeastHuntVars.bDebugToggleHunterSeen) ADD_WIDGET_STRING("") ADD_WIDGET_BOOL("Warp and display", sBeastHuntVars.bWarpAndDisplay) ADD_WIDGET_BOOL("Direct path to end", sBeastHuntVars.bDebugDirectPath) ADD_WIDGET_BOOL("Display active path", sBeastHuntVars.bDebugDisplayActivePath) ADD_WIDGET_BOOL("Display checkpoints", sBeastHuntVars.bDebugDisplayCheckpoints) ADD_WIDGET_BOOL("Display all paths", sBeastHuntVars.bDebugDisplayPaths) ADD_WIDGET_BOOL("Only current path", sBeastHuntVars.bDebugDisplayCurrentPath) ADD_WIDGET_INT_SLIDER("Path", iCurrentPath, 0, sBeastHuntVars.iNumPaths-1, 1) ADD_WIDGET_BOOL("Set current path", sBeastHuntVars.bDebugSetCurrentPath) ADD_WIDGET_BOOL("Spread nodes on path", sBeastHuntVars.bSpreadPathNodes) ADD_WIDGET_BOOL("Print path setup info", sBeastHuntVars.bPrintPathInformation) STOP_WIDGET_GROUP() IF widgetID != NULL CLEAR_CURRENT_WIDGET_GROUP(widgetID) ENDIF ENDPROC PROC Update_Beast_Hunt_Widgets(BeastHuntVars &sBeastHuntVars, WIDGET_GROUP_ID widgetID = NULL) INT index, iCurrent, iNext TEXT_LABEL_63 tl63Temp //Alive check IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) ENDIF //Check if data initialised, then create widgets IF NOT Has_Beast_Secret_Data_Setup_Finished() EXIT ELSE IF NOT sBeastHuntVars.bDebugWidgetsInitialised Create_Beast_Hunt_Widgets(sBeastHuntVars, widgetID) sBeastHuntVars.bDebugWidgetsInitialised = TRUE ENDIF ENDIF IF sBeastHuntVars.bDebugTerminateThread OR IS_DEBUG_KEY_JUST_PRESSED(KEY_F, KEYBOARD_MODIFIER_NONE, "Terminate thread") CPRINTLN(DEBUG_HUNTING, "Beast hunt thread terminating from widget.") TERMINATE_THIS_THREAD() ENDIF //Read only bools. Set it every frame based on state saved in global bitset. sBeastHuntVars.bDebugPeyotesComplete = IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_PEYOTES_COLLECTED) sBeastHuntVars.bDebugHuntComplete = IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) sBeastHuntVars.bDebugHunterSeen = IS_BIT_SET(sBeastHuntVars.iState, BH_BIT_HUNTER_SEEN) //Allow toggling of the saved bit. IF sBeastHuntVars.bDebugTogglePeyotesComplete IF IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_PEYOTES_COLLECTED) CLEAR_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_PEYOTES_COLLECTED) ELSE SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_PEYOTES_COLLECTED) ENDIF sBeastHuntVars.bDebugTogglePeyotesComplete = FALSE ENDIF IF sBeastHuntVars.bDebugToggleHuntComplete IF IS_BIT_SET(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) CLEAR_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) ELSE SET_BIT(g_savedGlobals.sFlowCustom.spInitBitset, SP_INIT_BEAST_HUNT_COMPLETED) ENDIF sBeastHuntVars.bDebugToggleHuntComplete = FALSE ENDIF IF sBeastHuntVars.bDebugToggleHunterSeen IF IS_BIT_SET(sBeastHuntVars.iState, BH_BIT_HUNTER_SEEN) CLEAR_BIT(sBeastHuntVars.iState, BH_BIT_HUNTER_SEEN) ELSE SET_BIT(sBeastHuntVars.iState, BH_BIT_HUNTER_SEEN) ENDIF sBeastHuntVars.bDebugToggleHunterSeen = FALSE ENDIF //Only update if allowed to run IF NOT Is_Beast_Hunt_Allowed_To_Run(sBeastHuntVars) EXIT ENDIF IF sBeastHuntVars.bWarpAndDisplay //Get first checkpoint, warp player there iCurrent = Get_Beast_Hunt_Current_Checkpoint() iNext = Get_Beast_Hunt_Next_Checkpoint() FLOAT fGroundZ VECTOR vDir = NORMALISE_VECTOR(g_vBHCheckpoints[iCurrent] - g_vBHCheckpoints[iNext]) * BH_CHECKPOINT_RADIUS * 1.3 //Place the ped at that location vDir = g_vBHCheckpoints[iCurrent] + vDir + <<0,0,50>> SET_ENTITY_COORDS(PLAYER_PED_ID(), vDir ) Wait(0) GET_GROUND_Z_FOR_3D_COORD(vDir,fGroundZ) vDir.z = fGroundZ IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) SET_ENTITY_COORDS(PLAYER_PED_ID(),vDir) ENDIF SET_ENTITY_HEADING(PLAYER_PED_ID(),GET_HEADING_BETWEEN_VECTORS_2D(GET_ENTITY_COORDS(PLAYER_PED_ID()),g_vBHCheckpoints[iCurrent])) SET_GAMEPLAY_CAM_RELATIVE_HEADING() //Set time to midnight SET_CLOCK_TIME(0,0,0) //Enable the debug spheres sBeastHuntVars.bDebugDisplayCheckpoints = TRUE sBeastHuntVars.bWarpAndDisplay = FALSE ENDIF IF sBeastHuntVars.bDebugDisplayCheckpoints OR sBeastHuntVars.bDebugDisplayPaths IF NOT sBeastHuntVars.bDebugDrawingEnabled SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE) sBeastHuntVars.bDebugDrawingEnabled = TRUE ENDIF ELSE IF sBeastHuntVars.bDebugDrawingEnabled SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(FALSE) sBeastHuntVars.bDebugDrawingEnabled = FALSE ENDIF ENDIF //Draw checkpoint spheres IF sBeastHuntVars.bDebugDisplayCheckpoints iCurrent = Get_Beast_Hunt_Current_Checkpoint() iNext = Get_Beast_Hunt_Next_Checkpoint() REPEAT BH_CHECKPOINT_COUNT index tl63Temp = "Checkpoint(" tl63Temp += index tl63Temp += ")" DRAW_DEBUG_TEXT(tl63Temp, g_vBHCheckpoints[index], 255, 255, 0) IF index = iCurrent tl63Temp = "Current(" DRAW_DEBUG_SPHERE(g_vBHCheckpoints[index], BH_CHECKPOINT_RADIUS, 0, 0, 255, 60) ELIF index = iNext tl63Temp = "Next(" DRAW_DEBUG_SPHERE(g_vBHCheckpoints[index], BH_CHECKPOINT_RADIUS, 0, 255, 0, 60) ELSE tl63Temp = "Checkpoint(" DRAW_DEBUG_SPHERE(g_vBHCheckpoints[index], BH_CHECKPOINT_RADIUS, 255, 0, 0, 50) ENDIF tl63Temp += index tl63Temp += ")" DRAW_DEBUG_TEXT(tl63Temp, g_vBHCheckpoints[index], 255, 255, 0) ENDREPEAT ENDIF //Draw the paths IF sBeastHuntVars.bDebugDisplayPaths INT path, curCP, nxtCP, pathStart, pathEnd, iNode curCP = Get_Beast_Hunt_Current_Checkpoint() nxtCP = Get_Beast_Hunt_Next_Checkpoint() iNode = Get_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState) path = g_iBHPathIndexes[curCP][nxtCP] //Draw line to the current node and distance DRAW_DEBUG_LINE(GET_ENTITY_COORDS(PLAYER_PED_ID())+<<0,0,1.2>>,Get_Node_Location(sBeastHuntVars, iNode),255,255,0) tl63Temp = "CP:" tl63Temp += curCP tl63Temp += " Node:" tl63Temp += iNode tl63Temp += " Dist:" tl63Temp += ROUND(VDIST(GET_ENTITY_COORDS(PLAYER_PED_ID()),Get_Node_Location(sBeastHuntVars, iNode)) * 10) tl63Temp += "/" tl63Temp += Round(SQRT(sBeastHuntVars.fCurrentMaxRadius) * 10) DRAW_DEBUG_TEXT(tl63Temp, GET_ENTITY_COORDS(PLAYER_PED_ID())+<<0,0,1.2>>,200,200,200) REPEAT sBeastHuntVars.iNumPaths path IF (NOT sBeastHuntVars.bDebugDisplayCurrentPath) OR (g_iBHPathIndexes[curCP][nxtCP] = path OR g_iBHPathIndexes[nxtCP][curCP] = path) Get_Beast_Hunt_Path_Endpoints(sBeastHuntVars, path, pathStart, pathEnd) REPEAT g_sBHPath[path].iLength index tl63Temp = "Path(" tl63Temp += path tl63Temp += ") Node(" tl63Temp += index tl63Temp += ")" DRAW_DEBUG_TEXT(tl63Temp, g_sBHPath[path].vNode[index], 255, 255, 0) DRAW_DEBUG_SPHERE(g_sBHPath[path].vNode[index], BH_PATH_NODE_RADIUS, 255, 255, 0, 60) IF index = 0 DRAW_DEBUG_LINE(g_vBHCheckpoints[pathStart]+ <<0,0,BH_PATH_NODE_RADIUS>>, g_sBHPath[path].vNode[index]+ <<0,0,BH_PATH_NODE_RADIUS>>, 0, 255, 128, 255) ENDIF IF index = g_sBHPath[path].iLength-1 DRAW_DEBUG_LINE(g_sBHPath[path].vNode[index]+ <<0,0,BH_PATH_NODE_RADIUS>>, g_vBHCheckpoints[pathEnd]+ <<0,0,BH_PATH_NODE_RADIUS>>, 255, 0, 255, 255) ELSE DRAW_DEBUG_LINE(g_sBHPath[path].vNode[index]+ <<0,0,BH_PATH_NODE_RADIUS>>, g_sBHPath[path].vNode[index+1]+ <<0,0,BH_PATH_NODE_RADIUS>>, 0, 0, 255, 255) ENDIF ENDREPEAT ENDIF ENDREPEAT ENDIF IF sBeastHuntVars.bDebugDisplayActivePath iCurrent = Get_Beast_Hunt_Current_Checkpoint() iNext = Get_Beast_Hunt_Next_Checkpoint() INT iPath = g_iBHPathIndexes[iCurrent][iNext] //Draw current checkpoint. tl63Temp = "Current(" tl63Temp += iCurrent tl63Temp += ")" DRAW_DEBUG_TEXT(tl63Temp, g_vBHCheckpoints[iCurrent], 255, 255, 0) DRAW_DEBUG_SPHERE(g_vBHCheckpoints[iCurrent], BH_CHECKPOINT_RADIUS, 0, 0, 255, 60) //Draw next checkpoint. tl63Temp = "Next(" tl63Temp += iNext tl63Temp += ")" DRAW_DEBUG_TEXT(tl63Temp, g_vBHCheckpoints[iNext], 255, 255, 0) DRAW_DEBUG_SPHERE(g_vBHCheckpoints[iNext], BH_CHECKPOINT_RADIUS, 0, 255, 0, 60) //Draw path. REPEAT g_sBHPath[iPath].iLength index tl63Temp = "Path(" tl63Temp += iPath tl63Temp += ") Node(" tl63Temp += index tl63Temp += ")" DRAW_DEBUG_TEXT(tl63Temp, g_sBHPath[iPath].vNode[index], 255, 255, 0) DRAW_DEBUG_SPHERE(g_sBHPath[iPath].vNode[index], BH_PATH_NODE_RADIUS, 255, 255, 0, 60) IF index < (g_sBHPath[iPath].iLength-2) DRAW_DEBUG_LINE(g_sBHPath[iPath].vNode[index], g_sBHPath[iPath].vNode[index+1], 0, 0, 255, 255) ENDIF ENDREPEAT ENDIF //Manage mouse-clicking checkpoints and nodes IF sBeastHuntVars.bDebugDisplayCheckpoints OR sBeastHuntVars.bDebugDisplayPaths VECTOR vPos IF IS_MOUSE_BUTTON_JUST_PRESSED(MB_LEFT_BTN) SET_FOCUS_POS_AND_VEL(GET_GAMEPLAY_CAM_COORD(), <<0,0,0>>) Wait(0) //Wait to generate collision at location vPos = GET_SCRIPT_MOUSE_POINTER_IN_WORLD_COORDS() //Search through all checkpoints REPEAT BH_CHECKPOINT_COUNT index IF VDIST2(vPos, g_vBHCheckpoints[index]) < BH_CHECKPOINT_RADIUS*BH_CHECKPOINT_RADIUS dbCheckPoint = index CPRINTLN(debug_dan,"found cp ",dbCheckPoint) //Undo vars oldPos = g_vBHCheckpoints[index] oldCheckpoint = index BREAKLOOP ENDIF ENDREPEAT IF dbCheckPoint = -1 INT path //Search through all paths REPEAT sBeastHuntVars.iNumPaths path BOOL bFound = FALSE REPEAT g_sBHPath[path].iLength index IF VDIST2(vPos, g_sBHPath[path].vNode[index]) < BH_PATH_NODE_RADIUS * BH_PATH_NODE_RADIUS dbPath = path dbNode = index bFound = TRUE CPRINTLN(debug_dan,"found node ",dbNode) //Undo vars oldPos = g_sBHPath[path].vNode[index] oldPath = path oldNode = index BREAKLOOP ENDIF ENDREPEAT IF bFound BREAKLOOP ENDIF ENDREPEAT ENDIF ELIF IS_MOUSE_BUTTON_PRESSED(MB_LEFT_BTN) vPos = GET_SCRIPT_MOUSE_POINTER_IN_WORLD_COORDS() VECTOR vDiff //Set streaming in that area SET_FOCUS_POS_AND_VEL(vPos, <<0,0,0>>) IF (dbCheckPoint > -1 OR dbNode > -1 OR dbPath > -1) //Move checkpoint IF dbCheckPoint > -1 vDiff = vPos - g_vBHCheckpoints[dbCheckPoint] g_vBHCheckpoints[dbCheckPoint] = vPos CPRINTLN(debug_dan,"Move CP to ",vPos) //Move node ELSE vDiff = vPos - g_sBHPath[dbPath].vNode[dbNode] g_sBHPath[dbPath].vNode[dbNode] = vPos ENDIF //Apply movement to all nodes IF IS_DEBUG_KEY_PRESSED(KEY_CAPITAL, KEYBOARD_MODIFIER_NONE, "Move all nodes") vDiff.z = 0 REPEAT BH_CHECKPOINT_COUNT index IF index != dbCheckpoint g_vBHCheckpoints[index] += vDiff ENDIF ENDREPEAT INT path REPEAT sBeastHuntVars.iNumPaths path REPEAT g_sBHPath[path].iLength index IF path != dbPath OR index != dbNode g_sBHPath[path].vNode[index] += vDiff ENDIF ENDREPEAT ENDREPEAT ENDIF ENDIF ELIF IS_MOUSE_BUTTON_JUST_RELEASED(MB_LEFT_BTN) CLEAR_FOCUS() dbNode = -1 dbPath = -1 dbCheckPoint = -1 ENDIF //Check undo press IF IS_DEBUG_KEY_JUST_PRESSED(KEY_Z, KEYBOARD_MODIFIER_NONE, "Undo last move") IF oldCheckpoint != -1 g_vBHCheckpoints[oldCheckpoint] = oldPos oldCheckpoint = -1 ELIF oldNode != -1 AND oldPath != -1 g_sBHPath[oldPath].vNode[oldNode] = oldPos oldNode = -1 oldPath = -1 ENDIF ENDIF ENDIF //Print path info IF sBeastHuntVars.bPrintPathInformation sBeastHuntVars.bPrintPathInformation = FALSE CPRINTLN(debug_hunting,"//<---------------PATH SETUP INFO HERE----------------->") CPRINTLN(debug_hunting,"") REPEAT BH_CHECKPOINT_COUNT index CPRINTLN(debug_hunting, "g_vBHCheckpoints[",index,"] = ",g_vBHCheckpoints[index]) ENDREPEAT INT path, iCP1, iCP2, index2 TEXT_LABEL_63 tlVec[4] CPRINTLN(debug_hunting,"") //Search through all paths REPEAT sBeastHuntVars.iNumPaths path Get_Beast_Hunt_Path_Endpoints(sBeastHuntVars, path, iCP1, iCP2) REPEAT 4 index tlVec[index] = "" ENDREPEAT REPEAT g_sBHPath[path].iLength index index2 = index / 2 IF index > 0 tlVec[index2] += ", " ENDIF tlVec[index2] += FLOAT_TO_STRING(g_sBHPath[path].vNode[index].x, 2) tlVec[index2] += ", " tlVec[index2] += FLOAT_TO_STRING(g_sBHPath[path].vNode[index].y, 2) tlVec[index2] += ", " tlVec[index2] += FLOAT_TO_STRING(g_sBHPath[path].vNode[index].z, 2) ENDREPEAT CPRINTLN(debug_hunting,"//Path ",path," from ",iCP1, " to ", iCP2) CPRINTLN(debug_hunting,"Add_Beast_Hunt_Path(sBeastHuntVars, ",iCP1,", ",iCP2,", TRUE, ",tlVec[0],tlVec[1],")") CPRINTLN(debug_hunting, "") ENDREPEAT CPRINTLN(debug_hunting,"") CPRINTLN(debug_hunting,"//<----------------END PATH SETUP INFO---------------->") ENDIF //Set current path IF sBeastHuntVars.bDebugSetCurrentPath sBeastHuntVars.bDebugSetCurrentPath = FALSE INT iStart, iEnd Get_Beast_Hunt_Path_Endpoints(sBeastHuntVars, iCurrentPath, iStart, iEnd) Set_Beast_Hunt_Current_Checkpoint(iStart) Set_Beast_Hunt_Next_Checkpoint(iEnd) Reset_Node_In_Path(sBeastHuntVars) ENDIF //Spread nodes on a path IF sBeastHuntVars.bSpreadPathNodes INT startCP, endCP FLOAT fGround Get_Beast_Hunt_Path_Endpoints(sBeastHuntVars, iCurrentPath, startCP, endCP) VECTOR vStep = g_vBHCheckpoints[endCP] - g_vBHCheckpoints[startCP] CPRINTLN(debug_hunting, startCP," - ",endCP," Step is ", vStep) vStep /= TO_FLOAT(g_sBHPath[iCurrentPath].iLength + 1) CPRINTLN(debug_hunting, "Step is ", vStep) REPEAT g_sBHPath[iCurrentPath].iLength index g_sBHPath[iCurrentPath].vNode[index] = g_vBHCheckpoints[startCP] + vStep * TO_FLOAT(index + 1) SET_FOCUS_POS_AND_VEL(g_sBHPath[iCurrentPath].vNode[index], <<0,0,0>>) Wait(0) TEST_VERTICAL_PROBE_AGAINST_ALL_WATER(g_sBHPath[iCurrentPath].vNode[index] + <<0,0,500>>, SCRIPT_INCLUDE_MOVER, fGround) g_sBHPath[iCurrentPath].vNode[index].z = fGround ENDREPEAT CLEAR_FOCUS() sBeastHuntVars.bSpreadPathNodes = FALSE ENDIF //J-skip to next node IF IS_DEBUG_KEY_JUST_PRESSED(KEY_J, KEYBOARD_MODIFIER_SHIFT,"Skip to next node") VECTOR vtemp = Get_Node_Location(sBeastHuntVars, Get_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState)) CPRINTLN(debug_hunting, "Starting j-skip to next node at ",vtemp) IF IS_GAMEPLAY_HINT_ACTIVE() STOP_GAMEPLAY_HINT() ENDIF // START_PLAYER_TELEPORT(PLAYER_ID(), Get_Node_Location(sBeastHuntVars, Get_Beast_Hunt_Current_Path_Node(sBeastHuntVars.iState)) + <<0,0,3>>, 0) // INT iTimer = GET_GAME_TIMER() + 1500 // WHILE UPDATE_PLAYER_TELEPORT(PLAYER_ID()) AND GET_GAME_TIMER() < iTimer // WAIT(0) // ENDWHILE // STOP_PLAYER_TELEPORT() SET_ENTITY_COORDS(PLAYER_PED_ID(),vTemp + <<0,0,3>>,FALSE) ENDIF //Check the node locations in globals vs current IF IS_DEBUG_KEY_JUST_PRESSED(KEY_C, KEYBOARD_MODIFIER_CTRL_SHIFT, "Check node consistency") INT i, j, iBad = 0 FOR i = 0 to 19 FOR j = 0 to 3 IF NOT ARE_VECTORS_EQUAL(g_sBHPath[i].vNode[j], g_vBHNodes[i][j]) CPRINTLN(Debug_Hunting,"node ",i," ",j," ",g_vBHNodes[i][j]," != ",g_sBHPath[i].vNode[j]) iBad++ ENDIF ENDFOR ENDFOR CPRINTLN(debug_hunting,"Bad nodes found: ",iBad) ENDIF ENDPROC #ENDIF //DEBUG #ENDIF //FEATURE_SP_DLC_BEAST_SECRET