USING "commands_itemsets.sch" USING "script_blips.sch" USING "RC_Helper_Functions.sch" USING "Shared_Hud_Displays.sch" USING "RC_Area_public.sch" USING "rc_threat_public.sch" USING "commands_pad.sch" USING "LauncherInclude.sch" USING "rgeneral_include.sch" USING "minigame_midsized_message.sch" USING "script_usecontext.sch" USING "website_public.sch" USING "mp_globals_block_SC_LB.sch" // ====================================== // ENUMS // ====================================== ENUM ELK_STATE ES_NULL = 0, // STATES WE NEED. ES_CHECK_CAN_SPAWN, ES_SPAWN_IN, ES_START_GRAZE, // Here we start the animation, and flag a time. ES_GRAZE, ES_PAUSE_THEN_PICK_NEW_DESTINATION, ES_CHOOSE_NEXT_DESTINATION, ES_TRAVEL_TO_NEXT_DESTINATION, ES_PAUSE_THEN_GRAZE, ES_TRAVEL_THEN_ENTER_GRAZE_AND_WAIT_TO_DIE, ES_ENTER_GRAZE_AND_WAIT_TO_DIE, ES_GRAZE_AND_WAIT_TO_DIE, ES_EXIT_GRAZE_AND_WAIT_TO_DIE, ES_IDLE_AND_WAIT_TO_DIE, ES_RUN_OFF, ES_RUNNING_OFF, ES_CLEAN_UP ENDENUM ENUM SPOOKED_REASON SR_NULL = 0, SR_SAW_PLAYER, SR_HEARD_PLAYER, SR_SMELLED_PLAYER, SR_SPOOKED_BY_ELK, SR_NEAR_MISS ENDENUM ENUM HIT_LOCATION HL_NULL = 0, HL_HEAD, HL_NECK, HL_HEART, HL_FORELEG, HL_BODY, HL_ASS, HL_HINDLEG, NUM_HIT_LOCATIONS ENDENUM // ====================================== // Constants // ====================================== CONST_INT MAX_HUNT_MODES 4 // Ambient hunt modes CONST_INT MAX_ELKS 8 // HOW MANY ARE THERE IN THE POOL Needs to be defined before common hunting CONST_INT MAX_GRAZE_AREAS 58 // WAYPOINTS FOR THE ELK TO WANDER ABOUT WITH CONST_INT MAX_POLY_TEST_VERTS 8 CONST_INT MIN_ELK_GRAZE_TIME 15000 CONST_INT MAX_ELK_GRAZE_TIME 25000 CONST_INT MIN_ELK_WAIT_TIME 1500 CONST_INT MAX_ELK_WAIT_TIME 3000 CONST_FLOAT CALL_RANGE 200.0 // EFFECTIVE RANGE OF CALLING (TRIANGLE/Y) WHICH INCREASES THE ELKS BLIP ALPHA CONST_INT MIN_BLIP_ALPHA 0 // 50 // DEFAULT = 0 // THE MINIMUM ALPHA OF THE BLIP. SET THIS HIGHER FOR DEBUG PURPOSES CONST_FLOAT MIN_SAFE_SPAWN_DIST 30.0 CONST_FLOAT MAX_SAFE_SPAWN_DIST 125.0 //These variables are used to detect if the player has been detected by //the elk. Used in CHECK_ELK_SPOOKED(int i) Will eventually need changing to use the //AI perception system. CONST_FLOAT ELK_SCENT_RANGE 45.0 CONST_FLOAT ELK_SCENT_WIDTH 10.0 CONST_FLOAT ELK_CLEANUP_DISTANCE 250.0 CONST_FLOAT SIGHT_RANGE_STANDING 30.0 CONST_FLOAT SIGHT_RANGE_DUCKED 20.0 CONST_FLOAT HEAR_RANGE 10.0 CONST_FLOAT ELK_FOV 90.0 // Used in Hunting2 CONST_INT iSAW_PLAYER_FLAG 0 CONST_INT iHEARD_PLAYER_FLAG 1 CONST_INT iSMELT_PLAYER_FLAG 2 CONST_INT iNEAR_MISS_FLAG 3 CONST_INT iSAW_SPOOKED_ELK_FLAG 4 CONST_INT FIVE_MINUTES 60000 * 5 CONST_INT THREE_MINUTES 60000 * 3 CONST_FLOAT CLOSE_KILL_RANGE 25.0 CONST_INT SCORE_HEART_SHOT 10 CONST_INT SCORE_HEAD_SHOT 5 CONST_INT SCORE_NECK_SHOT 7 CONST_INT SCORE_TORSO_SHOT 4 CONST_INT SCORE_ASS_SHOT 2 CONST_INT SCORE_LEG_SHOT 1 CONST_INT SCORE_SPOOKED_SHOT 1 CONST_INT SCORE_DOE 0 CONST_INT SCORE_UNKNOWN 2 CONST_INT SCORE_ROAD_KILL 1 CONST_INT SCORE_MOUNTAIN_LION_KILL 5 CONST_INT SCORE_BOAR_KILL 3 CONST_INT SCORE_COYOTE_KILL 2 CONST_INT SCORE_BIRD_KILL 5 CONST_INT SCORE_HUMAN_KILL 5 CONST_FLOAT k_ELK_SPOOK_RANGE 8.25 CONST_FLOAT k_ELK_SPOOK_RANGE_MULT 4.0 ENUM KILL_TYPE KILL_UNKNOWN = -1, KILL_HEART_SHOT, KILL_HEAD_SHOT, KILL_NECK_SHOT, KILL_TORSO_SHOT, KILL_ASS_SHOT, KILL_LEG_SHOT, KILL_SPOOKED_SHOT, KILL_DOE_KILL, KILL_MOUNTAIN_LION_KILL, KILL_BOAR_KILL, KILL_COYOTE_KILL, KILL_BIRD_KILL, KILL_HUMAN_KILL, KILL_ROAD_KILL, KILL_LIVE_ANIMAL, KILL_NO_KILL ENDENUM CONST_INT MONEY_HEART_SHOT 100 CONST_INT MONEY_HEAD_SHOT 50 CONST_INT MONEY_NECK_SHOT 75 CONST_INT MONEY_TORSO_SHOT 50 CONST_INT MONEY_ASS_SHOT 50 CONST_INT MONEY_LEG_SHOT 50 CONST_INT MONEY_SPOOKED_SHOT 50 CONST_INT MONEY_DOE 25 CONST_INT MONEY_ROAD_KILL 5 CONST_INT MONEY_MOUNTAIN_LION_KILL 25 CONST_INT MONEY_BOAR_KILL 50 CONST_INT MONEY_COYOTE_KILL 10 CONST_INT MONEY_BIRD_KILL 10 CONST_INT MONEY_HUMAN_KILL 0 CONST_FLOAT MONEY_MULT_SNIPER 1.0 CONST_FLOAT MONEY_MULT_MELEE 0.5 CONST_FLOAT MONEY_MULT_PISTOL 1.0 CONST_FLOAT MONEY_MULT_SMG 0.75 CONST_FLOAT MONEY_MULT_RIFLE 1.0 CONST_FLOAT MONEY_MULT_MG 0.25 CONST_FLOAT MONEY_MULT_SHOTGUN 0.25 CONST_FLOAT MONEY_MULT_HEAVY 0.1 CONST_FLOAT MONEY_MULT_THROWN 0.1 CONST_INT MAX_ELK_PER_HERD 3 CONST_INT HERD_MEMBER_INDEX_START 3 CONST_INT HERD_MEMBER_LEFT 3 CONST_INT HERD_MEMBER_RIGHT 4 CONST_INT HERD_MEMBER_FRONT 5 CONST_INT HERD_MEMBER_REAR 6 CONST_INT PERCENTAGE_HERD_CHANCE 100 // Percentage chance this elk will form a herd. CONST_INT PERCENTAGE_HERD_MEMBER_CHANCE 50 // Percentage chance a particular herd member will spawn. //TWEAK_FLOAT WIND_METER_X 0.025 //TWEAK_FLOAT WIND_METER_Y -0.064 CONST_INT BLEAT_TRIGGER_MIN_DELAY 30000 CONST_INT BLEAT_TRIGGER_MAX_DELAY 60000 CONST_INT BLEAT_RESPONSE_DELAY 4000 CONST_INT MAX_DOE_IN_PLAY 3 CONST_INT MIN_DIALOGUE_DELAY_TIME 30000 CONST_INT MAX_DIALOGUE_DELAY_TIME 120000 CONST_INT CHALLENGE_DISPLAY_DELAY 1750 TWEAK_FLOAT CHALLENGE_BACK_X 0.05 TWEAK_FLOAT CHALLENGE_BACK_Y 0.30 TWEAK_FLOAT CHALLENGE_BACK_WIDTH 0.25 TWEAK_FLOAT CHALLENGE_BACK_HEIGHT 0.30 TWEAK_FLOAT CHALLENGE_TEXT_OFFSET_X 0.015 TWEAK_FLOAT CHALLENGE_TEXT_OFFSET_Y 0.015 TWEAK_FLOAT CHALLENGE_TEXT_TABBED_OFFSET_X 0.01 TWEAK_FLOAT CHALLENGE_TEXT_GOAL_BUFFER_Y 0.02 TWEAK_FLOAT CHALLENGE_TEXT_OBJ_BUFFER_Y 0.03 REL_GROUP_HASH mElkGroup // ===================== // STRUCTS // ===================== STRUCT MY_ELK PED_INDEX mPed BLIP_INDEX mElkBlip INT iNextTestTime = 0 INT iBlipAlpha = 0 INT iCallTime = 0 INT iStartFadeTime = 0 INT iCallResponseTime = 0 BOOL bMustReplyToCall = FALSE BOOL bRandomlyCalls = TRUE BOOL bIsSpooked = FALSE BOOL bCalling = FALSE BOOL bCanFadeBlip = TRUE BOOL bHardBlipped = FALSE BOOL bBlockSpookedBlip = FALSE SPOOKED_REASON eSpookedReason MODEL_NAMES mModel = A_C_DEER ELK_STATE elkState //Elks spawn pos and scent offset position VECTOR vPos VECTOR vScentOffsetPos //Waiting time at each node INT iWaitTime INT iGrazeTime // ROUTE NODES INT iCurNode INT iPrevNode INT iDestNode BOOL bIsHerdLeader = FALSE BOOL bIsHerdMember = FALSE INT iLeaderIdx = -1 INt iNumFollowers = 0 FLOAT fRandHead FLOAT fDist INT iSpawnDelayTime BOOL bDelayBeforeRespawn = FALSE ENDSTRUCT MY_ELK mElk[MAX_ELKS] INT m_iTargetElk // Used when failing the mission, stores the index of the elk we were hunting at the time. STRUCT ELK_SPAWN_LOCATION VECTOR vCoord // A location an elk can spawn BOOL bIsBooked = FALSE // Is this graze point booked to spawn an elk or is an elk going to the graze point INT iNextSpawnTime = 0 // Next allowable spawn time. ENDSTRUCT CONST_INT ELK_SPAWN_RESPAWN_DELAY 40000 // A spawn pos needs to wait 30 seconds before something can spawn there again. ELK_SPAWN_LOCATION elkSpawn[MAX_GRAZE_AREAS] ENUM HUNTING_CHALLENGE HC_INVALID = -1, HC_MASTER_HUNTER, HC_PHOTOJOURNALIST, HC_WEAPONS_MASTER ENDENUM ENUM HUNTING_CHALLENGE_RANK HCR_LOCKED = -1, HCR_RANK_1, HCR_RANK_2, HCR_RANK_3, HCR_RANK_4, HCR_RANK_5, HCR_COMPLETE ENDENUM ENUM HUNTING_CHALLENGE_STATUS HCS_RANK_INIT, HCS_RANK_UPDATE, HCS_RANK_COMPLETE_TOAST, HCS_RANK_NEXT ENDENUM STRUCT HUNTING_CHALLENGE_DATA HUNTING_CHALLENGE_RANK hcRank HUNTING_CHALLENGE_STATUS hcStatus INT iPrevProgress ENDSTRUCT ENUM CORPSES_STATE CS_UPDATE = 0, CS_TAKING_PHOTO, CS_POST_PHOTO, CS_CONTACT_LIST, CS_WAIT_MSG, CS_WAIT_MSG_WRONG, CS_WAIT_MSG_WRONG_POST, CS_DO_SCORE_AND_CHALLENGES ENDENUM STRUCT HT_PLAYER_DATA STRING sFailReason INT iKillCount = 0 INT iHighScore INT iScoreForBronze INT iScoreForSilver INT iScoreForGold INT iScore = 0 INT iMoney = 0 BOOL bGivenMoney = FALSE INT iHitsOnLocation[NUM_HIT_LOCATIONS] BOOL bRunPlayerDeath = FALSE //BOOL bCanDisplayChallengeToast = TRUE HUNTING_CHALLENGE_DATA challengeData[COUNT_OF(HUNTING_CHALLENGE)] structTimer unlockTimer // Things needed for challenges INT iKillsSinceSpooked INT iKillStreakHeartshot INT iKillsSinceElkCall INT iKillsTimed INT iKillsTimeRemaining INT iKillTimes[10] // Using 10 for right now INT iChallengeDisplayTime = -1 TIMEOFDAY todHuntStarted = INVALID_TIMEOFDAY // Tracking. INT iPhotosSent = 0 INT iCougarKills = 0 INT iBoarKills = 0 INT iCoyoteKills = 0 INT iLastCommentTime = 0 structTimer tTimeSpentHunting // Leaderboard time is tracked in MS. To get that, multiply this timer by 1000, if bGoldAchieved is set to TRUE. // For some reason, when passing in time to the leaderboard, you have to make it negative. This is so lower times show up on the top of the // leaderboard. Ask Asa if this is confusing. structTimer tTimeToGold BOOL bGoldAchieved = FALSE // Timing structs for speed challenge // SIMPLE_USE_CONTEXT controlsUI BOOL bSetupHuntingControls = FALSE SCRIPT_SHARD_BIG_MESSAGE splashUI BOOL bChallengeScreenSetup END_SCREEN_DATASET challengeScreen ITEMSET_INDEX setCorpses ITEMSET_INDEX setPhoto CORPSES_STATE eCorpseState structTimer textTimer BOOL bNearCorpse BOOL bSentPhotoHelp BOOL bSentPhotoNearHelp BOOL bSentPhotoSendHelp BOOL bSentUnlockText BOOL bSentChalUnlockHelp BOOL bSentDownwindHelp BOOL bSentLowPointPerKillText BOOL bSentNearBronzeText BOOL bSentNearSilverText BOOL bSentNearGoldText BOOL bNeedLoserSound = FALSE VEHICLE_INDEX vehQuad WEAPON_GROUP lastWeaponUsed FLOAT fLastCamZoom BOOL bSetupDeath INT iLastPhotoTime SC_LEADERBOARD_CONTROL_STRUCT huntLB_control SCALEFORM_INDEX huntLB_UI BOOL bOnlineForPrediction ENDSTRUCT CONST_INT HUNTING_COMMENT_DELAY 8000 CONST_INT HUNTING_PHOTO_CATCH_DELAY 3000 HT_PLAYER_DATA Player_Hunt_Data // ================================= // Variables // ================================= // WIND FLOAT fWindDirection VECTOR vWindDirection BOOL bIsAmbient = FALSE CONST_FLOAT DISTANCE_HARD_BLIP_THRESHOLD 40.0 //Dealing with the players rifle FLOAT fDistanceThreshold FLOAT fZoomLevel = 1.0 BOOL bHadSniperRifle = FALSE BOOL bHadSuppressor = FALSE INT iSniperAmmoBefore = 0 BOOL bAllowCall = FALSE //Used to delay the player being able to use the elk whistle, Defined in here but only changed via a main hunting script BOOL bPlayerCalling = FALSE VECTOR vHuntingPlayerCoords BOOL bPlayerKillElkIncorrectly = FALSE BOOL bIsPlayerOutsideHuntArea = FALSE //Defined in here but only changed via a main hunting script BOOL bSniperEquiped = FALSE //Defined in here but only changed via a main hunting script BLIP_INDEX mCentreBlip // ELK INT iDoeInPlay = 0 INT iElksInPlay = 0 VECTOR SCENT_RANGE = << 0.0, 40.0, 0.0 >> INT iRandGraze BOOL bRandomBleat = FALSE INT iBleatInitiateTime = 0 INT iBleatResponseTime = 0 INT iInitiatorIndex = -1 INT iElkTesting = -1 SHAPETEST_INDEX elkShapeTest // SOUNDS INT iSoundId = -1 INT iSoundDelay = 0 FLOAT fConcentration = 0.0 FLOAT fHeartBeat = 0.0 // KILLS BOOL bUncleanKill = FALSE INT iUncleanKills = 0 INT iLocalKillCount = 0 INT iMissMessageDelay = 0 CONST_INT MISS_MESSAGE_DELAY_TIME 500 BOOL bGotNearMissTime = FALSE BOOL bSuppressNearMissMessage = FALSE BOOL bShouldClearSuppressNearMissMsg = FALSE CONST_INT SPAWN_DELAY_TIME 1000 // AREA TEST_POLY mAreaCheck1 TEST_POLY mAreaCheck2 // TRAFFIC FLOAT fCarDensity = 1.0 INT iDialDownTime = 0 BOOL bGotDialDownTime = FALSE // HUD BOOL bPauseTimer = FALSE // TIMER INT iEndTime = 0 INT iPauseDuration = 0 INT iPauseStartTime = 0 INT iPauseEndTime = 0 BOOL bGotPauseTime = FALSE // ====================================== // COMMON FUNCTIONS // ====================================== /// PURPOSE: /// Checks to see if an animal ped was a doe. /// RETURNS: FUNC BOOL IS_ELK_A_DOE(ENTITY_INDEX entElk) IF DOES_ENTITY_EXIST(entElk) IF DECOR_EXIST_ON(entElk, "doe_elk") RETURN DECOR_GET_BOOL(entElk, "doe_elk") ENDIF ENDIF RETURN FALSE ENDFUNC #IF IS_DEBUG_BUILD FUNC STRING GET_DISPLAY_NAME_FOR_KILL_TYPE(ENTITY_INDEX entCorpse, KILL_TYPE eKillType) SWITCH eKillType CASE KILL_HEART_SHOT RETURN "Elk (Heart)" CASE KILL_HEAD_SHOT RETURN "Elk (Head)" CASE KILL_NECK_SHOT RETURN "Elk (Neck)" CASE KILL_TORSO_SHOT RETURN "Elk (Body)" CASE KILL_ASS_SHOT RETURN "Elk (Rear)" CASE KILL_LEG_SHOT RETURN "Elk (Leg)" CASE KILL_SPOOKED_SHOT RETURN "Elk (Spooked)" CASE KILL_DOE_KILL RETURN "Doe" CASE KILL_MOUNTAIN_LION_KILL RETURN "Mountain Lion" CASE KILL_BOAR_KILL RETURN "Boar" CASE KILL_COYOTE_KILL RETURN "Coyote" CASE KILL_BIRD_KILL RETURN "Bird" CASE KILL_HUMAN_KILL RETURN "Human" CASE KILL_ROAD_KILL SWITCH GET_ENTITY_MODEL(entCorpse) CASE A_C_DEER IF IS_ELK_A_DOE(entCorpse) RETURN "Doe (Roadkill)" ELSE RETURN "Elk (Roadkill)" ENDIF BREAK CASE A_C_MTLION RETURN "Mountain Lion (Roadkill)" CASE A_C_BOAR RETURN "Boar (Roadkill)" CASE A_C_COYOTE RETURN "Coyote (Roadkill)" DEFAULT RETURN "Unknown Roadkill" ENDSWITCH BREAK CASE KILL_LIVE_ANIMAL SWITCH GET_ENTITY_MODEL(entCorpse) CASE A_C_DEER IF IS_ELK_A_DOE(entCorpse) RETURN "Doe (Live)" ELSE RETURN "Elk (Live)" ENDIF BREAK CASE A_C_MTLION RETURN "Mountain Lion (Live)" CASE A_C_BOAR RETURN "Boar (Live)" CASE A_C_COYOTE RETURN "Coyote (Live)" DEFAULT RETURN "Unknown Live Animal" ENDSWITCH BREAK ENDSWITCH RETURN "Unknown Photo Subject" ENDFUNC #ENDIF /// PURPOSE: /// Stop the sniper audio from activating. Used to stop the audio playing on the results screen /// and if we need to free up audio slots to play the mission passed theme. PROC STOP_SNIPE_AUDIO() IF IS_AUDIO_SCENE_ACTIVE("HUNTING_02_SETTINGS") STOP_AUDIO_SCENE("HUNTING_02_SETTINGS") STOP_SOUND(iSoundID) RELEASE_SOUND_ID(iSoundID) iSoundID = -1 ENDIF ENDPROC /// PURPOSE: /// Triggers an ambient speech line from the player if he hasn't commented recently. PROC TRIGGER_HUNTING_AUDIO(STRING sAmbientSpeech, BOOL bAllowOverlap = FALSE) // Don't trigger too recently, unless we're allowed to overlap. IF NOT bAllowOverlap AND Player_Hunt_Data.iLastCommentTime > GET_GAME_TIMER() EXIT ENDIF // Trigger the dialogue & delay the next one. PLAY_PED_AMBIENT_SPEECH_WITH_VOICE_NATIVE(PLAYER_PED_ID(), sAmbientSpeech, "TREVOR_NORMAL", AUDIO_SPEECH_GET_PARAM_STRING_FROM_ENUM(SPEECH_PARAMS_FORCE)) Player_Hunt_Data.iLastCommentTime += HUNTING_COMMENT_DELAY ENDPROC // Try to supress the global help text displaying when the select screen is on screen. PROC SUPRESS_HELP_TEXT() IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("AM_H_ARMST") OR IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("AM_H_FTXT") CLEAR_HELP() ENDIF ENDPROC PROC CHALLENGE_NOTIFICATION( STRING sText, INT iScore, INT iScoreGoal ) BEGIN_TEXT_COMMAND_THEFEED_POST( sText ) ADD_TEXT_COMPONENT_INTEGER(iScore) ADD_TEXT_COMPONENT_INTEGER(iScoreGoal) END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE) ENDPROC /// PURPOSE: /// Sets whether or not elk will randomly make noise and call. /// Does not stop the reply to the elk call. PROC SET_ELK_RANDOM_CALLS_ENABLED(MY_ELK & thisElk, BOOL bRandomCallsEnabled) thisElk.bRandomlyCalls = bRandomCallsEnabled ENDPROC /// PURPOSE: /// Sets whether an elk will have a 75% chance of replying to a call, or a 100% chance. PROC SET_ELK_MUST_REPLY_TO_CALL(MY_ELK & thisElk, BOOL bMustReplyToCall) thisElk.bMustReplyToCall = bMustReplyToCall ENDPROC /// PURPOSE: /// Stores in globals that the player has hunted, and a week from now, he'll be getting old conversations. /// This is so that if the player makes phonecalls in ambient hunting, he's given a proper conversation. PROC SET_TIME_LAST_HUNTED(BOOL bAwesomeHunt = FALSE) g_SavedGlobals.sAmbient.todHuntedWeekExp = GET_CURRENT_TIMEOFDAY() ADD_TIME_TO_TIMEOFDAY(g_SavedGlobals.sAmbient.todHuntedWeekExp, 0, 0, 0, 7) // Player's hunted recently. CANCEL_COMMUNICATION(CHAT_CLE1_1) CANCEL_COMMUNICATION(CHAT_CLE1_2) CANCEL_COMMUNICATION(CHAT_CLE2_1) CANCEL_COMMUNICATION(CHAT_CLE2_2) CANCEL_COMMUNICATION(CHAT_CLE3_1) // Re-add the proper conversations. If it was an awesome hunt, we trigger that. Otherwise IF bAwesomeHunt PRINTLN("--------------------------------- PLAYER HAD GREAT HUNT! ADDING CONVO 3! ---------------------------------") REGISTER_CHAT_CALL_FROM_PLAYER_TO_CHARACTER(CHAT_CLE3_1, BIT_TREVOR, CHAR_HUNTER, 3, 7200000) ELSE PRINTLN("--------------------------------- PLAYER HAD OKAY HUNT, ADDING CONVO 1 & 2! ---------------------------------") REGISTER_CHAT_CALL_FROM_PLAYER_TO_CHARACTER(CHAT_CLE1_1, BIT_TREVOR, CHAR_HUNTER, 3, 7200000) REGISTER_CHAT_CALL_FROM_PLAYER_TO_CHARACTER(CHAT_CLE1_2, BIT_TREVOR, CHAR_HUNTER, 3, 7200000) ENDIF ENDPROC /// PURPOSE: /// Adds blip to Peds first checking that the blip doesnt exist then if the ped is ok. Also can set the ped to be enemy blip or not PROC ADD_SAFE_BLIP_TO_PED(BLIP_INDEX &blipIn, PED_INDEX pedIndex, BOOL bEnemy = TRUE, FLOAT fScale = 1.0) IF NOT DOES_BLIP_EXIST(blipIn) IF IS_PED_UNINJURED(pedIndex) blipIn = CREATE_BLIP_FOR_PED(pedIndex, bEnemy) SET_BLIP_SCALE(blipIn, fScale) ENDIF ENDIF ENDPROC /// PURPOSE: /// Loads the elk model. PROC LOAD_ELK_MODEL() REQUEST_MODEL(A_C_DEER) WHILE NOT HAS_MODEL_LOADED(A_C_DEER) WAIT(0) ENDWHILE ENDPROC /// PURPOSE: /// Requests a model and checks that it has loaded /// PARAMS: /// _modname - The name of the model to load /// _debugstring - The string to print -purely debug /// i - an index to be printed in case you are loading models that are referenced in an array /// RETURNS: /// TRUE if the model loaded FUNC BOOL REQUEST_AND_CHECK_MODEL(MODEL_NAMES _modname) REQUEST_MODEL(_modname) IF HAS_MODEL_LOADED(_modname) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// To confuse the living piss out of anyone who tries to use it, read it /// or, god forbid, try to debug it. I don't even... /// Spawns a ped and returns true if it was succesful /// Loads the model and unloads the model if the ped was created properly /// PARAMS: /// pedindex - The ped index to write the newly created ped to /// model - The model the ped should be created with /// pos - The postion the ped should be created at /// dir - The heading the ped should have /// RETURNS: /// TRUE if the ped was created sucessfully FUNC BOOL SPAWN_PED(PED_INDEX &pedindex, MODEL_NAMES model, VECTOR pos, FLOAT dir, BOOL bUnload = TRUE, BOOL bIsHunter = FALSE, BOOL bForceElkDoe = FALSE) IF NOT DOES_ENTITY_EXIST(pedindex) IF REQUEST_AND_CHECK_MODEL(model) pedindex = CREATE_PED(PEDTYPE_MISSION, model, pos, dir) IF NOT bIsHunter // Deer are a special case. They need to be tagged, have antlers, and can only have so many doe in play at once. IF (model = A_C_DEER) BOOL bSpawnElk = TRUE // See if we should & can spawn a doe. IF (iDoeInPlay < MAX_DOE_IN_PLAY) OR bForceElkDoe FLOAT fPctDoes = 50.0 IF (iElksInPlay != 0) // Careful not to divide by 0... fPctDoes = TO_FLOAT(iDoeInPlay) / TO_FLOAT(iElksInPlay) // We don't get a proper percent because we actually want to skew towards spawning doe. // This is because doe will inevitably fill up anyway, and we'll be forced to make elk. fPctDoes *= 75.0 ENDIF IF GET_RANDOM_INT_IN_RANGE(0, 100) > fPctDoes OR bForceElkDoe SET_PED_COMPONENT_VARIATION(pedindex, PED_COMP_SPECIAL, 0, 0) DECOR_SET_BOOL(pedindex, "doe_elk", TRUE) bSpawnElk = FALSE iDoeInPlay += 1 ENDIF ENDIF // If we still need to spawn, that means eithe rwe shouldn't have, or couldn't have spawned a doe. IF bSpawnElk SET_PED_COMPONENT_VARIATION(pedindex, PED_COMP_SPECIAL, 1, 0) // GIVE HIM ANTLERS IF DECOR_EXIST_ON(pedindex, "doe_elk") DECOR_REMOVE(pedindex, "doe_elk") ENDIF ENDIF // Deer have 3 color variants. SET_PED_COMPONENT_VARIATION(pedindex, PED_COMP_HEAD, 0, GET_RANDOM_INT_IN_RANGE(0, 3)) // Change fur color ELIF (model = A_C_MTLION) // Mountain lions have 3 color variants. SET_PED_COMPONENT_VARIATION(pedindex, PED_COMP_HEAD, 0, GET_RANDOM_INT_IN_RANGE(0, 3)) // Change fur color ELIF (model = A_C_BOAR) // Boar have 4 color variants. SET_PED_COMPONENT_VARIATION(pedindex, PED_COMP_HEAD, 0, GET_RANDOM_INT_IN_RANGE(0, 4)) // Change fur color ENDIF // Make the boar visible from far away. SET_ENTITY_LOD_DIST(pedindex, 1500) SET_ENTITY_LOAD_COLLISION_FLAG(pedindex, TRUE) SET_PED_LOD_MULTIPLIER(pedindex, 5.0) ENDIF IF bUnload SET_MODEL_AS_NO_LONGER_NEEDED(model) ENDIF IF DOES_ENTITY_EXIST(pedindex) SET_PED_CAN_BE_TARGETTED(pedindex, FALSE) RETURN TRUE ENDIF ELSE RETURN FALSE ENDIF ELSE RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Spawns and sets up a ped with a debug name /// Basic function that can be expanded on /// PARAMS: /// index - The ped index to write the new ped to /// pos - The position to create ped /// fDir - The heading to give ped /// modelName - The model to create the ped with /// RETURNS: /// TRUE if the ped was created properly FUNC BOOL SETUP_PED(PED_INDEX &index, VECTOR pos, FLOAT fDir, MODEL_NAMES modelName, BOOL bUnload = TRUE, BOOL bForceElkDoe = FALSE) IF SPAWN_PED(index, modelName, pos, fDir, bUnload, DEFAULT, bForceElkDoe) IF IS_PED_UNINJURED(index) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC // Gradually reduces the vehicle density in the world. PROC DIAL_DOWN_TRAFFIC() IF fCarDensity > 0.0 IF NOT bGotDialDownTime iDialDownTime = GET_GAME_TIMER() + 3000 bGotDialDownTime = TRUE ELSE IF GET_GAME_TIMER() > iDialDownTime fCarDensity = fCarDensity - 0.1 //CPRINTLN(DEBUG_MISSION,"DIALING DOWN TRAFFIC TO ", fCarDensity) bGotDialDownTime = FALSE ENDIF ENDIF ENDIF //CPRINTLN(DEBUG_MISSION,"DIALING DOWN TRAFFIC TO ", fCarDensity) SET_VEHICLE_DENSITY_MULTIPLIER_THIS_FRAME(fCarDensity) ENDPROC /// GIVES THE PLAYER A SNIPER RIFLE, IF HE DOESN'T ALREADY HAVE ONE PROC SAFE_GIVE_SNIPER_TO_PLAYER(BOOL bForceToHand = TRUE) PED_INDEX pedPlayer = PLAYER_PED_ID() IF IS_PED_UNINJURED(pedPlayer) IF NOT HAS_PED_GOT_WEAPON(pedPlayer, WEAPONTYPE_SNIPERRIFLE, GENERALWEAPON_TYPE_INVALID) // Need to give the sniper rifle! CDEBUG2LN( DEBUG_MISSION, "SAFE_GIVE_SNIPER_TO_PLAYER player didn't have sniper rifle" ) bHadSniperRifle = FALSE GIVE_WEAPON_TO_PED(pedPlayer, WEAPONTYPE_SNIPERRIFLE, INFINITE_AMMO, bForceToHand, TRUE) ELSE // Player had sniper rifle. Just set infinite ammo and suppressor. bHadSniperRifle = TRUE SET_CURRENT_PED_WEAPON(pedPlayer, WEAPONTYPE_SNIPERRIFLE, bForceToHand) iSniperAmmoBefore = GET_PED_AMMO_BY_TYPE(pedPlayer, AMMOTYPE_SNIPER) IF iSniperAmmoBefore = 0 CDEBUG2LN( DEBUG_MISSION, "SAFE_GIVE_SNIPER_TO_PLAYER ammo was 0, setting with SET_PED_AMMO_BY_TYPE and SET_AMMO_IN_CLIP." ) SET_PED_AMMO_BY_TYPE( pedPlayer, AMMOTYPE_SNIPER, 20 ) SET_AMMO_IN_CLIP( pedPlayer, WEAPONTYPE_SNIPERRIFLE, 10 ) WAIT(0) ENDIF ENDIF IF NOT HAS_PED_GOT_WEAPON_COMPONENT(pedPlayer, WEAPONTYPE_SNIPERRIFLE, WEAPONCOMPONENT_AT_AR_SUPP_02) bHadSuppressor = FALSE GIVE_WEAPON_COMPONENT_TO_PED(pedPlayer, WEAPONTYPE_SNIPERRIFLE, WEAPONCOMPONENT_AT_AR_SUPP_02) ELSE bHadSuppressor = TRUE ENDIF SET_PED_INFINITE_AMMO(pedPlayer, TRUE, WEAPONTYPE_SNIPERRIFLE) ENDIF ENDPROC PROC RETURN_PLAYERS_GUN(BOOL bForceCleanup = FALSE) PED_INDEX pedPlayer = PLAYER_PED_ID() IF IS_PED_UNINJURED(pedPlayer) OR bForceCleanup // Regardless, don't set the player to infinite ammo. SET_PED_INFINITE_AMMO(pedPlayer, FALSE, WEAPONTYPE_SNIPERRIFLE) SET_PED_AMMO_BY_TYPE(pedPlayer, AMMOTYPE_SNIPER, iSniperAmmoBefore) IF NOT bHadSuppressor IF HAS_PED_GOT_WEAPON_COMPONENT(pedPlayer, WEAPONTYPE_SNIPERRIFLE, WEAPONCOMPONENT_AT_AR_SUPP_02) REMOVE_WEAPON_COMPONENT_FROM_PED(pedPlayer, WEAPONTYPE_SNIPERRIFLE, WEAPONCOMPONENT_AT_AR_SUPP_02) ENDIF ENDIF IF NOT bHadSniperRifle REMOVE_WEAPON_FROM_PED(pedPlayer, WEAPONTYPE_SNIPERRIFLE) ENDIF ENDIF ENDPROC FUNC BOOL CAN_PLAYER_SEE_POINT(VECTOR vPos, FLOAT fRadius = 5.0, INT distance = 120) IF IS_PED_UNINJURED(PLAYER_PED_ID()) FLOAT fDiff = GET_DISTANCE_BETWEEN_COORDS( GET_ENTITY_COORDS(PLAYER_PED_ID()), vPos) IF fDiff <= distance IF IS_SPHERE_VISIBLE(vPos, fRadius) RETURN TRUE ENDIF ENDIF ENDIF RETURN FALSE ENDFUNC FUNC BOOL DOES_PLAYER_HAVE_RIFLE_EQUIPT() IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF GET_WEAPONTYPE_GROUP(GET_PEDS_CURRENT_WEAPON(PLAYER_PED_ID())) = WEAPONGROUP_SNIPER //CPRINTLN(DEBUG_MISSION, "PLAYER HAS SNIPER") IF NOT bSniperEquiped bSniperEquiped = TRUE ENDIF RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC FUNC BOOL IS_PLAYER_IN_IMMEDIATE_HUNT_AREA() VECTOR vPos vPos = GET_ENTITY_COORDS(PLAYER_PED_ID()) IF IS_POINT_IN_POLY_2D(mAreaCheck1, vPos) RETURN TRUE ENDIF RETURN FALSE ENDFUNC FUNC BOOL IS_PLAYER_IN_OUTER_HUNT_AREA() VECTOR vPos vPos = GET_ENTITY_COORDS(PLAYER_PED_ID()) IF IS_POINT_IN_POLY_2D(mAreaCheck2, vPos) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Turn off the ambient services PROC SERVICES_TOGGLE(BOOL bOn) //Wanted ENABLE_DISPATCH_SERVICE(DT_POLICE_AUTOMOBILE, bOn) ENABLE_DISPATCH_SERVICE(DT_POLICE_HELICOPTER, bOn) ENABLE_DISPATCH_SERVICE(DT_FIRE_DEPARTMENT, bOn) ENABLE_DISPATCH_SERVICE(DT_SWAT_AUTOMOBILE, bOn) ENABLE_DISPATCH_SERVICE(DT_AMBULANCE_DEPARTMENT, bOn) IF bOn //SET_VEHICLE_DENSITY_MULTIPLIER(1.0) SET_WANTED_LEVEL_MULTIPLIER(1.0) SET_MAX_WANTED_LEVEL(5) ELSE SET_MAX_WANTED_LEVEL(0) SET_WANTED_LEVEL_MULTIPLIER(0.0) ENDIF ENDPROC // ================== // ELK FUNCTIONS // ================== // Used in hunt2 FUNC INT GET_SPOOKED_REASON(INT i) RETURN ENUM_TO_INT(mElk[i].eSpookedReason) ENDFUNC // RETURNS TRUE IF THE ELK EXISTS AND IS NOT DEAD FUNC BOOL IS_ELK_OK(INT i) RETURN DOES_ENTITY_EXIST(mElk[i].mPed) AND NOT IS_ENTITY_DEAD(mElk[i].mPed) ENDFUNC FUNC BOOL IS_ANY_ELK_OK() INT i = 0 REPEAT MAX_ELKS i IF IS_ELK_OK (i) RETURN TRUE ENDIF ENDREPEAT RETURN FALSE ENDFUNC /// PURPOSE: /// Checks if any of the main pool of elks is currently a herd member (Only one herd can be active at a time) /// RETURNS: /// FUNC BOOL IS_ANY_ELK_A_HERD_MEMBER() INT i = 0 WHILE i < MAX_ELKS IF IS_ELK_OK(i) IF mElk[i].bIsHerdMember RETURN TRUE ENDIF ENDIF ++ i ENDWHILE RETURN FALSE ENDFUNC // RETURNS TRUE IF ANY ELK HAS BEEN DAMAGED BY THE PLAYER FUNC BOOL HAS_PLAYER_SHOT_ELK(INT i) IF IS_ELK_OK(i) IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mElk[i].mPed, PLAYER_PED_ID()) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Spooks or unspooks the Elk in mElk[i] /// PARAMS: /// i - The index of the elk to spook PROC SET_ELK_SPOOKED( INT i, BOOL bSpook ) IF i < 0 OR i >= MAX_ELKS DEBUG_PRINTCALLSTACK() CWARNINGLN( DEBUG_MISSION, "SET_ELK_SPOOKED exiting, i is out of bounds, i=", i ) EXIT ENDIF CDEBUG2LN( DEBUG_MISSION, "SET_ELK_SPOOKED setting elk i=", i, " to ", PICK_STRING( bSpook, "TRUE", "FALSE" ) ) mElk[i].bIsSpooked = bSpook ENDPROC // Used in non-ambient missions to get the Elk to flee and set the appropriate fail message. PROC FORCE_ELK_FLEE(INT i) IF NOT bIsAmbient IF IS_ENTITY_ALIVE(mElk[i].mPed) CPRINTLN(DEBUG_MISSION,"FORCE ELK FLEE ", i) SET_ENTITY_PROOFS(mElk[i].mPed, TRUE, FALSE, FALSE, FALSE, FALSE) TASK_SMART_FLEE_PED(mElk[i].mPed, PLAYER_PED_ID(), 500.0, -1, FALSE) SET_PED_KEEP_TASK(mElk[i].mPed, TRUE) ENDIF SET_ELK_SPOOKED(i, TRUE) ENDIF ENDPROC FUNC BOOL IS_ELK_CLOSE_TO_SPOOKED_ELK(INT i) INT j = 0 REPEAT MAX_ELKS j IF j <> i IF IS_ELK_OK(j) IF mElk[j].bIsSpooked IF (GET_DISTANCE_BETWEEN_ENTITIES (mElk[i].mPed, mElk[j].mPed)) < 10.0 RETURN TRUE ENDIF ENDIF ENDIF ENDIF ENDREPEAT RETURN FALSE ENDFUNC // SHOULD WE TURN THE WIND DIRECTION ARROW RED FUNC BOOL PLAYER_CLOSE_TO_BEING_DETECTED() INT i = 0 REPEAT MAX_ELKS i IF IS_ELK_OK(i) AND NOT mElk[i].bIsSpooked VECTOR vNormal = NORMALISE_VECTOR(mElk[i].vScentOffsetPos+<<0,0,ELK_SCENT_RANGE>> - mElk[i].vPos+<<0,0,-ELK_SCENT_RANGE>>) VECTOR vA = (mElk[i].vPos + <<0.0, 0.0, ELK_SCENT_RANGE>>)// - (vNormal * 45.0) VECTOR vB = (mElk[i].vScentOffsetPos + <<0.0, 0, -ELK_SCENT_RANGE >>) + (vNormal * 45.0) // DRAW_DEBUG_AREA(mElk[i].vPos + <<0.0, 0.0, ELK_SCENT_RANGE>>, mElk[i].vScentOffsetPos + <<0.0, 0, -ELK_SCENT_RANGE >>, ELK_SCENT_WIDTH, 255, 255, 255) // DRAW_DEBUG_AREA(vA, vB, ELK_SCENT_WIDTH+15, 74, 44, 14) IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), vA, vB, ELK_SCENT_WIDTH+20, FALSE, FALSE, TM_ANY) IF bIsAmbient IF NOT Player_Hunt_Data.bSentDownwindHelp IF NOT IS_MESSAGE_BEING_DISPLAYED() PRINT_HELP("AHT_DOWNWIND") Player_Hunt_Data.bSentDownwindHelp = TRUE ENDIF ENDIF ENDIF RETURN TRUE ENDIF ENDIF ENDREPEAT RETURN FALSE ENDFUNC /// PURPOSE: /// Forces all elk associated with a particular herd to scatter and flee. /// PARAMS: /// idxMemberOrLeader - index of either a member elk or leader elk. PROC FORCE_ELK_HERD_SCATTER(INT idxMemberOrLeader) INT iLeaderIdx = idxMemberOrLeader IF mElk[idxMemberOrLeader].bIsHerdMember // Okay, get it's leader. iLeaderIdx = mElk[idxMemberOrLeader].iLeaderIdx ENDIF SET_ELK_SPOOKED(idxMemberOrLeader, TRUE) mElk[idxMemberOrLeader].bIsHerdLeader = FALSE mElk[idxMemberOrLeader].bIsHerdMember = FALSE mElk[idxMemberOrLeader].iLeaderIdx = -1 // Otherwise, this was already the leader. // Loop through all elk. Any living elk that claims this index as it's leader's index needs to spook. INT idx REPEAT MAX_ELKS idx // Leader check is cheap, do that first. IF (mElk[idx].iLeaderIdx = iLeaderIdx) IF DOES_ENTITY_EXIST(mElk[idx].mPed) AND NOT IS_ENTITY_DEAD(mElk[idx].mPed) FORCE_ELK_FLEE(idx) // Need to set our fleeing reason. mElk[idx].eSpookedReason = SR_SPOOKED_BY_ELK // Lastly, this elk needs to leave the herd. SET_ELK_SPOOKED(idx, TRUE) mElk[idx].bIsHerdLeader = FALSE mElk[idx].bIsHerdMember = FALSE mElk[idx].iLeaderIdx = -1 ENDIF ENDIF ENDREPEAT ENDPROC /// PURPOSE: Checks whether the Elk has detected the player /// RETURNS: TRUE if the player is in the elk's line of sight, /// or if you are downwind of the elk, /// or within 15 metres of it in any direction making noise. PROC CHECK_ELK_SPOOKED(INT i) BOOL bWasAlreadySpooked = mElk[i].bIsSpooked IF IS_ELK_OK(i) AND NOT mElk[i].bIsSpooked mElk[i].vPos = GET_ENTITY_COORDS(mElk[i].mPed, FALSE) mElk[i].fDist = GET_DISTANCE_BETWEEN_COORDS(mElk[i].vPos, GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), FALSE) mElk[i].vScentOffsetPos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(mElk[i].vPos, fWindDirection, -SCENT_RANGE) IF CAN_PED_SEE_HATED_PED(mElk[i].mPed, PLAYER_PED_ID()) IF bIsAmbient PRINT_HELP("AHT_CROUCH") // THE ELK SAW YOU. STAY OUT OF ITS LINE OF SIGHT ELSE CPRINTLN(DEBUG_MISSION,"CHECKING FROM HUNTIN2 - ELK SAW YOU") PRINT_HELP ("HT_CROUCH") // THE ELK SAW YOU. STAY OUT OF ITS LINE OF SIGHT FORCE_ELK_FLEE(i) mElk[i].eSpookedReason = SR_SAW_PLAYER // So we can pass the spooked reason over to the hunting 2 script ENDIF //CPRINTLN(DEBUG_MISSION, "Setting spooked flag - spotted player") SET_ELK_SPOOKED(i, TRUE) ENDIF // Is the player just so close that the elk would have to know he's there? IF (mElk[i].fDist < k_ELK_SPOOK_RANGE) IF bIsAmbient PRINT_HELP("AHT_NOTICED") // If elk detect danger close nearby, they will flee. ELSE PRINT_HELP("HT_HEARD") ENDIF mElk[i].eSpookedReason = SR_HEARD_PLAYER SET_ELK_SPOOKED(i, TRUE) ENDIF // CAN THE ELK SMELL THE PLAYER IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), mElk[i].vPos+<<0,0,-ELK_SCENT_RANGE>>, mElk[i].vScentOffsetPos+<<0,0,ELK_SCENT_RANGE>>, ELK_SCENT_WIDTH, FALSE, FALSE, TM_ANY) IF bIsAmbient PRINT_HELP("AHT_SCENT") // THE ELK PICKED UP YOUR SCENT. ALWAYS TRY TO STAY DOWNWIND FROM YOUR QUARRY ELSE PRINT_HELP ("HT_SCENT") // THE ELK PICKED UP YOUR SCENT. ALWAYS TRY TO STAY DOWNWIND FROM YOUR QUARRY ENDIF FORCE_ELK_FLEE(i) mElk[i].eSpookedReason = SR_SMELLED_PLAYER SET_ELK_SPOOKED(i, TRUE) ENDIF // CAN THE ELK HEAR THE PLAYER? IF CAN_PED_HEAR_PLAYER(PLAYER_ID(), mElk[i].mPed) IF bIsAmbient PRINT_HELP("AHT_HEARD") // THE ELK HEARD YOU. WHEN CLOSE, USE STEALTH TO HELP REMAIN UNDETECTED ELSE FORCE_ELK_FLEE(i) PRINT_HELP("HT_HEARD") // THE ELK HEARD YOU. WHEN CLOSE, USE STEALTH TO HELP REMAIN UNDETECTED mElk[i].eSpookedReason = SR_HEARD_PLAYER ENDIF SET_ELK_SPOOKED(i, TRUE) ENDIF // HAS THE ELK COME CLOSE TO ANOTHER SPOOKED ELK? IF IS_ELK_CLOSE_TO_SPOOKED_ELK(i) IF NOT bIsAmbient FORCE_ELK_FLEE(i) mElk[i].eSpookedReason = SR_SPOOKED_BY_ELK ENDIF CPRINTLN(DEBUG_MISSION,"Setting spooked flag - spooked by a fleeing elk") SET_ELK_SPOOKED(i, TRUE) ENDIF // HAS THE ELK BEEN SPOOKED BY A NEAR MISS? IF IS_ANYONE_SHOOTING_NEAR_PED(mElk[i].mPed) IF NOT bGotNearMissTime CPRINTLN(DEBUG_MISSION, "bullet too close to elk ", i ) iMissMessageDelay = GET_GAME_TIMER() + MISS_MESSAGE_DELAY_TIME bGotNearMissTime = TRUE ENDIF IF bIsAmbient TRIGGER_HUNTING_AUDIO("HUNTING_MISSED") iLocalKillCount = Player_Hunt_Data.iScore SET_ELK_SPOOKED(i, TRUE) ELSE FORCE_ELK_FLEE(i) SET_ELK_SPOOKED(i, TRUE) mElk[i].eSpookedReason = SR_NEAR_MISS ENDIF ENDIF IF bGotNearMissTime //CPRINTLN(DEBUG_MISSION, "This elk has a near miss time ", i ) // Only show the "You missed" message if, after a second, the kill count hasn't gone up // or the message isn't being suppressed by a recent kill IF GET_GAME_TIMER() > iMissMessageDelay IF iLocalKillCount = Player_Hunt_Data.iScore AND NOT bSuppressNearMissMessage IF bIsAmbient // Don't really want to notify the player that he missed an elk if he didn't even see the elk he missed. //IF WOULD_ENTITY_BE_OCCLUDED(A_C_DEER, mElk[i].vPos, FALSE) PRINT_HELP("AHT_MISS") // YOU MISSED AND SPOOKED THE ELK. BE SURE TO HIT THE TARGET NEXT TIME //ENDIF ELSE PRINT_HELP("HT_MISS") // YOU MISSED AND SPOOKED THE ELK. BE SURE TO HIT THE TARGET NEXT TIME ENDIF ENDIF bShouldClearSuppressNearMissMsg = TRUE bGotNearMissTime = FALSE ENDIF ENDIF ENDIF IF mElk[i].bIsSpooked AND NOT bWasAlreadySpooked // Reset the kills since spooked counter Player_Hunt_Data.iKillsSinceSpooked = 0 // If he's a herd member, he scatters. IF mElk[i].bIsHerdMember OR mElk[i].bIsHerdLeader FORCE_ELK_HERD_SCATTER(i) ENDIF ENDIF ENDPROC // RETURNS TRUE IF THE PLAYER CAN SEE ANY ELK FUNC BOOL CAN_PLAYER_SEE_ELK(INT i) IF IS_ELK_OK(i) IF IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), mElk[i].mPed, 150.0) AND IS_ENTITY_ON_SCREEN(mElk[i].mPed) RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Checks to see if the player has pressed the call button /// PARAMS: /// i - the index of the elk to use when checking INT iResponseTime INT iCallEndTime INT iWhistleDelay = -1 INT iWhistleCallTime //BOOL bShowNoiseBlip CONST_INT CALL_DURATION 4000 CONST_INT FADE_DELAY_TIME 4000 CONST_INT RESPONSE_DELAY 3500 CONST_INT WHISTLE_CALL_TIME 2500 /// PURPOSE: /// Returns the MS to wait for a shapetest given the distance something is from the player. FUNC INT GET_HARD_BLIP_DELAY_TIME(FLOAT fDist) IF (fDist > 180) RETURN 3500 ELIF (fDist > 120) RETURN 2500 ELIF (fDist > 50) RETURN 2000 ENDIF // Always wait at least a second. RETURN 1000 ENDFUNC /// PURPOSE: /// Runs a shapetest on an occluded ped. /// RETURNS: /// 1 if the test passed. 0 to keep processing. -1 if it failed and is done. FUNC INT RUN_SHAPE_TEST_FOR_ELK(MY_ELK & thisElk, VECTOR vElkCoord, FLOAT fDistToPlayer) IF (elkShapeTest = NULL) //PRINTLN("Starting shapetest on elk: ", iAnimalIdx) VECTOR vStart = vHuntingPlayerCoords + <<0,0,0.75>> elkShapeTest = START_SHAPE_TEST_LOS_PROBE(vStart, vElkCoord) ELSE INT iHit VECTOR vHitPos, vNormal ENTITY_INDEX entHit //PRINTLN("Processing shapetest on animal: ", iAnimalIdx) SHAPETEST_STATUS eResult = GET_SHAPE_TEST_RESULT(elkShapeTest, iHit, vHitPos, vNormal, entHit) IF (eResult = SHAPETEST_STATUS_RESULTS_READY) //PRINTLN("Shapetest results -- iHit: ", iHit, ", vPos: ", vHitPos, ", entHit: ", NATIVE_TO_INT(entHit)) IF (iHit = 0) // PASSED! //PRINTLN("Elk passed shapetest: ", vElkCoord) thisElk.iNextTestTime = GET_GAME_TIMER() + GET_HARD_BLIP_DELAY_TIME(fDistToPlayer) iElkTesting = -1 elkShapeTest = NULL RETURN 1 ELSE // FAILED //PRINTLN("Elk failed shapetest: ", vElkCoord) thisElk.iNextTestTime = GET_GAME_TIMER() + GET_HARD_BLIP_DELAY_TIME(fDistToPlayer) iElkTesting = -1 elkShapeTest = NULL RETURN -1 ENDIF ELIF (eResult = SHAPETEST_STATUS_NONEXISTENT) //PRINTLN("No test result. Going to null: ", iAnimalIdx) //PRINTLN("No shapetest: ", vElkCoord) iElkTesting = -1 elkShapeTest = NULL RETURN -1 ENDIF ENDIF //PRINTLN("Processing shapetest: ", vElkCoord) RETURN 0 ENDFUNC PROC MANAGE_ELK_BLIP(MY_ELK &thisElk, INT iElkIndex) IF NOT IS_ELK_OK(iElkIndex) IF DOES_BLIP_EXIST(thisElk.mElkBlip) CPRINTLN(DEBUG_MISSION, "Remove existing blip on Elk that's not okay.") REMOVE_BLIP(thisElk.mElkBlip) ENDIF EXIT ENDIF IF thisElk.bIsSpooked EXIT ENDIF // Distance is needed no matter what. VECTOR vDeerCoord = GET_ENTITY_COORDS(thisElk.mPed) FLOAT distToPlayer = GET_DISTANCE_BETWEEN_COORDS(vHuntingPlayerCoords, vDeerCoord) BOOL bOnScreen = IS_ENTITY_ON_SCREEN(thisElk.mPed) // Hard blipping will be checked first. IF NOT thisElk.bHardBlipped BOOL bOccluded = TRUE IF bOnScreen AND (thisElk.iNextTestTime < GET_GAME_TIMER()) AND (distToPlayer < fDistanceThreshold) AND (iElkTesting = iElkIndex OR iElkTesting = -1) // Flag us as the tester! iElkTesting = iElkIndex INT iResult = RUN_SHAPE_TEST_FOR_ELK(thisElk, vDeerCoord, distToPlayer) IF (iResult = 1) // Passed! bOccluded = FALSE ENDIF ENDIF // Blip the deer if he's on screen, ,not occluded, and "close enough" as defined by zoom level. IF bOnScreen AND NOT bOccluded FLOAT fScreenX, fScreenY GET_HUD_SCREEN_POSITION_FROM_WORLD_POSITION(vDeerCoord, fScreenX, fScreenY) IF (fScreenX > 0.3 AND fScreenX < 0.7 AND fScreenY > 0.3 AND fScreenY < 0.7) AND (distToPlayer < fDistanceThreshold) CPRINTLN(DEBUG_MISSION, "Removing any existing blip on elk before hard blipping.") SAFE_REMOVE_BLIP(thisElk.mElkBlip) ADD_SAFE_BLIP_TO_PED(thisElk.mElkBlip, thisElk.mPed, TRUE) SET_BLIP_SHOW_CONE(thisElk.mElkBlip, TRUE) thisElk.bHardBlipped = TRUE TRIGGER_HUNTING_AUDIO("HUNTING_SPOT_ANIMAL") CPRINTLN(DEBUG_MISSION, "Adding hard blip on ELK. fDist: ", distToPlayer, ", Zoom: ", fZoomLevel, ", ScreenX: ", fScreenX, ", ScreenY: ", fScreenY) EXIT ENDIF ENDIF ENDIF // If the elk doesn't have a blip... IF NOT DOES_BLIP_EXIST(thisElk.mElkBlip) // There's a few cases in which the elk has to be blipped: making a call, or responfing to the player. // Check response to the player. IF (bPlayerCalling AND GET_GAME_TIMER() > iResponseTime AND NOT thisElk.bCalling) OR (thisElk.bCalling) IF thisElk.bCalling // Elk gets a radius blip. FLOAT fBlipRadius = distToPlayer * 0.5 VECTOR vBlipPos = vDeerCoord CPRINTLN(DEBUG_MISSION, "Adding elk radius blip: ", fBlipRadius, " for elk: ", iElkIndex) CPRINTLN(DEBUG_MISSION, "Deer at: ", vDeerCoord, " & player at: ", vHuntingPlayerCoords) thisElk.mElkBlip = ADD_BLIP_FOR_RADIUS(vBlipPos/* + vBlipOffset*/, fBlipRadius) SET_BLIP_ALPHA(thisElk.mElkBlip, 100) SET_BLIP_COLOUR(thisElk.mElkBlip, BLIP_COLOUR_RED) SHOW_HEIGHT_ON_BLIP(thisElk.mElkBlip, FALSE) thisElk.iStartFadeTime = GET_GAME_TIMER() + 4000 ENDIF IF (thisElk.bRandomlyCalls AND GET_GAME_TIMER() > iResponseTime) OR bPlayerCalling // If the elk is supposed to be calling, make it happen. IF NOT thisElk.bCalling // Delay us a bit. IF (thisElk.iCallResponseTime = 0) thisElk.iCallResponseTime = GET_GAME_TIMER() + (GET_RANDOM_INT_IN_RANGE(0, 11) * 100) ELSE IF (thisElk.iCallResponseTime < GET_GAME_TIMER()) thisElk.iCallResponseTime = 0 PLAY_SOUND_FROM_ENTITY(-1, "ELK_BREY_MASTER", thisElk.mPed) CPRINTLN(DEBUG_MISSION, "Elk breying as a response to a call!") thisElk.bCalling = TRUE iBleatInitiateTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(BLEAT_TRIGGER_MIN_DELAY, BLEAT_TRIGGER_MAX_DELAY) ENDIF ENDIF ENDIF ENDIF ENDIF ELSE //CPRINTLN(DEBUG_MISSION,"Blip for this elk is visible = ", i) IF DOES_BLIP_EXIST(thisElk.mElkBlip) // Elk may be hard blipped, can still make calls. IF (bPlayerCalling AND GET_GAME_TIMER() > iResponseTime AND NOT thisElk.bCalling) CPRINTLN(DEBUG_MISSION, "Elk responding to another brey!") PLAY_SOUND_FROM_ENTITY(-1, "ELK_BREY_MASTER", thisElk.mPed) thisElk.bCalling = TRUE iBleatInitiateTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(BLEAT_TRIGGER_MIN_DELAY, BLEAT_TRIGGER_MAX_DELAY) EXIT ENDIF // So here, we only need to handle fading out. IF (GET_GAME_TIMER() > thisElk.iStartFadeTime AND distToPlayer > 35 AND thisElk.bCanFadeBlip) IF bOnScreen // See if we need to shapetest for the blip. IF (thisElk.iNextTestTime < GET_GAME_TIMER() AND (iElkTesting = iElkIndex OR iElkTesting = -1)) AND (distToPlayer < fDistanceThreshold) // Flag us as the tester! iElkTesting = iElkIndex INT iResult = RUN_SHAPE_TEST_FOR_ELK(thisElk, vDeerCoord, distToPlayer) IF (iResult = 1) // Passed! IF thisElk.bHardBlipped SET_BLIP_ALPHA(thisElk.mElkBlip, 255) ELSE SET_BLIP_ALPHA(thisElk.mElkBlip, 100) ENDIF thisElk.iStartFadeTime = GET_GAME_TIMER() + 10000 EXIT ELIF (iResult = -1) // Failed... ELIF (iResult = 0) // Continue processing... ENDIF ENDIF ENDIF thisElk.iBlipAlpha = GET_BLIP_ALPHA(thisElk.mElkBlip) IF thisElk.iBlipAlpha > MIN_BLIP_ALPHA IF GET_RANDOM_INT_IN_RANGE(0, 1000) > 666 thisElk.iBlipAlpha -= 1 //CPRINTLN(DEBUG_MISSION, "LOWERING BLIP ALPHA") SET_BLIP_ALPHA(thisElk.mElkBlip, thisElk.iBlipAlpha) ENDIF ELSE SET_BLIP_SHOW_CONE(thisElk.mElkBlip, FALSE) CPRINTLN(DEBUG_MISSION, "Elk blip alpha'd out. Removing.") SAFE_REMOVE_BLIP(thisElk.mElkBlip) thisElk.bHardBlipped = FALSE thisElk.bCalling = FALSE bPlayerCalling = FALSE ENDIF ENDIF ENDIF ENDIF ENDPROC PROC CHECK_FOR_CALLS() IF NOT bAllowCall //PRINTLN("CHECK_FOR_CALLS -- Calls disabled!") EXIT ENDIF IF NOT IS_PLAYER_PLAYING(PLAYER_ID()) PRINTLN("CHECK_FOR_CALLS -- Player not playing.") EXIT ENDIF PED_INDEX playerPed = PLAYER_PED_ID() IF GET_INTERIOR_FROM_ENTITY(playerPed) != NULL PRINTLN("CHECK_FOR_CALLS -- Player in interior.") EXIT ENDIF IF DOES_ENTITY_EXIST(GET_VEHICLE_PED_IS_USING(playerPed)) EXIT ENDIF IF IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() EXIT ENDIF //PRINTLN("CHECK_FOR_CALLS -- Waiting for an elk call...") IF (IS_CONTROL_JUST_RELEASED(FRONTEND_CONTROL, INPUT_SCRIPT_PAD_LEFT) AND NOT IS_PLAYER_FREE_AIMING(PLAYER_ID()) AND NOT IS_PED_RAGDOLL(playerPed) AND NOT IS_PED_RUNNING_RAGDOLL_TASK(playerPed)) OR (iWhistleDelay != -1) PRINTLN("Processing a player whistle!") // Allow player to call any time - as long as the last call isn't still playing... IF GET_GAME_TIMER() > iWhistleCallTime IF (iWhistleDelay = -1) PRINTLN("Player started a whistle!") // Start the timer. iWhistleDelay = GET_GAME_TIMER() + 250 ELIF (GET_GAME_TIMER() > iWhistleDelay) PRINTLN("Playing a player whistle.") // Play the sound. IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) <> CAM_VIEW_MODE_FIRST_PERSON TASK_PLAY_ANIM(playerPed, "facials@p_m_one@variations@elkcall", "mood_elkcal_1", DEFAULT, DEFAULT, DEFAULT, AF_SECONDARY) ENDIF PLAY_SOUND_FROM_ENTITY(-1, "PLAYER_CALLS_ELK_MASTER", playerPed) TRIGGER_SONAR_BLIP(GET_ENTITY_COORDS(playerPed), 30, HUD_COLOUR_BLUEDARK) iWhistleCallTime = GET_GAME_TIMER() + WHISTLE_CALL_TIME Player_Hunt_Data.iKillsSinceElkCall = 0 Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY iWhistleDelay = -1 // Reset all deer calls iBleatInitiateTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(BLEAT_TRIGGER_MIN_DELAY, BLEAT_TRIGGER_MAX_DELAY) // Only have response when elk are due to respond - probably need to rename this variable IF NOT bPlayerCalling iResponseTime = GET_GAME_TIMER() + RESPONSE_DELAY iCallEndTime = GET_GAME_TIMER() + CALL_DURATION bPlayerCalling = TRUE ENDIF ENDIF ENDIF ENDIF // See if we should be forcing sonar. IF (GET_GAME_TIMER() < iCallEndTime) CPRINTLN(DEBUG_HUNTING, "Forcing sonar blips due to recent call.") FORCE_SONAR_BLIPS_THIS_FRAME() ENDIF ENDPROC // Checks if a random node that's passed in is suitable for the Elk's new destintion FUNC BOOL IS_NODE_OK_FOR_THIS_ELK(INT i, INT iNode) //CPRINTLN(DEBUG_MISSION,"Randomly chosen node..") IF bIsAmbient = FALSE //CPRINTLN(DEBUG_MISSION,"... is no good as we're not ambient ") RETURN FALSE ENDIF IF iNode = mElk[i].iCurNode OR iNode = mElk[i].iPrevNode OR elkSpawn[iNode].bIsBooked OR GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(mElk[i].mPed, elkSpawn[iNode].vCoord) > 50.0 //CPRINTLN(DEBUG_MISSION,"... is no good ") RETURN FALSE ENDIF //CPRINTLN(DEBUG_MISSION,"... is OK TO TRAVEL TO ") RETURN TRUE ENDFUNC /// PURPOSE: Measures the distance from the Elk's current node to each other node in the network, /// disregarding the current node, the Elk's previously visited node, any node that is booked by another elk. /// RETURNS: The value of the closest suitable node. FUNC INT FIND_BEST_CLOSEST_NODE(INT i) FLOAT fCurDist = 0.0 FLOAT fShortestDist = 10000.0 INT iCounter = 0 INT iClosestNode = 0 REPEAT MAX_GRAZE_AREAS iCounter IF iCounter <> mElk[i].iCurNode AND iCounter <> mElk[i].iPrevNode AND NOT elkSpawn[iCounter].bIsBooked // Try to find the next closest... fCurDist = GET_DISTANCE_BETWEEN_COORDS(elkSpawn[mElk[i].iCurNode].vCoord, elkSpawn[iCounter].vCoord, FALSE) //CPRINTLN(DEBUG_MISSION,"NODE DISTANCE IS") //PRINTFLOAT(fCurDist) PRINTNL() IF fCurDist < fShortestDist //CPRINTLN(DEBUG_MISSION,"WHICH IS CLOSER THAN THE LAST NODE WE CHECKED") fShortestDist = fCurDist iClosestNode = iCounter ENDIF ENDIF ENDREPEAT RETURN iClosestNode ENDFUNC /// PURPOSE: /// Checks to see if there is an elk blip visable /// RETURNS: /// True if there is an elk blip visible on the radar FUNC BOOL IS_ANY_ELK_BLIP_VISIBLE() INT i = 0 REPEAT MAX_ELKS i IF DOES_BLIP_EXIST(mElk[i].mElkBlip) mElk[i].iBlipAlpha = GET_BLIP_ALPHA(mElk[i].mElkBlip) IF mElk[i].iBlipAlpha > MIN_BLIP_ALPHA RETURN TRUE ENDIF // ELSE // IF DOES_BLIP_EXIST(mElk[i].mHintBlip) // RETURN TRUE // ENDIF ENDIF ENDREPEAT RETURN FALSE ENDFUNC /// PURPOSE: /// Sets the elk state to ES_CHECK_CAN_SPAWN which kicks the elk /// state machine in to gear PROC SPAWN_FIRST_ELK() CPRINTLN(DEBUG_MISSION,"SPAWN FIRST ELK") INT i = 0 REPEAT MAX_ELKS i // There's a chance that we started with some elk. If this is the case, don't retask. IF NOT DOES_ENTITY_EXIST(mElk[i].mPed) CPRINTLN(DEBUG_MISSION,"CHECKING WE CAN SPAWN IN ELK NUMBER ", i) mElk[i].elkState = ES_CHECK_CAN_SPAWN ENDIF ENDREPEAT ENDPROC PROC UNBOOK_EVERY_GRAZE_POS() INT i REPEAT MAX_GRAZE_AREAS i elkSpawn[i].bIsBooked = FALSE elkSpawn[i].iNextSpawnTime = 0 ENDREPEAT ENDPROC /// PURPOSE: /// Deletes any alive elk and puts the elk state in to ES_NULL /// thereby stopping the state machine running PROC REMOVE_ALL_ELK() CPRINTLN(DEBUG_MISSION, "REMOVE_ALL_ELK") UNBOOK_EVERY_GRAZE_POS() INT i REPEAT MAX_ELKS i SAFE_REMOVE_BLIP(mElk[i].mElkBlip) IF DOES_ENTITY_EXIST(mElk[i].mPed) AND IS_ENTITY_A_MISSION_ENTITY(mElk[i].mPed) DELETE_PED(mElk[i].mPed) ENDIF SAFE_REMOVE_BLIP(mElk[i].mElkBlip) SET_ELK_SPOOKED(i, FALSE) mElk[i].elkState = ES_NULL mElk[i].iCallResponseTime = 0 ENDREPEAT iDoeInPlay = 0 iElksInPlay = 0 ENDPROC /// PURPOSE: /// Checks if an entity was damaged by the sniper rifle. /// PARAMS: /// index - the entity to check PROC CHECK_TARGET_DAMAGED_BY_RIFLE(ENTITY_INDEX index) CPRINTLN(DEBUG_MISSION,"CHECKING TARGET ELK WEAPON DAMAGE") // We generally don't care about most of this in ambient hunting. IF DOES_ENTITY_EXIST(index) AND IS_PED_UNINJURED(PLAYER_PED_ID()) CPRINTLN(DEBUG_MISSION,"ENTITY EXISTS.") IF NOT bIsAmbient CPRINTLN(DEBUG_MISSION,"NON AMBIENT KILL") VECTOR pos = GET_ENTITY_COORDS(index) IF IS_EXPLOSION_IN_SPHERE(EXP_TAG_DONTCARE, pos, 20) CLEAR_PRINTS() bPlayerKillElkIncorrectly = TRUE CPRINTLN(DEBUG_MISSION,"Elk incorrectly killed by explosion") EXIT ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(index, PLAYER_PED_ID()) // Only sniper rifles and knives in Hunting. IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(index, WEAPONTYPE_SNIPERRIFLE) CPRINTLN(DEBUG_MISSION,"Elk damaged by sniper rifle") EXIT ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON(index, WEAPONTYPE_KNIFE) CPRINTLN(DEBUG_MISSION,"Elk damaged by knife") EXIT ENDIF // Anything else is wrong. CPRINTLN(DEBUG_MISSION,"Elk damaged by incorrect weapon!") CLEAR_PRINTS() bPlayerKillElkIncorrectly = TRUE ENDIF ELSE CPRINTLN(DEBUG_MISSION,"AMBIENT KILL") // However, in ambient, we do care if the player kills a doe! IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(index, PLAYER_PED_ID()) CPRINTLN(DEBUG_MISSION,"AMBIENT KILL BY PLAYER") // // If there's a decorator on this elk tagging it as a doe, we're going to fail. // IF DECOR_EXIST_ON(index, "doe_elk") // bKilledDoe = DECOR_GET_BOOL(index, "doe_elk") // ENDIF ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// When the player is outside the snipe area this is called to check if the player shoots from /// outside the area when the shouldnt be /// PARAMS: /// index - the entity to be checking PROC CHECK_FOR_PLAYER_DAMAGE_WHEN_OUTSIDE_SHOOT(ENTITY_INDEX index) IF DOES_ENTITY_EXIST(index) IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(index, PLAYER_PED_ID()) IF NOT IS_ENTITY_DEAD(index) CLEAR_ENTITY_LAST_DAMAGE_ENTITY(index) bPlayerKillElkIncorrectly = TRUE ENDIF ENDIF ENDIF ENDPROC /// PURPOSE: /// Checks to see if an animal spawn would be in front of the player, in a cone. FUNC BOOL WOULD_POINT_BE_IN_FRONT_OF_PLAYER(VECTOR vPoint) VECTOR vFwd = GET_ENTITY_FORWARD_VECTOR(PLAYER_PED_ID()) vFwd.z = 0.0 VECTOR vBetween = vPoint - GET_ENTITY_COORDS(PLAYER_PED_ID()) vBetween = NORMALISE_VECTOR(vBetween) FLOAT fDot = DOT_PRODUCT_XY(vFwd, vBetween) //CPRINTLN(DEBUG_MISSION, "Dot product of point is: ", fDot) IF (fDot > 0.1) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Counts through all the graze points in order. /// Checks if it's safe to spawn an elk there (far enough from player and out of sight) /// Randomly decides if the suitable point can be returned as the elks spawn point /// PARAMS: /// i - /// RETURNS: /// A random int to be used as a spawn point for a new elk FUNC INT GET_SPAWN_POS() INT i = GET_RANDOM_INT_IN_RANGE(0, MAX_GRAZE_AREAS) IF elkSpawn[i].bIsBooked RETURN MAX_GRAZE_AREAS+1 ENDIF IF NOT IS_PED_UNINJURED(PLAYER_PED_ID()) // CWARNINGLN(DEBUG_HUNTING, "GET_SPAWN_POS returning default, NOT IS_PED_UNINJURED(PLAYER_PED_ID())") RETURN MAX_GRAZE_AREAS+1 ENDIF IF IS_SPHERE_VISIBLE(elkSpawn[i].vCoord, 4.0) // CWARNINGLN(DEBUG_HUNTING, "GET_SPAWN_POS returning default, IS_SPHERE_VISIBLE(elkSpawn[i].vCoord, 4.0)") RETURN MAX_GRAZE_AREAS+1 ENDIF VECTOR vCamPos = GET_GAMEPLAY_CAM_COORD() VECTOR vCamRot = GET_GAMEPLAY_CAM_ROT() VECTOR vCamForward = ROTATE_VECTOR_ABOUT_Z( (<<0,1,0>>), vCamRot.z ) VECTOR vCamToCoord = elkSpawn[i].vCoord - vCamPos #IF IS_DEBUG_BUILD DEBUG_RECORD_SPHERE("vCamPos", vCamPos, 0.5, (<<0, 0, 255>>) ) DEBUG_RECORD_LINE("vCamForward", vCamPos, vCamPos + vCamForward, (<<255, 0, 0>>), (<<0, 255, 0>>) ) DEBUG_RECORD_LINE("vCamToCoord", vCamPos, vCamPos + vCamToCoord, (<<255, 0, 0>>), (<<0, 0, 255>>) ) #ENDIF FLOAT fDot = DOT_PRODUCT(vCamForward, vCamToCoord) IF fDot > 0 // CWARNINGLN(DEBUG_HUNTING, "GET_SPAWN_POS returning default, fDot > 0, fDot = ", fDot, " vCamForward = ", vCamForward, " vCamRot = ", vCamRot, " vCamPos = ", vCamPos ) RETURN MAX_GRAZE_AREAS+1 ENDIF VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID()) FLOAT fDist = GET_DISTANCE_BETWEEN_COORDS(vPlayerPos, elkSpawn[i].vCoord) IF fDist > MIN_SAFE_SPAWN_DIST OR IS_SCREEN_FADED_OUT() //CPRINTLN(DEBUG_MISSION,"This pos is NOT visible ", i) RETURN i ENDIF //CPRINTLN(DEBUG_MISSION,"Couldn't find a valid spawn...") RETURN MAX_GRAZE_AREAS+1 ENDFUNC /// PURPOSE: /// /// PARAMS: /// i - /// elkstate - PROC SETUP_ELK(MY_ELK & thisElk, ELK_STATE elkstate, BOOL bBlipFade = TRUE) //CPRINTLN(DEBUG_MISSION,"SET UP ELK...") IF DOES_ENTITY_EXIST(thisElk.mPed) SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(thisElk.mPed, TRUE) SET_PED_COMBAT_ATTRIBUTES(thisElk.mPed, CA_USE_COVER, FALSE) SET_PED_FLEE_ATTRIBUTES(thisElk.mPed, FA_USE_COVER, FALSE) SET_ENTITY_HEALTH(thisElk.mPed, 100) SET_PED_BLOCKS_PATHING_WHEN_DEAD(thisElk.mPed, TRUE) SET_PED_RELATIONSHIP_GROUP_HASH(thisElk.mPed, mElkGroup) SET_RELATIONSHIP_BETWEEN_GROUPS(ACQUAINTANCE_TYPE_PED_HATE, mElkGroup, RELGROUPHASH_PLAYER) SET_PED_SEEING_RANGE(thisElk.mPed, SIGHT_RANGE_DUCKED) SET_PED_HEARING_RANGE(thisElk.mPed, HEAR_RANGE) SET_ENTITY_LOD_DIST(thisElk.mPed, 1500) SET_ENTITY_LOAD_COLLISION_FLAG(thisElk.mPed, TRUE) SET_PED_LOD_MULTIPLIER(thisElk.mPed, 5.0) SET_PED_CAN_BE_TARGETTED(thisElk.mPed, FALSE) thisElk.iNumFollowers = 0 thisElk.bRandomlyCalls = TRUE thisElk.bHardBlipped = FALSE thisElk.bCanFadeBlip = bBlipFade thisElk.bIsSpooked = FALSE //CPRINTLN(DEBUG_MISSION,"Set Up Elk - bIsSpooked = FALSE") IF bIsAmbient AND NOT thisElk.bIsHerdMember elkSpawn[thisElk.iCurNode].bIsBooked = TRUE elkSpawn[thisElk.iCurNode].iNextSpawnTime = GET_GAME_TIMER() + ELK_SPAWN_RESPAWN_DELAY ENDIF //CPRINTLN(DEBUG_MISSION,"Set up Elk - Booking graze node", mElk[i].iCurNode) bUncleanKill = FALSE iElksInPlay++ //CPRINTLN(DEBUG_MISSION,"Set up Elk - iElksInPlay has been incremented = ", iElksInPlay) thisElk.elkState = elkstate ENDIF ENDPROC /// PURPOSE: /// /// PARAMS: /// i - /// RETURNS: /// FUNC BOOL SPAWN_ELK(INT i, ELK_STATE elkstate, BOOL bRandSpawn = TRUE, BOOL bBlipFade = TRUE) IF bRandSpawn AND bIsAmbient INT iSpawn = GET_SPAWN_POS() IF iSpawn > MAX_GRAZE_AREAS RETURN FALSE ELSE // If this spawn point would be more than 150m away, we can't spawn here. IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), elkSpawn[iSpawn].vCoord) > 22500.0 RETURN FALSE ENDIF // If we've spawned too recently, we can't spawn there again. IF GET_GAME_TIMER() < elkSpawn[iSpawn].iNextSpawnTime RETURN FALSE ENDIF //CPRINTLN(DEBUG_MISSION,"Chosen spawn is position ", iSpawn) VECTOR vCoord = GET_RANDOM_POINT_IN_SPHERE(elkSpawn[iSpawn].vCoord, 5.0) GET_GROUND_Z_FOR_3D_COORD(vCoord + (<<0.0,0.5,0.0>>), vCoord.z) mElk[i].vPos = vCoord mElk[i].iCurNode = iSpawn SET_ELK_SPOOKED(i, FALSE) IF bIsAmbient elkSpawn[iSpawn].bIsBooked = TRUE ENDIF ENDIF ENDIF // We'll always pick a random spanw heading. mElk[i].fRandHead = GET_RANDOM_FLOAT_IN_RANGE(0.0, 359.9) // Try and spawn the elk. IF SETUP_PED(mElk[i].mPed, mElk[i].vPos, mElk[i].fRandHead, mElk[i].mModel, FALSE) SETUP_ELK(mElk[i], elkstate, bBlipFade) RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Spawns an addition elk as a member of a static herd. /// PARAMS: /// pedLeadElk - This is the main elk where all the others are placed near. /// i - /// eElkHerdPos - The relative position of the elk. /// elkstate - The state /// bBlipFade - /// bIsStatic - /// RETURNS: /// /// FUNC BOOL SPAWN_ELK_HERD_MEMBER(INT i, INT iLeadElkIndex) IF IS_PED_UNINJURED( mElk[iLeadElkIndex].mPed ) VECTOR vOffset VECTOR vPos = GET_ENTITY_COORDS(mElk[iLeadElkIndex].mPed) FLOAT fHeading = GET_ENTITY_HEADING(mElk[iLeadElkIndex].mPed) SWITCH i // Offset on left flank CASE HERD_MEMBER_LEFT vOffset = << GET_RANDOM_FLOAT_IN_RANGE( -3.0, -2.0 ), GET_RANDOM_FLOAT_IN_RANGE( -2.0, -2.0 ), 0.0 >> BREAK // Offset on right flank CASE HERD_MEMBER_RIGHT vOffset = << GET_RANDOM_FLOAT_IN_RANGE( 3.0, 2.0 ), GET_RANDOM_FLOAT_IN_RANGE( -2.0, -2.0 ), 0.0 >> BREAK // Offset to the front CASE HERD_MEMBER_FRONT vOffset = << GET_RANDOM_FLOAT_IN_RANGE( -2.0, 2.0 ), GET_RANDOM_FLOAT_IN_RANGE( 2.0, 3.0 ), 0.0 >> BREAK // Offset to the rear CASE HERD_MEMBER_REAR vOffset = << GET_RANDOM_FLOAT_IN_RANGE( -2.0, 2.0 ), GET_RANDOM_FLOAT_IN_RANGE( -3.0, -2.0 ), 0.0 >> BREAK ENDSWITCH mElk[i].vPos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vPos, fHeading, vOffset) SNAP_3D_COORD_TO_GROUND(mElk[i].vPos) mElk[i].fRandHead = fHeading + GET_RANDOM_FLOAT_IN_RANGE(-30.0, 30.0) mElk[i].iCurNode = mElk[iLeadElkIndex].iCurNode SET_ELK_SPOOKED(i, FALSE) mElk[i].bIsHerdMember = TRUE mElk[i].iLeaderIdx = iLeadElkIndex // Mark our leader as a leader. mElk[iLeadElkIndex].bIsHerdLeader = TRUE WHILE mElk[i].fRandHead < -180.0 mElk[i].fRandHead += 360.0 ENDWHILE WHILE mElk[i].fRandHead > 180.0 mElk[i].fRandHead -= 360.0 ENDWHILE CPRINTLN( DEBUG_MISSION, "Elk Heading:", mElk[i].fRandHead ) // If the lead elk already has a follower, force a doe elk. BOOL bForceDoe = FALSE IF (mElk[iLeadElkIndex].iNumFollowers != 0) bForceDoe = TRUE ENDIF IF SETUP_PED(mElk[i].mPed, mElk[i].vPos, mElk[i].fRandHead, mElk[i].mModel, FALSE, bForceDoe) SETUP_ELK(mElk[i], ES_GRAZE, TRUE) TASK_FOLLOW_TO_OFFSET_OF_ENTITY(mElk[i].mPed, mElk[iLeadElkIndex].mPed, vOffset, PEDMOVEBLENDRATIO_WALK) RETURN TRUE ENDIF RETURN FALSE ENDIF RETURN FALSE ENDFUNC FUNC HIT_LOCATION GET_HIT_LOCATION_FOR_ELK_BONE_ID(INT iBoneID) SWITCH (iBoneID) CASE 31086 // Head CASE 65079 // AntlerRoot RETURN HL_HEAD BREAK CASE 39317 // Neck1 CASE 24532 // Neck2 RETURN HL_NECK BREAK CASE 45509 // L_UpperArm CASE 40269 // R_UpperArm CASE 24818 // Spine3 CASE 24816 // Spine1 CASE 64729 // L_Clavicle CASE 10706 // R_Clavicle RETURN HL_HEART BREAK CASE 61163 // L_Forearm CASE 26610 // L_Finger00 CASE 4089 // L_Finger01 CASE 18905 // L_Hand CASE 37709 // PH_L_Hand CASE 36029 // IK_L_Hand CASE 28252 // R_Forearm CASE 58866 // R_Finger00 CASE 64016 // R_Finger01 CASE 57005 // R_Hand CASE 7966 // PH_R_Hand CASE 6286 // IK_R_Hand RETURN HL_FORELEG BREAK CASE 63931 // L_Calf CASE 14201 // L_Foot CASE 2108 // L_Toe0 CASE 7531 // L_Toe1 CASE 2718 // PH_L_Foot CASE 65245 // IK_L_Foot CASE 36864 // R_Calf CASE 52301 // R_Foot CASE 20781 // R_Toe0 CASE 45631 // R_Toe1 CASE 38142 // PH_R_Foot CASE 35502 // IK_R_Foot RETURN HL_HINDLEG BREAK CASE 11816 // Pelvis CASE 58271 // L_Thigh CASE 51826 // R_Thigh CASE 839 // Tail_01 CASE 840 // Tail_02 CASE 841 // Tail_03 CASE 842 // Tail_04 CASE 843 // Tail_05 RETURN HL_ASS BREAK CASE 0 // Root CASE 57597 // Spine_Root CASE 23553 // Spine0 CASE 24817 // Spine2 CASE 17916 // PelvisRoot CASE 53251 // Pelvis1 RETURN HL_BODY BREAK ENDSWITCH // We should never get here. All bones were accounted for that were listed in: // x:\gta5\tools\etc\config\anim\skeletons\deer.skel RETURN HL_BODY ENDFUNC // Get the last damaged bonetag and saves that out to the player_hunt_data_struct ehitLocation. // Svaes the screen position of where the x should go PROC RECORD_LAST_HIT_LOCATION(INT iElk) PED_BONETAG ePedBoneTag GET_PED_LAST_DAMAGE_BONE(mElk[iElk].mPed, ePedBoneTag) INT iBoneID = ENUM_TO_INT(ePedBoneTag) HIT_LOCATION hitLoc = GET_HIT_LOCATION_FOR_ELK_BONE_ID(iBoneID) Player_Hunt_Data.iHitsOnLocation[hitLoc]++ IF hitLoc = HL_HEART Player_Hunt_Data.iKillStreakHeartshot++ ELSE Player_Hunt_Data.iKillStreakHeartshot = 0 ENDIF // No matter what, delay the challenge update. Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY ENDPROC PROC SCORE_NOTIFICATION( string sText, INT iScore) TEXT_LABEL_15 txtNotification = "HN_ELK" IF iScore = 1 txtNotification += "_1PT" ENDIF BEGIN_TEXT_COMMAND_THEFEED_POST( txtNotification ) ADD_TEXT_COMPONENT_SUBSTRING_TEXT_LABEL( sText ) ADD_TEXT_COMPONENT_INTEGER( iScore ) END_TEXT_COMMAND_THEFEED_POST_TICKER(FALSE) ENDPROC /// PURPOSE: /// Registers a lootable corpse within the system. PROC ADD_CORPSE_WITH_LOCATION(ENTITY_INDEX entLootable, KILL_TYPE eKillType, WEAPON_TYPE eKillWeapon) // TEMP: Looting can't be done in MP. //IF NETWORK_IS_IN_SESSION() // EXIT //ENDIF IF NOT DOES_ENTITY_EXIST(entLootable) // CERRORLN(DEBUG_LOOTING, "ADD_LOOTABLE_CORPSE - Cannot add invalid entity to the looting system.") EXIT ENDIF IF IS_IN_ITEMSET(entLootable, Player_Hunt_data.setCorpses) // CDEBUG3LN(DEBUG_LOOTING, "ADD_LOOTABLE_CORPSE - Corpse already exists in the lootable set..") EXIT ENDIF // IF NOT GET_ENTITY_LOOTABLE(entLootable) // CDEBUG3LN(DEBUG_LOOTING, "ADD_LOOTABLE_CORPSE - Entity not lootable.") // EXIT // ENDIF DECOR_SET_INT(entLootable, "hunt_score", ENUM_TO_INT(eKillType)) IF Player_Hunt_Data.iKillsSinceSpooked > 0 DECOR_SET_BOOL(entLootable, "hunt_undetected", TRUE) ENDIF IF Player_Hunt_Data.iKillsSinceElkCall > 0 DECOR_SET_BOOL(entLootable, "hunt_nocall", TRUE) ENDIF IF IS_WEAPON_VALID(eKillWeapon) DECOR_SET_INT(entLootable, "hunt_weapon", ENUM_TO_INT(eKillWeapon)) ENDIF // Add decorators so Cletus knows to comment on this one! IF Player_Hunt_Data.challengeData[HC_WEAPONS_MASTER].hcRank = HCR_RANK_2 IF eKillType = KILL_BOAR_KILL AND eKillWeapon = WEAPONTYPE_RUNOVERBYVEHICLE DECOR_SET_INT(entLootable, "hunt_chal_weapon", 2) ENDIF ELIF Player_Hunt_Data.challengeData[HC_WEAPONS_MASTER].hcRank = HCR_RANK_1 IF eKillType = KILL_COYOTE_KILL AND (eKillWeapon = WEAPONTYPE_PUMPSHOTGUN OR eKillWeapon = WEAPONTYPE_SAWNOFFSHOTGUN OR eKillWeapon = WEAPONTYPE_ASSAULTSHOTGUN) DECOR_SET_INT(entLootable, "hunt_chal_weapon", 1) ENDIF ELIF Player_Hunt_Data.challengeData[HC_WEAPONS_MASTER].hcRank = HCR_RANK_3 IF eKillType = KILL_MOUNTAIN_LION_KILL AND (eKillWeapon = WEAPONTYPE_GRENADELAUNCHER OR eKillWeapon = WEAPONTYPE_RPG OR eKillWeapon = WEAPONTYPE_GRENADE) DECOR_SET_INT(entLootable, "hunt_chal_weapon", 3) ENDIF ELIF Player_Hunt_Data.challengeData[HC_WEAPONS_MASTER].hcRank = HCR_RANK_4 IF eKillType < KILL_DOE_KILL AND (eKillWeapon = WEAPONTYPE_SNIPERRIFLE OR eKillWeapon = WEAPONTYPE_HEAVYSNIPER) IF NOT IS_FIRST_PERSON_AIM_CAM_ACTIVE() DECOR_SET_INT(entLootable, "hunt_chal_weapon", 4) ENDIF ENDIF ENDIF // Put that entity within the looting system. // CDEBUG2LN(DEBUG_LOOTING, "ADD_LOOTABLE_CORPSE - Adding a lootable corpse!") DECOR_SET_INT(entLootable, "hunt_kill_time", GET_GAME_TIMER()) IF NOT IS_IN_ITEMSET(entLootable, Player_Hunt_data.setCorpses) ADD_TO_ITEMSET(entLootable, Player_Hunt_data.setCorpses) ENDIF SET_ENTITY_AS_MISSION_ENTITY(entLootable) PED_INDEX pedCorpse = GET_PED_INDEX_FROM_ENTITY_INDEX(entLootable) SET_PED_CONFIG_FLAG(pedCorpse, PCF_RemoveDeadExtraFarAway, TRUE) Player_Hunt_data.bSentPhotoHelp = FALSE // Send a text! Player_Hunt_data.bSentPhotoNearHelp = FALSE // Send a text! Player_Hunt_data.bSentPhotoSendHelp = FALSE // Send a text! // PRINTLN("Added corpse ", NATIVE_TO_INT(entLootable), " at dist ", VDIST(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_ENTITY_COORDS(entLootable))) ENDPROC PROC ADD_CLEAN_KILL_CORPSE(INT i) PED_BONETAG ePedBoneTag GET_PED_LAST_DAMAGE_BONE(mElk[i].mPed, ePedBoneTag) INT iBoneID = ENUM_TO_INT(ePedBoneTag) KILL_TYPE eKillType HIT_LOCATION hitLoc = GET_HIT_LOCATION_FOR_ELK_BONE_ID(iBoneID) SWITCH (hitLoc) CASE HL_HEAD CPRINTLN(DEBUG_MISSION,"Increase score HEAD: ", iBoneID) eKillType = KILL_HEAD_SHOT BREAK CASE HL_NECK CPRINTLN(DEBUG_MISSION,"Increase score NECK: ", iBoneID) eKillType = KILL_NECK_SHOT BREAK CASE HL_HEART CPRINTLN(DEBUG_MISSION,"Increase score HEART: ", iBoneID) eKillType = KILL_HEART_SHOT BREAK CASE HL_HINDLEG CASE HL_FORELEG CPRINTLN(DEBUG_MISSION,"Increase score FRONT LEG: ", iBoneID) eKillType = KILL_LEG_SHOT BREAK CASE HL_ASS CPRINTLN(DEBUG_MISSION,"Increase score REAR: ", iBoneID) eKillType = KILL_ASS_SHOT BREAK CASE HL_BODY CPRINTLN(DEBUG_MISSION,"Increase score TORSO: ", iBoneID) eKillType = KILL_TORSO_SHOT BREAK DEFAULT // We should never get here. All bones were accounted for that were listed in: // x:\gta5\tools\etc\config\anim\skeletons\deer.skel CPRINTLN(DEBUG_MISSION, "================= INCREASE_SCORE - Unknown Bone: ", iBoneID, " =================") eKillType = KILL_TORSO_SHOT BREAK ENDSWITCH IF IS_ELK_A_DOE(mElk[i].mPed) eKillType = KILL_DOE_KILL ENDIF WEAPON_TYPE killWeapon IF NOT GET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), killWeapon) killWeapon = WEAPONTYPE_INVALID ENDIF ADD_CORPSE_WITH_LOCATION(mElk[i].mPed, eKillType, killWeapon) ENDPROC ///// PURPOSE: ///// Makes trevor utter a random line when he kills an elk. //PROC HANDLE_KILL_DIALOGUE() // IF bIsAmbient // IF GET_RANDOM_BOOL() AND (iNextDialogueTime < GET_GAME_TIMER()) // CPRINTLN(DEBUG_MISSION,"HANDLE_KILL_DIALOGUE - Showing Dialoge") // CREATE_CONVERSATION(mTrevConv, sTrevText, "HTAMB_RAND", CONV_PRIORITY_MEDIUM) // // // Sets our next dialogue time to be in the future. // iNextDialogueTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(MIN_DIALOGUE_DELAY_TIME, MAX_DIALOGUE_DELAY_TIME) // ENDIF // ENDIF //ENDPROC PROC CHECK_WEAPONS_MASTER_CHALLENGE_FOR_ANIMAL(HT_PLAYER_DATA &huntingData, ENTITY_INDEX entAnimal) IF huntingData.challengeData[HC_WEAPONS_MASTER].hcStatus != HCS_RANK_UPDATE EXIT ENDIF MODEL_NAMES modelName SWITCH huntingData.challengeData[HC_WEAPONS_MASTER].hcRank CASE HCR_RANK_1 IF GET_ENTITY_MODEL(entAnimal) != A_C_COYOTE EXIT ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_PUMPSHOTGUN) OR HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_SAWNOFFSHOTGUN) OR HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_ASSAULTSHOTGUN) Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY Player_Hunt_Data.bChallengeScreenSetup = FALSE huntingData.challengeData[HC_WEAPONS_MASTER].hcStatus = HCS_RANK_COMPLETE_TOAST ENDIF BREAK CASE HCR_RANK_2 IF GET_ENTITY_MODEL(entAnimal) != A_C_BOAR EXIT ENDIF //PED_INDEX pedAnimal //pedAnimal = GET_PED_INDEX_FROM_ENTITY_INDEX(entAnimal) IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID()) AND HAS_PED_BEEN_DAMAGED_BY_WEAPON(GET_PED_INDEX_FROM_ENTITY_INDEX(entAnimal), WEAPONTYPE_RUNOVERBYVEHICLE) Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY Player_Hunt_Data.bChallengeScreenSetup = FALSE huntingData.challengeData[HC_WEAPONS_MASTER].hcStatus = HCS_RANK_COMPLETE_TOAST ENDIF BREAK CASE HCR_RANK_3 IF GET_ENTITY_MODEL(entAnimal) != A_C_MTLION EXIT ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_GRENADELAUNCHER) OR HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_RPG) OR HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_GRENADE) Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY Player_Hunt_Data.bChallengeScreenSetup = FALSE huntingData.challengeData[HC_WEAPONS_MASTER].hcStatus = HCS_RANK_COMPLETE_TOAST ENDIF BREAK CASE HCR_RANK_4 IF GET_ENTITY_MODEL(entAnimal) != A_C_DEER EXIT ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_SNIPERRIFLE) OR HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_HEAVYSNIPER) IF NOT IS_FIRST_PERSON_AIM_CAM_ACTIVE() AND NOT IS_ELK_A_DOE(entAnimal) Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY Player_Hunt_Data.bChallengeScreenSetup = FALSE huntingData.challengeData[HC_WEAPONS_MASTER].hcStatus = HCS_RANK_COMPLETE_TOAST ENDIF ENDIF BREAK CASE HCR_RANK_5 modelName = GET_ENTITY_MODEL(entAnimal) IF modelName != A_C_CHICKENHAWK AND modelName != A_C_CORMORANT AND modelName != A_C_CROW AND modelName != A_C_PIGEON AND modelName != A_C_SEAGULL EXIT ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_SNIPERRIFLE) OR HAS_ENTITY_BEEN_DAMAGED_BY_WEAPON( entAnimal, WEAPONTYPE_HEAVYSNIPER) Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY Player_Hunt_Data.bChallengeScreenSetup = FALSE huntingData.challengeData[HC_WEAPONS_MASTER].hcStatus = HCS_RANK_COMPLETE_TOAST ENDIF BREAK ENDSWITCH ENDPROC PROC MARK_ELK_KILL_TIME() INT iElkTimeIndex REPEAT COUNT_OF(Player_Hunt_Data.iKillTimes) iElkTimeIndex IF Player_Hunt_Data.iKillTimes[iElkTimeIndex] = 0 Player_Hunt_Data.iKillTimes[iElkTimeIndex] = GET_GAME_TIMER() EXIT ENDIF ENDREPEAT ENDPROC FUNC INT GET_SCORE_FOR_KILL_TYPE(KILL_TYPE eKillType) SWITCH eKillType CASE KILL_HEART_SHOT RETURN SCORE_HEART_SHOT CASE KILL_HEAD_SHOT RETURN SCORE_HEAD_SHOT CASE KILL_NECK_SHOT RETURN SCORE_NECK_SHOT CASE KILL_TORSO_SHOT RETURN SCORE_TORSO_SHOT CASE KILL_ASS_SHOT RETURN SCORE_ASS_SHOT CASE KILL_LEG_SHOT RETURN SCORE_LEG_SHOT CASE KILL_SPOOKED_SHOT RETURN SCORE_SPOOKED_SHOT CASE KILL_ROAD_KILL RETURN SCORE_ROAD_KILL CASE KILL_MOUNTAIN_LION_KILL RETURN SCORE_MOUNTAIN_LION_KILL CASE KILL_BOAR_KILL RETURN SCORE_BOAR_KILL CASE KILL_COYOTE_KILL RETURN SCORE_COYOTE_KILL CASE KILL_BIRD_KILL RETURN SCORE_BIRD_KILL CASE KILL_HUMAN_KILL RETURN SCORE_HUMAN_KILL ENDSWITCH RETURN 0 ENDFUNC FUNC INT GET_MONEY_FOR_KILL_TYPE(KILL_TYPE eKillType) SWITCH eKillType CASE KILL_HEART_SHOT RETURN MONEY_HEART_SHOT CASE KILL_HEAD_SHOT RETURN MONEY_HEAD_SHOT CASE KILL_NECK_SHOT RETURN MONEY_NECK_SHOT CASE KILL_TORSO_SHOT RETURN MONEY_TORSO_SHOT CASE KILL_ASS_SHOT RETURN MONEY_ASS_SHOT CASE KILL_LEG_SHOT RETURN MONEY_LEG_SHOT CASE KILL_SPOOKED_SHOT RETURN MONEY_SPOOKED_SHOT CASE KILL_ROAD_KILL RETURN MONEY_ROAD_KILL CASE KILL_DOE_KILL RETURN MONEY_DOE CASE KILL_MOUNTAIN_LION_KILL RETURN MONEY_MOUNTAIN_LION_KILL CASE KILL_BOAR_KILL RETURN MONEY_BOAR_KILL CASE KILL_COYOTE_KILL RETURN MONEY_COYOTE_KILL CASE KILL_BIRD_KILL RETURN MONEY_BIRD_KILL CASE KILL_HUMAN_KILL RETURN MONEY_HUMAN_KILL ENDSWITCH RETURN 0 ENDFUNC FUNC FLOAT GET_MONEY_MULTIPLIER_FOR_WEAPONGROUP(WEAPON_GROUP eWeaponGroup) SWITCH eWeaponGroup CASE WEAPONGROUP_MELEE RETURN MONEY_MULT_MELEE CASE WEAPONGROUP_PISTOL RETURN MONEY_MULT_PISTOL CASE WEAPONGROUP_SMG RETURN MONEY_MULT_SMG CASE WEAPONGROUP_RIFLE RETURN MONEY_MULT_RIFLE CASE WEAPONGROUP_MG RETURN MONEY_MULT_MG CASE WEAPONGROUP_SHOTGUN RETURN MONEY_MULT_SHOTGUN CASE WEAPONGROUP_SNIPER RETURN MONEY_MULT_SNIPER CASE WEAPONGROUP_HEAVY RETURN MONEY_MULT_HEAVY CASE WEAPONGROUP_THROWN RETURN MONEY_MULT_THROWN ENDSWITCH RETURN MONEY_MULT_MELEE ENDFUNC FUNC STRING GET_NOTIFICATION_FOR_KILL_TYPE(KILL_TYPE eKillType) SWITCH eKillType CASE KILL_HEART_SHOT RETURN "HN_HT" CASE KILL_HEAD_SHOT RETURN "HN_HS" CASE KILL_NECK_SHOT RETURN "HN_NS" CASE KILL_TORSO_SHOT RETURN "HN_TS" CASE KILL_ASS_SHOT RETURN "HN_REAR" CASE KILL_LEG_SHOT RETURN "HN_FL" CASE KILL_SPOOKED_SHOT RETURN "HN_SPK" CASE KILL_ROAD_KILL RETURN "HN_RDK" CASE KILL_DOE_KILL RETURN "HN_DOE" CASE KILL_MOUNTAIN_LION_KILL RETURN "HN_MLK" CASE KILL_BOAR_KILL RETURN "HN_BRK" CASE KILL_COYOTE_KILL RETURN "HN_CYK" CASE KILL_BIRD_KILL RETURN "HN_BDK" CASE KILL_HUMAN_KILL RETURN "HN_HMK" ENDSWITCH RETURN "" ENDFUNC FUNC TEXT_LABEL GET_HUNTING_TEXT_VARIATION(STRING strBase, INT iVariations) TEXT_LABEL retVal = "HTXT_" retVal += strBase IF iVariations != 0 retVal += GET_RANDOM_INT_IN_RANGE(1,iVariations+1) ENDIF RETURN retVal ENDFUNC FUNC TEXT_LABEL GET_TEXT_MESSAGE_FOR_KILL_TYPE(KILL_TYPE eKillType) SWITCH eKillType CASE KILL_HEART_SHOT RETURN GET_HUNTING_TEXT_VARIATION("HT", 5) CASE KILL_HEAD_SHOT RETURN GET_HUNTING_TEXT_VARIATION("HS", 5) CASE KILL_NECK_SHOT RETURN GET_HUNTING_TEXT_VARIATION("NS", 5) CASE KILL_TORSO_SHOT RETURN GET_HUNTING_TEXT_VARIATION("TS", 5) CASE KILL_ASS_SHOT RETURN GET_HUNTING_TEXT_VARIATION("REAR", 5) CASE KILL_LEG_SHOT RETURN GET_HUNTING_TEXT_VARIATION("RL", 5) CASE KILL_SPOOKED_SHOT RETURN GET_HUNTING_TEXT_VARIATION("SPK", 5) CASE KILL_DOE_KILL RETURN GET_HUNTING_TEXT_VARIATION("DOE", 5) CASE KILL_ROAD_KILL RETURN GET_HUNTING_TEXT_VARIATION("RDK", 3) CASE KILL_MOUNTAIN_LION_KILL RETURN GET_HUNTING_TEXT_VARIATION("MLK", 3) CASE KILL_BOAR_KILL RETURN GET_HUNTING_TEXT_VARIATION("BRK", 3) CASE KILL_COYOTE_KILL RETURN GET_HUNTING_TEXT_VARIATION("CYK", 3) CASE KILL_BIRD_KILL RETURN GET_HUNTING_TEXT_VARIATION("BDK", 3) CASE KILL_HUMAN_KILL RETURN GET_HUNTING_TEXT_VARIATION("HMK", 3) CASE KILL_LIVE_ANIMAL RETURN GET_HUNTING_TEXT_VARIATION("LIVE", 3) ENDSWITCH RETURN GET_HUNTING_TEXT_VARIATION("GEN", 0) ENDFUNC FUNC TEXT_LABEL GET_TEXT_MESSAGE_FOR_KILL(ITEM_INDEX itemKillCorpse, KILL_TYPE eKillType, WEAPON_TYPE eKillWeapon) IF DECOR_EXIST_ON(itemKillCorpse, "hunt_chal_weapon") TEXT_LABEL retVal = "HTXT_WCHAL" retVal += DECOR_GET_INT(itemKillCorpse, "hunt_chal_weapon") RETURN retVal ENDIF INT iScoreInc = GET_SCORE_FOR_KILL_TYPE(eKillType) IF iScoreInc < 5 // We have a relatively low score AND NOT Player_Hunt_Data.bSentLowPointPerKillText // And we haven't sent a low point text AND Player_Hunt_Data.iScore < Player_Hunt_Data.iScoreForBronze // We haven't scored a bronze yet AND Player_Hunt_Data.iPhotosSent > 4 // We have sent at least 5 photos AND (Player_Hunt_Data.iScore / Player_Hunt_Data.iPhotosSent) < 4.0 // And our score per photo is low Player_Hunt_Data.bSentLowPointPerKillText = TRUE RETURN GET_HUNTING_TEXT_VARIATION("LOWPPK", 5) ENDIF IF NOT Player_Hunt_Data.bSentNearBronzeText AND Player_Hunt_Data.iScore < Player_Hunt_Data.iScoreForBronze IF Player_Hunt_Data.iScore + iScoreInc < Player_Hunt_Data.iScoreForBronze AND Player_Hunt_Data.iScore + iScoreInc + 5 > Player_Hunt_Data.iScoreForBronze Player_Hunt_Data.bSentNearBronzeText = TRUE RETURN GET_HUNTING_TEXT_VARIATION("NBRONZE", 3) ENDIF ELIF NOT Player_Hunt_Data.bSentNearSilverText AND Player_Hunt_Data.iScore < Player_Hunt_Data.iScoreForSilver IF Player_Hunt_Data.iScore + iScoreInc < Player_Hunt_Data.iScoreForSilver AND Player_Hunt_Data.iScore + iScoreInc + 5 > Player_Hunt_Data.iScoreForSilver Player_Hunt_Data.bSentNearSilverText = TRUE RETURN GET_HUNTING_TEXT_VARIATION("NSILVER", 3) ENDIF ELIF NOT Player_Hunt_Data.bSentNearGoldText AND Player_Hunt_Data.iScore < Player_Hunt_Data.iScoreForGold IF Player_Hunt_Data.iScore + iScoreInc < Player_Hunt_Data.iScoreForGold AND Player_Hunt_Data.iScore + iScoreInc + 5 > Player_Hunt_Data.iScoreForGold Player_Hunt_Data.bSentNearGoldText = TRUE RETURN GET_HUNTING_TEXT_VARIATION("NGOLD", 3) ENDIF ENDIF IF Player_Hunt_Data.iScore < Player_Hunt_Data.iScoreForBronze IF Player_Hunt_Data.iScore + iScoreInc > Player_Hunt_Data.iScoreForBronze RETURN GET_HUNTING_TEXT_VARIATION("BRONZE", 3) ENDIF ELIF Player_Hunt_Data.iScore < Player_Hunt_Data.iScoreForSilver IF Player_Hunt_Data.iScore + iScoreInc > Player_Hunt_Data.iScoreForSilver RETURN GET_HUNTING_TEXT_VARIATION("SILVER", 3) ENDIF ELIF Player_Hunt_Data.iScore < Player_Hunt_Data.iScoreForGold IF Player_Hunt_Data.iScore + iScoreInc > Player_Hunt_Data.iScoreForGold RETURN GET_HUNTING_TEXT_VARIATION("GOLD", 3) ENDIF ENDIF // Doe kills take priority over weapon kills. IF (eKillType = KILL_DOE_KILL) RETURN GET_TEXT_MESSAGE_FOR_KILL_TYPE(eKillType) ENDIF SWITCH eKillWeapon CASE WEAPONTYPE_PISTOL CASE WEAPONTYPE_COMBATPISTOL CASE WEAPONTYPE_APPISTOL CASE WEAPONTYPE_DLC_SNSPISTOL IF Player_Hunt_Data.lastWeaponUsed != WEAPONGROUP_PISTOL Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_PISTOL RETURN GET_HUNTING_TEXT_VARIATION("PISTOL", 3) ENDIF BREAK // Sub machine guns CASE WEAPONTYPE_MICROSMG CASE WEAPONTYPE_SMG IF Player_Hunt_Data.lastWeaponUsed != WEAPONGROUP_SMG Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_SMG RETURN GET_HUNTING_TEXT_VARIATION("SMG", 3) ENDIF BREAK // Assault rifles CASE WEAPONTYPE_ASSAULTRIFLE CASE WEAPONTYPE_CARBINERIFLE CASE WEAPONTYPE_DLC_SPECIALCARBINE CASE WEAPONTYPE_ADVANCEDRIFLE // IF Player_Hunt_Data.lastWeaponUsed != WEAPONGROUP_RIFLE // Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_RIFLE // RETURN GET_HUNTING_TEXT_VARIATION("RIFLE", 3) // ENDIF // BREAK // // // Light machine guns CASE WEAPONTYPE_MG CASE WEAPONTYPE_COMBATMG CASE WEAPONTYPE_MINIGUN IF Player_Hunt_Data.lastWeaponUsed != WEAPONGROUP_MG Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_MG RETURN GET_HUNTING_TEXT_VARIATION("MG", 3) ENDIF BREAK // Shotguns CASE WEAPONTYPE_PUMPSHOTGUN CASE WEAPONTYPE_SAWNOFFSHOTGUN CASE WEAPONTYPE_ASSAULTSHOTGUN IF Player_Hunt_Data.lastWeaponUsed != WEAPONGROUP_SHOTGUN Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_SHOTGUN RETURN GET_HUNTING_TEXT_VARIATION("SHOTGUN", 3) ENDIF BREAK // Heavy weapons CASE WEAPONTYPE_GRENADELAUNCHER CASE WEAPONTYPE_RPG CASE WEAPONTYPE_GRENADE CASE WEAPONTYPE_STICKYBOMB CASE WEAPONTYPE_MOLOTOV IF Player_Hunt_Data.lastWeaponUsed != WEAPONGROUP_HEAVY Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_HEAVY RETURN GET_HUNTING_TEXT_VARIATION("EXPL", 3) ENDIF BREAK // Melee Weapons CASE WEAPONTYPE_UNARMED CASE WEAPONTYPE_BALL CASE WEAPONTYPE_KNIFE CASE WEAPONTYPE_NIGHTSTICK CASE WEAPONTYPE_HAMMER CASE WEAPONTYPE_BAT CASE WEAPONTYPE_CROWBAR CASE WEAPONTYPE_GOLFCLUB CASE WEAPONTYPE_DLC_BOTTLE IF Player_Hunt_Data.lastWeaponUsed != WEAPONGROUP_MELEE Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_MELEE RETURN GET_HUNTING_TEXT_VARIATION("MELEE", 3) ENDIF BREAK DEFAULT Player_Hunt_Data.lastWeaponUsed = WEAPONGROUP_SNIPER BREAK ENDSWITCH RETURN GET_TEXT_MESSAGE_FOR_KILL_TYPE(eKillType) ENDFUNC FUNC TEXT_LABEL GET_TEXT_MESSAGE_FOR_WRONG_CONTACT(enumCharacterList charWrongText) TEXT_LABEL txtTemp SWITCH charWrongText CASE CHAR_MICHAEL IF NOT IS_PLAYER_PED_AVAILABLE(CHAR_MICHAEL) txtTemp = "" CPRINTLN(DEBUG_HUNTING, "GET_TEXT_MESSAGE_FOR_WRONG_CONTACT Michael is unplayable, giving no response.") RETURN txtTemp ENDIF CPRINTLN(DEBUG_HUNTING, "GET_TEXT_MESSAGE_FOR_WRONG_CONTACT Michael is playable, giving a response.") RETURN GET_HUNTING_TEXT_VARIATION("MICHAEL", 3) CASE CHAR_FRANKLIN RETURN GET_HUNTING_TEXT_VARIATION("FRANKLIN", 3) CASE CHAR_RON RETURN GET_HUNTING_TEXT_VARIATION("RON", 0) CASE CHAR_WADE RETURN GET_HUNTING_TEXT_VARIATION("WADE", 0) CASE CHAR_OSCAR RETURN GET_HUNTING_TEXT_VARIATION("OSCAR", 0) CASE CHAR_DEVIN IF NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_FINALE_C2) RETURN GET_HUNTING_TEXT_VARIATION("DEVIN", 0) ELSE txtTemp = "" RETURN txtTemp ENDIF BREAK CASE CHAR_CHENG CASE CHAR_CHENGSR IF NOT GET_MISSION_COMPLETE_STATE(SP_MISSION_FINALE_C2) RETURN GET_HUNTING_TEXT_VARIATION("CHENG", 0) ELSE txtTemp = "" RETURN txtTemp ENDIF BREAK CASE CHAR_JIMMY RETURN GET_HUNTING_TEXT_VARIATION("JIMMY", 0) CASE CHAR_DAVE RETURN GET_HUNTING_TEXT_VARIATION("DAVE", 0) CASE CHAR_LESTER RETURN GET_HUNTING_TEXT_VARIATION("LESTER", 0) CASE CHAR_LAMAR RETURN GET_HUNTING_TEXT_VARIATION("LAMAR", 0) CASE CHAR_PATRICIA RETURN GET_HUNTING_TEXT_VARIATION("PATRICIA", 0) CASE CHAR_MAUDE RETURN GET_HUNTING_TEXT_VARIATION("MAUDE", 0) CASE CHAR_CASTRO RETURN GET_HUNTING_TEXT_VARIATION("CASTRO", 0) CASE CHAR_GAYMILITARY RETURN GET_HUNTING_TEXT_VARIATION("GAYMILIT", 0) CASE CHAR_HITCHER_GIRL RETURN GET_HUNTING_TEXT_VARIATION("HITCHGRL", 0) CASE CHAR_BARRY RETURN GET_HUNTING_TEXT_VARIATION("BARRY", 0) CASE CHAR_JOE RETURN GET_HUNTING_TEXT_VARIATION("JOE", 0) CASE CHAR_JOSEF RETURN GET_HUNTING_TEXT_VARIATION("JOSEF", 0) CASE CHAR_JOSH RETURN GET_HUNTING_TEXT_VARIATION("JOSH", 0) CASE CHAR_NIGEL RETURN GET_HUNTING_TEXT_VARIATION("NIGEL", 0) CASE CHAR_ONEIL // Between Chinese 2 and Exile 2, the palyer has killed ONeil's family, and then ONeil. // He probably should respond during this time. IF GET_MISSION_COMPLETE_STATE(SP_MISSION_CHINESE_2) txtTemp = "" RETURN txtTemp ENDIF RETURN GET_HUNTING_TEXT_VARIATION("ONEIL", 0) BREAK ENDSWITCH RETURN GET_HUNTING_TEXT_VARIATION("RANDOM_", 3) ENDFUNC FUNC STRING GET_TEXT_MESSAGE_FOR_PHOTO_RANK(HUNTING_CHALLENGE_RANK hrRank) SWITCH hrRank CASE HCR_RANK_1 RETURN "HTXT_PCHAL1" CASE HCR_RANK_2 RETURN "HTXT_PCHAL2" CASE HCR_RANK_3 RETURN "HTXT_PCHAL3" CASE HCR_RANK_4 RETURN "HTXT_PCHAL4" CASE HCR_RANK_5 RETURN "HTXT_PCHAL5" ENDSWITCH RETURN "HTXT_PHOTO_1" ENDFUNC FUNC INT DO_CORPSE_PAYMENT(ENTITY_INDEX entCorpse) IF NOT IS_ENTITY_DEAD(entCorpse) // Don't give scores for live animals - they are just here for photo challenge RETURN 0 ENDIF IF NOT DECOR_EXIST_ON(entCorpse, "hunt_score") RETURN 0 ENDIF KILL_TYPE eKillType = INT_TO_ENUM(KILL_TYPE, DECOR_GET_INT(entCorpse, "hunt_score")) INT iMoney = GET_MONEY_FOR_KILL_TYPE(eKillType) FLOAT fMoneyMultiplierForWeapon IF DECOR_EXIST_ON(entCorpse, "hunt_weapon") fMoneyMultiplierForWeapon = GET_MONEY_MULTIPLIER_FOR_WEAPONGROUP(GET_WEAPONTYPE_GROUP(INT_TO_ENUM(WEAPON_TYPE, DECOR_GET_INT(entCorpse, "hunt_weapon")))) ELSE fMoneyMultiplierForWeapon = GET_MONEY_MULTIPLIER_FOR_WEAPONGROUP(WEAPONGROUP_INVALID) ENDIF iMoney = ROUND(TO_FLOAT(iMoney) * fMoneyMultiplierForWeapon) Player_Hunt_Data.iMoney += iMoney CPRINTLN(DEBUG_MISSION, "Payment - ", GET_DISPLAY_NAME_FOR_KILL_TYPE(entCorpse, eKillType),": $", iMoney) RETURN iMoney ENDFUNC PROC DO_CORPSE_SCORING(ENTITY_INDEX entCorpse) IF NOT IS_ENTITY_DEAD(entCorpse) // Don't give scores for live animals - they are just here for photo challenge EXIT ENDIF IF NOT DECOR_EXIST_ON(entCorpse, "hunt_score") EXIT ENDIF KILL_TYPE eKillType = INT_TO_ENUM(KILL_TYPE, DECOR_GET_INT(entCorpse, "hunt_score")) INT iScore = GET_SCORE_FOR_KILL_TYPE(eKillType) Player_Hunt_Data.iScore += iScore CPRINTLN(DEBUG_MISSION, "Scoring - ", GET_DISPLAY_NAME_FOR_KILL_TYPE(entCorpse, eKillType),": ", iScore, " Points") SCORE_NOTIFICATION( GET_NOTIFICATION_FOR_KILL_TYPE(eKillType), iScore) ENDPROC PROC DO_CHALLENGE_RANK_SCORING(HUNTING_CHALLENGE_RANK hrRank) INT iScore SWITCH hrRank CASE HCR_RANK_1 iScore = 5 BREAK CASE HCR_RANK_2 iScore = 10 BREAK CASE HCR_RANK_3 iScore = 15 BREAK CASE HCR_RANK_4 iScore = 20 BREAK CASE HCR_RANK_5 iScore = 25 BREAK ENDSWITCH IF iScore > 0 Player_Hunt_Data.iScore += iScore SCORE_NOTIFICATION( "HN_RANK", iScore ) ENDIF ENDPROC /// PURPOSE: /// Checks if the player has just killed an elk. /// Increments the kill counter and records where the elk was shot. /// PARAMS: /// i - the individual elk to check PROC HAS_PLAYER_KILLED_ELK(INT i) IF DOES_ENTITY_EXIST(mElk[i].mPed) // Blah debug kill cheat... // IF IS_CONTROL_JUST_RELEASED(PLAYER_CONTROL, INPUT_FRONTEND_RB) // Player_Hunt_Data.iScore++ // ENDIF IF NOT IS_ELK_OK(i) bSuppressNearMissMessage = TRUE WEAPON_TYPE killWeapon IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("AHT_MISS") CLEAR_HELP() ENDIF IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mElk[i].mPed, PLAYER_PED_ID()) CPRINTLN(DEBUG_MISSION, "Elk just harmed by player!") IF HAS_PED_BEEN_DAMAGED_BY_WEAPON(mElk[i].mPed, WEAPONTYPE_RUNOVERBYVEHICLE) CPRINTLN(DEBUG_MISSION, "Player used a vehicle...") ADD_CORPSE_WITH_LOCATION(mElk[i].mPed, KILL_ROAD_KILL, WEAPONTYPE_RUNOVERBYVEHICLE) IF NOT IS_ELK_A_DOE(mElk[i].mPed) Player_Hunt_Data.iKillCount += 1 MARK_ELK_KILL_TIME() ENDIF IF IS_ENTITY_ALIVE(mElk[i].mPed) CLEAR_ENTITY_LAST_DAMAGE_ENTITY(mElk[i].mPed) ENDIF EXIT ENDIF CHECK_WEAPONS_MASTER_CHALLENGE_FOR_ANIMAL(Player_Hunt_Data, mElk[i].mPed) // See how it was killed, then clear that. CHECK_TARGET_DAMAGED_BY_RIFLE(mElk[i].mPed) CLEAR_ENTITY_LAST_DAMAGE_ENTITY(mElk[i].mPed) TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) IF mElk[i].bIsSpooked CPRINTLN(DEBUG_MISSION, "Killed elk had already been spooked.") // In ambient mode, killing doe doesn't count. IF bIsAmbient IF NOT IS_ELK_A_DOE(mElk[i].mPed) Player_Hunt_Data.iKillCount += 1 IF GET_GAME_TIMER() > iWhistleCallTime + 30000 Player_Hunt_Data.iKillsSinceElkCall += 1 ENDIF Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY IF NOT GET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), killWeapon) killWeapon = WEAPONTYPE_INVALID ENDIF IF Player_Hunt_Data.iScore < 0 Player_Hunt_Data.iScore = 0 ENDIF MARK_ELK_KILL_TIME() ENDIF IF IS_ELK_A_DOE(mElk[i].mPed) ADD_CORPSE_WITH_LOCATION(mElk[i].mPed, KILL_DOE_KILL, killWeapon) ELSE ADD_CORPSE_WITH_LOCATION(mElk[i].mPed, KILL_SPOOKED_SHOT, killWeapon) ENDIF ENDIF ELSE CPRINTLN(DEBUG_MISSION, "Elk was killed cleanly.") IF NOT bGotNearMissTime iMissMessageDelay = GET_GAME_TIMER() + MISS_MESSAGE_DELAY_TIME bSuppressNearMissMessage = TRUE bGotNearMissTime = TRUE ENDIF // In ambient mode, killing a doe doesn't count. IF bIsAmbient //AND NOT IS_ELK_A_DOE(mElk[i].mPed) IF NOT IS_ELK_A_DOE(mElk[i].mPed) IF bIsAmbient CPRINTLN(DEBUG_MISSION, "Recording hit location in slot: ", Player_Hunt_Data.iKillCount) RECORD_LAST_HIT_LOCATION(i) ENDIF // Increment all counters. Player_Hunt_Data.iKillCount += 1 Player_Hunt_Data.iKillsSinceSpooked += 1 IF GET_GAME_TIMER() > iWhistleCallTime + 30000 Player_Hunt_Data.iKillsSinceElkCall += 1 ENDIF MARK_ELK_KILL_TIME() ENDIF Player_Hunt_Data.iChallengeDisplayTime = GET_GAME_TIMER() + CHALLENGE_DISPLAY_DELAY ADD_CLEAN_KILL_CORPSE(i) ENDIF IF Player_Hunt_Data.iScore > 0 #IF IS_DEBUG_BUILD PRINTLN("KILLCOUNT/SCORE = ", Player_Hunt_Data.iScore) #ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDPROC INT iTooFarTimer /// PURPOSE: /// /// RETURNS: /// FUNC BOOL IS_ANY_VISIBLE_ELK_IN_RANGE() //CPRINTLN(DEBUG_MISSION,"CHECKING IF ANY ELK IS IN RANGE OF THE PLAYER") INT i, iNumInRange = 0 REPEAT MAX_ELKS i IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) IF IS_ELK_OK(i) IF IS_ENTITY_IN_RANGE_ENTITY(PLAYER_PED_ID(), mElk[i].mPed, CLOSE_KILL_RANGE) IF IS_ENTITY_ON_SCREEN(mElk[i].mPed) AND NOT WOULD_ENTITY_BE_OCCLUDED(mElk[i].mModel, GET_ENTITY_COORDS(mElk[i].mPed, FALSE)) AND NOT mElk[i].bIsSpooked iNumInRange++ ENDIF ELSE //CPRINTLN(DEBUG_MISSION,"THIS ELK IS TOO FAR: ", i) IF IS_PLAYER_FREE_AIMING_AT_ENTITY(PLAYER_ID(), mElk[i].mPed) AND NOT mElk[i].bIsSpooked //CPRINTLN(DEBUG_MISSION,"TEH PLAYER IS AIMING AT ELK: ", i) IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("AHT_TOFAR") iTooFarTimer = GET_GAME_TIMER() + 3000 //PRINT_HELP("AHT_TOFAR") ENDIF ELSE IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("AHT_TOFAR") IF GET_GAME_TIMER() > iTooFarTimer OR mElk[i].bIsSpooked CLEAR_HELP() ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDREPEAT IF iNumInRange > 0 RETURN TRUE ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Checks if the player is within CLOSE_KILL_RANGE of the Elk he is aiming at and prints help /// to the screen to let the player know he can make a close kill. PROC CHECK_PLAYER_IN_RANGE() IF IS_ANY_VISIBLE_ELK_IN_RANGE() IF NOT IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("AHT_RANGE") PRINT_HELP("AHT_RANGE") ENDIF ELSE IF IS_THIS_HELP_MESSAGE_BEING_DISPLAYED("AHT_RANGE") CLEAR_HELP() ENDIF ENDIF ENDPROC /// PURPOSE: /// Checks if any elk is spooked /// RETURNS: /// TRUE if the player has spooked an elk FUNC BOOL IS_ANY_ELK_SPOOKED() INT i REPEAT MAX_ELKS i IF IS_ELK_OK(i) IF mElk[i].bIsSpooked //AND NOT mElk[i].bGotNearMissTime //CPRINTLN(DEBUG_MISSION, "IS_ANY_ELK_SPOOKED return true - ", i) RETURN TRUE ELSE //CPRINTLN(DEBUG_MISSION, "IS_ANY_ELK_SPOOKED returns false - ", i) ENDIF ENDIF ENDREPEAT RETURN FALSE ENDFUNC PROC SPAWN_HERD_MEMBERS(INT iHerdLeaderIndex) // Track how many are in the herd, as there's a max. We start at 1, because being here means there's a leader. INT iSpawnedInHerd = 1 INT i = HERD_MEMBER_INDEX_START WHILE (i < MAX_ELKS) AND (iSpawnedInHerd < MAX_ELK_PER_HERD) IF NOT IS_ELK_OK(i) IF GET_RANDOM_INT_IN_RANGE(0, 100) < PERCENTAGE_HERD_MEMBER_CHANCE SPAWN_ELK_HERD_MEMBER(i, iHerdLeaderIndex) iSpawnedInHerd += 1 mElk[iHerdLeaderIndex].iNumFollowers += 1 ENDIF ENDIF ++i ENDWHILE ENDPROC /// PURPOSE: /// Resets the timer on all elk calls. PROC RESET_ALL_ELK_CALLS() INT idx REPEAT MAX_ELKS idx mElk[idx].iCallTime = GET_GAME_TIMER() ENDREPEAT iBleatInitiateTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(BLEAT_TRIGGER_MIN_DELAY, BLEAT_TRIGGER_MAX_DELAY) ENDPROC /// PURPOSE: /// Handles the elk calling to each other randomly, as well as responding to player. /// Only happens if the elk is not spooked. PROC MANAGE_ELK_CALLS(INT iElkIdx) // Don't call if the elk isn't alive. IF NOT IS_ELK_OK(iElkIdx) EXIT ENDIF IF NOT mElk[iElkIdx].bRandomlyCalls EXIT ENDIF IF mElk[iElkIdx].bIsSpooked EXIT ENDIF IF bPlayerCalling AND iCallEndTime + BLEAT_RESPONSE_DELAY + 5000 < GET_GAME_TIMER() AND mElk[iElkIdx].iCallTime < GET_GAME_TIMER() // Okay, so the player has called... Select a few elk to respond. bPlayerCalling = FALSE // Determine if this elk responds. //IF GET_RANDOM_INT_IN_RANGE(0, 100) < 90 mElk[iElkIdx].iCallTime = GET_GAME_TIMER() mElk[iElkIdx].bCalling = TRUE PLAY_SOUND_FROM_ENTITY(-1, "ELK_BREY_MASTER", mElk[iElkIdx].mPed) CPRINTLN(DEBUG_MISSION, "Elk replying to call: ", iElkIdx) iInitiatorIndex = -1 // Don't trigger random bleats for a bit iBleatInitiateTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(BLEAT_TRIGGER_MIN_DELAY, BLEAT_TRIGGER_MAX_DELAY) //ENDIF ENDIF // Okay, make sure that it's not time for a random bleat. IF (iBleatInitiateTime != -1) AND iBleatInitiateTime < GET_GAME_TIMER() // This guy will be our initiator. mElk[iElkIdx].bCalling = TRUE PLAY_SOUND_FROM_ENTITY(-1, "ELK_BREY_MASTER", mElk[iElkIdx].mPed) CPRINTLN(DEBUG_MISSION, "Elk Brey Initiate!") iBleatResponseTime = GET_GAME_TIMER() + BLEAT_RESPONSE_DELAY iInitiatorIndex = iElkIdx iBleatInitiateTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(BLEAT_TRIGGER_MIN_DELAY, BLEAT_TRIGGER_MAX_DELAY) ELIF (iInitiatorIndex != -1) AND (iBleatResponseTime < GET_GAME_TIMER()) AND (iBleatResponseTime != -1) IF (iElkIdx != iInitiatorIndex) //// 90% chance an elk is going to respond. //IF GET_RANDOM_INT_IN_RANGE(0, 100) < 90 mElk[iElkIdx].iCallTime = GET_GAME_TIMER() mElk[iElkIdx].bCalling = TRUE PLAY_SOUND_FROM_ENTITY(-1, "ELK_BREY_MASTER", mElk[iElkIdx].mPed) iBleatResponseTime = GET_GAME_TIMER() + BLEAT_RESPONSE_DELAY //ENDIF ENDIF bRandomBleat = TRUE ENDIF ENDPROC /// PURPOSE: /// Removes any other blip on a spooked animal, and adds aa fleeing blip. PROC SETUP_ELK_SPOOKED_BLIP(MY_ELK & thisElk) IF DOES_BLIP_EXIST(thisElk.mElkBlip) CPRINTLN(DEBUG_MISSION, "Removing previous elk blip before adding spooked blip.") REMOVE_BLIP(thisElk.mElkBlip) ENDIF IF NOT thisElk.bBlockSpookedBlip CPRINTLN(DEBUG_MISSION, "Adding an elk spooked blip!") ADD_SAFE_BLIP_TO_PED(thisElk.mElkBlip, thisElk.mPed, TRUE, BLIP_SIZE_PED) SET_BLIP_ALPHA(thisElk.mElkBlip, 128) SET_BLIP_SHOW_CONE(thisElk.mElkBlip, TRUE) ENDIF thisElk.bIsSpooked = TRUE ENDPROC /// PURPOSE: /// Lets you disable a spooked blip on an elk. PROC SET_ELK_SPOOKED_BLIP_ENABLED(MY_ELK & thisElk, BOOL bSpookedBlipEnabled = TRUE) thisElk.bBlockSpookedBlip = !bSpookedBlipEnabled ENDPROC // ==================== // ELK STATES // ==================== /// PURPOSE: /// The state machine for the elk /// PARAMS: /// i - the index of the elk to be processed. PROC CHECK_ELK_STATES(INT i) IF mElk[i].bIsSpooked //CPRINTLN(DEBUG_MISSION, "Checking at top of elk state machine - THIS ELK IS SPOOKED ", i) IF DOES_ENTITY_EXIST(mElk[i].mPed) AND IS_ENTITY_DEAD(mElk[i].mPed) IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(mElk[i].mPed, PLAYER_PED_ID()) bUncleanKill = TRUE ENDIF ENDIF ELSE CHECK_ELK_SPOOKED(i) MANAGE_ELK_CALLS(i) // Don't want to tweak the blips if the elk is spooked. MANAGE_ELK_BLIP(mElk[i], i) // Cleanup far away elk. IF bIsAmbient FLOAT fDistance = 9999.9 IF DOES_ENTITY_EXIST(mElk[i].mPed) IF NOT IS_PED_INJURED(mElk[i].mPed) IF NOT IS_PED_INJURED(PLAYER_PED_ID()) VECTOR vElkPos = GET_ENTITY_COORDS(mElk[i].mPed) fDistance = GET_DISTANCE_BETWEEN_COORDS(vHuntingPlayerCoords, vElkPos) IF fDistance > ELK_CLEANUP_DISTANCE IF NOT IS_SPHERE_VISIBLE(vElkPos, 2.0) OR IS_SCREEN_FADED_OUT() mElk[i].elkState = ES_CLEAN_UP ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF ENDIF // Herd members just wait for the leader to do something new. IF (mElk[i].bIsHerdMember) mElk[i].elkState = mElk[mElk[i].iLeaderIdx].elkState EXIT ENDIF SWITCH mElk[i].elkState // HOLDING AREA CASE ES_NULL // DO NOTHING BREAK CASE ES_CHECK_CAN_SPAWN IF bIsAmbient //CPRINTLN(DEBUG_MISSION,"ES_CHECK_CAN_SPAWN - Elks In Play is ", iElksInPlay) IF iElksInPlay < MAX_ELKS AND NOT bIsPlayerOutsideHuntArea // First elk can spawn without a delay IF NOT mElk[i].bDelayBeforeRespawn CPRINTLN(DEBUG_MISSION,"ES_CHECK_CAN_SPAWN - SPAWNING IN") mElk[i].elkState = ES_SPAWN_IN // need to wait for any delayed spooked messages/flags to be sorted out before repsawn ELIF GET_GAME_TIMER() > mElk[i].iSpawnDelayTime //CPRINTLN(DEBUG_MISSION,"ES_CHECK_CAN_SPAWN AFTER DELAY - SPAWNING IN") mElk[i].elkState = ES_SPAWN_IN ENDIF ENDIF ENDIF BREAK // CREATES AN ELK IN A VACANT GRAZE AREA. SETS A RANDOM HEADING. BLIPS THE ELK WITH A TRANSPARENT BLIP. CASE ES_SPAWN_IN IF SPAWN_ELK(i, ES_PAUSE_THEN_GRAZE) //CPRINTLN(DEBUG_MISSION,"ES_SPAWN_IN - Elks In Play is now: ", iElksInPlay) // Only male elk can be herd leaders. IF bIsAmbient AND NOT IS_ELK_A_DOE(mElk[i].mPed) // If no herd is active, try to spawn a herd around the elk, and set it to static behaviour IF NOT IS_ANY_ELK_A_HERD_MEMBER() IF GET_RANDOM_INT_IN_RANGE(0, 100) < PERCENTAGE_HERD_CHANCE mElk[i].elkState = ES_START_GRAZE SPAWN_HERD_MEMBERS(i) ENDIF ENDIF ENDIF ENDIF BREAK CASE ES_START_GRAZE // This elk is to graze. Start the anim and figure out how long to graze for. IF NOT mElk[i].bIsSpooked INT iRand iRand = GET_RANDOM_INT_IN_RANGE() % 3 SEQUENCE_INDEX Seq OPEN_SEQUENCE_TASK(Seq) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@enter", "enter") IF (iRand = 0) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@idle_a", "idle_a", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING) ELIF (iRand = 1) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@idle_a", "idle_b", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING) ELSE TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@idle_a", "idle_c", NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1, AF_LOOPING) ENDIF CLOSE_SEQUENCE_TASK(Seq) TASK_PERFORM_SEQUENCE(mElk[i].mPed, Seq) CLEAR_SEQUENCE_TASK(Seq) mElk[i].iWaitTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(MIN_ELK_GRAZE_TIME, MAX_ELK_GRAZE_TIME) mElk[i].elkState = ES_GRAZE ELSE CPRINTLN(DEBUG_MISSION,"Elk spooked from Graze state") mElk[i].elkState = ES_RUN_OFF ENDIF BREAK CASE ES_GRAZE // Here, the elk is grazing. IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked VECTOR vElkPos vElkPos = GET_ENTITY_COORDS(mElk[i].mPed) IF GET_GAME_TIMER() > mElk[i].iWaitTime AND WOULD_POINT_BE_IN_FRONT_OF_PLAYER(vElkPos) AND VDIST2(vElkPos, GET_ENTITY_COORDS(PLAYER_PED_ID())) < 10000.0 // Time to move on. SEQUENCE_INDEX Seq OPEN_SEQUENCE_TASK(Seq) IF (GET_SCRIPT_TASK_STATUS(mElk[i].mPed, SCRIPT_TASK_PERFORM_SEQUENCE) = PERFORMING_TASK) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@exit", "exit", SLOW_BLEND_IN) ENDIF TASK_LOOK_AT_ENTITY(NULL, PLAYER_PED_ID(), 4200) CLOSE_SEQUENCE_TASK(Seq) TASK_PERFORM_SEQUENCE(mElk[i].mPed, Seq) CLEAR_SEQUENCE_TASK(Seq) // Pause, then move mElk[i].iWaitTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(MIN_ELK_WAIT_TIME, MAX_ELK_WAIT_TIME) mElk[i].elkState = ES_PAUSE_THEN_PICK_NEW_DESTINATION ENDIF ELSE // Elk is spooked, clean. mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_PAUSE_THEN_PICK_NEW_DESTINATION // Okay, we're waiting for a set time, then we'll go to a new destination. IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked IF GET_GAME_TIMER() > mElk[i].iWaitTime // Pick a new destination and go there. mElk[i].elkState = ES_CHOOSE_NEXT_DESTINATION ENDIF ELSE // Elk is spooked, run. mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_CHOOSE_NEXT_DESTINATION IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked // Get a random node, and go to it. iRandGraze = GET_RANDOM_INT_IN_RANGE(0, MAX_GRAZE_AREAS) IF IS_NODE_OK_FOR_THIS_ELK(i, iRandGraze) mElk[i].iDestNode = iRandGraze ELSE mElk[i].iDestNode = FIND_BEST_CLOSEST_NODE(i) ENDIF elkSpawn[mElk[i].iCurNode].bIsBooked = FALSE IF bIsAmbient elkSpawn[mElk[i].iDestNode].bIsBooked = TRUE ENDIF TASK_FOLLOW_NAV_MESH_TO_COORD(mElk[i].mPed, elkSpawn[mElk[i].iDestNode].vCoord, PEDMOVEBLENDRATIO_WALK, DEFAULT_TIME_NEVER_WARP, DEFAULT, ENAV_DEFAULT) mElk[i].iPrevNode = mElk[i].iCurNode // Go to that destination. mElk[i].elkState = ES_TRAVEL_TO_NEXT_DESTINATION ELSE // Spooked, run. mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_TRAVEL_TO_NEXT_DESTINATION //CPRINTLN(DEBUG_MISSION,"ES_GO_TO_NEXT_DESTINATION") IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked IF IS_ENTITY_AT_COORD(mElk[i].mPed, elkSpawn[mElk[i].iDestNode].vCoord, <<3.0, 3.0, 3.0>>, FALSE, FALSE, TM_ANY) mElk[i].iCurNode = mElk[i].iDestNode CLEAR_PED_TASKS(mElk[i].mPed) mElk[i].iWaitTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(MIN_ELK_WAIT_TIME, MAX_ELK_WAIT_TIME) mElk[i].elkState = ES_PAUSE_THEN_GRAZE ENDIF ELSE //CPRINTLN(DEBUG_MISSION,"ES - SPOOKED - RUN OFF") mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_TRAVEL_THEN_ENTER_GRAZE_AND_WAIT_TO_DIE IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked IF IS_ENTITY_AT_COORD(mElk[i].mPed, elkSpawn[mElk[i].iDestNode].vCoord, <<3.0, 3.0, 3.0>>, FALSE, FALSE, TM_ANY) mElk[i].iCurNode = mElk[i].iDestNode CLEAR_PED_TASKS(mElk[i].mPed) mElk[i].iWaitTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(MIN_ELK_WAIT_TIME, MAX_ELK_WAIT_TIME) mElk[i].elkState = ES_ENTER_GRAZE_AND_WAIT_TO_DIE ENDIF ELSE //CPRINTLN(DEBUG_MISSION,"ES - SPOOKED - RUN OFF") mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_PAUSE_THEN_GRAZE // Okay, we're waiting for a set time, then we'll go to a new destination. IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked IF GET_GAME_TIMER() > mElk[i].iWaitTime // Need to graze. mElk[i].elkState = ES_START_GRAZE ENDIF ELSE // Elk is spooked, run. mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_RUN_OFF //CPRINTLN(DEBUG_MISSION,"[ES] ES_RUN_OFF") IF bIsPlayerOutsideHuntArea CPRINTLN(DEBUG_MISSION, "Elk running away and player isn't in hunting area. Kill blip.") SAFE_REMOVE_BLIP(mElk[i].mElkBlip) ENDIF IF IS_ELK_OK(i) CPRINTLN(DEBUG_MISSION, "ES_RUN_OFF -> Setting up run off.") SETUP_ELK_SPOOKED_BLIP(mElk[i]) CLEAR_PED_TASKS(mElk[i].mPed) TASK_SMART_FLEE_PED(mElk[i].mPed, PLAYER_PED_ID(), 500.0, -1, FALSE) SET_PED_KEEP_TASK(mElk[i].mPed, TRUE) //CPRINTLN(DEBUG_MISSION,"ES - RUNNING OFF") mElk[i].elkState = ES_RUNNING_OFF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_ENTER_GRAZE_AND_WAIT_TO_DIE IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked IF GET_SCRIPT_TASK_STATUS(mElk[i].mPed, SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK OR GET_SCRIPT_TASK_STATUS(mElk[i].mPed, SCRIPT_TASK_PERFORM_SEQUENCE) != PERFORMING_TASK SEQUENCE_INDEX mEnterSeq OPEN_SEQUENCE_TASK(mEnterSeq) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@enter", "enter", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@base", "base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) IF GET_RANDOM_BOOL() TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@idle_a", "idle_b", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@base", "base") ENDIF IF GET_RANDOM_BOOL() TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@idle_a", "idle_a", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) ELSE TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@idle_a", "idle_c", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) ENDIF TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@base", "base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@exit", "exit", NORMAL_BLEND_IN, SLOW_BLEND_OUT) CLOSE_SEQUENCE_TASK(mEnterSeq) TASK_PERFORM_SEQUENCE(mElk[i].mPed, mEnterSeq) CLEAR_SEQUENCE_TASK(mEnterSeq) mElk[i].iGrazeTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(10000, 15000) mElk[i].elkState = ES_GRAZE_AND_WAIT_TO_DIE ENDIF ELSE mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) // Elk is dead mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_GRAZE_AND_WAIT_TO_DIE IF IS_ELK_OK(i) IF NOT mElk[i].bIsSpooked IF GET_SCRIPT_TASK_STATUS(mElk[i].mPed, SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK OR GET_SCRIPT_TASK_STATUS(mElk[i].mPed, SCRIPT_TASK_PERFORM_SEQUENCE) <> PERFORMING_TASK IF GET_GAME_TIMER() > mElk[i].iGrazeTime SEQUENCE_INDEX mExitSeq OPEN_SEQUENCE_TASK(mExitSeq) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@enter", "enter", FAST_BLEND_IN, NORMAL_BLEND_OUT) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@base", "base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) IF GET_RANDOM_BOOL() TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@base", "base", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@idle_a", "idle_b", NORMAL_BLEND_IN, NORMAL_BLEND_OUT) ENDIF TASK_PLAY_ANIM(NULL, "creatures@deer@amb@world_deer_grazing@exit", "exit", NORMAL_BLEND_IN, SLOW_BLEND_OUT) CLOSE_SEQUENCE_TASK(mExitSeq) TASK_PERFORM_SEQUENCE(mElk[i].mPed, mExitSeq) CLEAR_SEQUENCE_TASK(mExitSeq) mElk[i].elkState = ES_ENTER_GRAZE_AND_WAIT_TO_DIE ENDIF ENDIF ELSE mElk[i].elkState = ES_RUN_OFF ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) // Elk is dead mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK // CHECKS IF THE ELK IS OFF-SCREEN... CASE ES_RUNNING_OFF IF IS_ELK_OK(i) AND IS_PED_UNINJURED(PLAYER_PED_ID()) FLOAT fDist VECTOR vElkPos vElkPos = GET_ENTITY_COORDS(mElk[i].mPed, FALSE) fDist = GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(PLAYER_PED_ID(), FALSE), vElkPos) IF (fDist > 70.0) AND NOT IS_SPHERE_VISIBLE(vElkPos, 5.0) mElk[i].elkState = ES_CLEAN_UP ENDIF ELSE //TRIGGER_HUNTING_AUDIO("HUNTING_KILL", TRUE) PLAY_SOUND_FROM_ENTITY(-1, "ELK_PAIN_MASTER", mElk[i].mPed) mElk[i].elkState = ES_CLEAN_UP ENDIF BREAK CASE ES_CLEAN_UP //CPRINTLN(DEBUG_MISSION,"ES - CLEANING UP") CPRINTLN(DEBUG_MISSION, "Cleanup elk. Remove blip.") SAFE_REMOVE_BLIP(mElk[i].mElkBlip) // This node is not booked. elkSpawn[mElk[i].iCurNode].bIsBooked = FALSE elkSpawn[mElk[i].iDestNode].bIsBooked = FALSE // Don't let either the dest node or the cur node respawn for a while. elkSpawn[mElk[i].iCurNode].iNextSpawnTime = GET_GAME_TIMER() + ELK_SPAWN_RESPAWN_DELAY elkSpawn[mElk[i].iDestNode].iNextSpawnTime = GET_GAME_TIMER() + ELK_SPAWN_RESPAWN_DELAY IF DOES_ENTITY_EXIST(mElk[i].mPed) // If a doe, decrement the number in play. IF DECOR_EXIST_ON(mElk[i].mPed, "doe_elk") iDoeInPlay -= 1 ENDIF SET_PED_AS_NO_LONGER_NEEDED(mElk[i].mPed) ENDIF IF (iElkTesting = i) iElkTesting = -1 elkShapeTest = NULL ENDIF iElksInPlay-- //CPRINTLN(DEBUG_MISSION,"Elk cleaned. Elks in play is now", iElksInPlay) mElk[i].iSpawnDelayTime = GET_GAME_TIMER() + SPAWN_DELAY_TIME mElk[i].bDelayBeforeRespawn = TRUE mElk[i].bIsHerdMember = FALSE mElk[i].bIsHerdLeader = FALSE SET_ELK_SPOOKED(i, FALSE) mElk[i].bBlockSpookedBlip = FALSE mElk[i].iLeaderIdx = -1 mElk[i].iCallResponseTime = 0 mElk[i].elkState = ES_CHECK_CAN_SPAWN BREAK ENDSWITCH ENDPROC /// PURPOSE: /// Flags all elk as spooked and gets them to run off. /// Called when the player leaves the hunt area to prevent him from being able to get kills when he's /// being told to return to the hunt area. PROC SPOOK_ALL_ELK() INT i REPEAT MAX_ELKS i IF IS_ELK_OK(i) mElk[i].elkState = ES_RUN_OFF ENDIF ENDREPEAT ENDPROC // Returns true if the player left the hunt area // after being warned FUNC BOOL DID_PLAYER_LEAVE_AREA() IF NOT IS_PLAYER_IN_IMMEDIATE_HUNT_AREA() IF NOT bIsPlayerOutsideHuntArea IF NOT bIsAmbient CLEAR_HELP() ENDIF PRINT_NOW("AHT_RTN", DEFAULT_GOD_TEXT_TIME, 0) // GET BACK TO THE HUNTING AREA mCentreBlip = CREATE_COORD_BLIP(mAreaCheck1.vCentre, BLIPPRIORITY_HIGH, FALSE) SPOOK_ALL_ELK() bAllowCall = FALSE bIsPlayerOutsideHuntArea = TRUE ELSE // Yes, he is outside the area CPRINTLN(DEBUG_MISSION,"PLAYER HAS BEEN WARNED - TIMERA IS ", TIMERA()) IF NOT IS_PLAYER_IN_OUTER_HUNT_AREA() SAFE_REMOVE_BLIP(mCentreBlip) CPRINTLN(DEBUG_MISSION,"PLAYER LEFT AREA") RETURN TRUE ENDIF ENDIF ELSE IF bIsPlayerOutsideHuntArea CPRINTLN(DEBUG_MISSION,"PLAYER IS BACK INSIDE") CLEAR_PRINTS() IF DOES_BLIP_EXIST(mCentreBlip) REMOVE_BLIP(mCentreBlip) ENDIF IF NOT bIsAmbient PRINT_HELP("AHT_CALL") ENDIF bAllowCall = TRUE bIsPlayerOutsideHuntArea = FALSE // Reset all animal and elk calls, that way the player isn't inundated as soon as he enters the area. //RESET_ALL_ANIMAL_CALLS() RESET_ALL_ELK_CALLS() ENDIF ENDIF RETURN FALSE ENDFUNC // ============== // WIND FUNCTIONS // ============== /// PURPOSE: /// Sets the direction of the wind indicator on the HUD. /// PARAMS: /// huntingUI - /// fRotation - /// fSpeed - PROC SET_WIND_DIRECTION_FOR_HUNTING(SCALEFORM_INDEX huntingUI, FLOAT fRotation = -1.0, FLOAT fSpeed = -1.0) BEGIN_SCALEFORM_MOVIE_METHOD(huntingUI, "SET_WIND_DIRECTION") SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(fRotation) SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(fSpeed) END_SCALEFORM_MOVIE_METHOD() ENDPROC /// PURPOSE: /// Sets the direction of the compass (relative to player heading) on the compass on the HUD /// PARAMS: /// huntingUI - /// fRotation - PROC SET_COMPASS(SCALEFORM_INDEX huntingUI, FLOAT fRotation = -1.0) BEGIN_SCALEFORM_MOVIE_METHOD(huntingUI, "SET_COMPASS_DIRECTION") SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(fRotation) END_SCALEFORM_MOVIE_METHOD() ENDPROC /// PURPOSE: /// Tints the HUD wind display to the params passed in /// PARAMS: /// huntingUI - the handle to the UI element /// R - Red /// B - Blue /// G - Green PROC SET_WIND_TINT(SCALEFORM_INDEX huntingUI, INT R, INT B, INT G = 0) BEGIN_SCALEFORM_MOVIE_METHOD(huntingUI, "TINT_WIND_POINTER") SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(0) //Arrow SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(R) //Red SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(G) //Green SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(B) //Blue END_SCALEFORM_MOVIE_METHOD() ENDPROC //CONST_INT iGREENRedVal 74 //CONST_INT iGREENGreenVal 170 //CONST_INT iGREENBlueVal 47 // //CONST_INT iREDRedVal 245 //CONST_INT iREDGreenVal 44 //CONST_INT iREDBlueVal 16 // Start the wind indicator off green INT iRedx = -1 INT iGreenx = 0 INT iBluex = 0 INT iCapR_R = -1 INT iCapR_G INT iCapR_B INT iCapG_R INT iCapG_G INT iCapG_B /// PURPOSE: /// Updates the wind scaleform /// PARAMS: /// bOverride - In Hunt 2 this flag is set to override the actual wind direction with one /// set by the last param /// i - The direction we want to override the direction of the wind with PROC UPDATE_WIND_BLIP(BOOL bOverride = FALSE, FLOAT i = 270.0) // On first update, make sure we set our starting vals. IF (iRedx = -1) INT iDontCare GET_HUD_COLOUR(HUD_COLOUR_GREEN, iRedx, iGreenx, iBluex, iDontCare) // Get caps too GET_HUD_COLOUR(HUD_COLOUR_GREEN, iCapG_R, iCapG_G, iCapG_B, iDontCare) GET_HUD_COLOUR(HUD_COLOUR_RED, iCapR_R, iCapR_G, iCapR_B, iDontCare) ENDIF FLOAT tempWind = 0.0 VECTOR camRot = GET_GAMEPLAY_CAM_ROT() IF NOT bOverride IF NOT IS_ENTITY_DEAD (PLAYER_PED_ID()) vWindDirection = GET_WIND_DIRECTION() fWindDirection = GET_HEADING_FROM_VECTOR_2D(vWindDirection.x, vWindDirection.y) tempWind = camRot.z - fWindDirection ENDIF ELSE fWindDirection = i tempWind = camRot.z - i ENDIF WHILE fWindDirection < 0 fWindDirection+=360.0 ENDWHILE WHILE tempWind < 0 tempWind += 360.0 ENDWHILE FLOAT windSpeed = GET_WIND_SPEED() IF PLAYER_CLOSE_TO_BEING_DETECTED() IF iRedx < iCapR_R iRedx++ ELIF iRedx > iCapR_R iRedx-- ENDIF IF iBluex < iCapR_B iBluex++ ELIF iBluex > iCapR_B iBluex-- ENDIF IF iGreenx < iCapR_G iGreenx++ ELIF iGreenx > iCapR_G iGreenx-- ENDIF ELSE IF iRedx < iCapG_R iRedx++ ELIF iRedx > iCapG_R iRedx-- ENDIF IF iBluex < iCapG_B iBluex++ ELIF iBluex > iCapG_B iBluex-- ENDIF IF iGreenx < iCapG_G iGreenx++ ELIF iGreenx > iCapG_G iGreenx-- ENDIF ENDIF // Call drawing funcs. DRAW_GENERIC_WIND_METER("AHT_WIND_UPPR", ROUND(windSpeed), tempWind, iRedx, iGreenx, iBluex, HUDORDER_FOURTHBOTTOM) ENDPROC /// ===== /// AUDIO /// ===== /// PURPOSE: /// Returns the audio values to default when the player stops aiming down the sight. PROC RETURN_AUDIO() fConcentration -= 0.05 IF NOT IS_ANY_ELK_OK() fHeartBeat -= 0.05 ENDIF IF fConcentration <= 0.0 //OR fHeartBeat <= 70.0 fConcentration = 0.0 //fHeartBeat = 70.0 IF IS_AUDIO_SCENE_ACTIVE("HUNTING_02_SETTINGS") STOP_AUDIO_SCENE("HUNTING_02_SETTINGS") STOP_SOUND(iSoundID) RELEASE_SOUND_ID(iSoundID) iSoundID = -1 ENDIF ENDIF IF fConcentration >= 1.0 fConcentration = 1.0 ENDIF IF fHeartBeat >= 100.0 fHeartBeat = 100.0 ENDIF IF fHeartBeat <= 70.0 fHeartBeat = 70.0 ENDIF IF IS_AUDIO_SCENE_ACTIVE("HUNTING_02_SETTINGS") SET_AUDIO_SCENE_VARIABLE("HUNTING_02_SETTINGS","Concentration",fConcentration) SET_AUDIO_SCENE_VARIABLE("HUNTING_02_SETTINGS","Breathing",fConcentration) SET_VARIABLE_ON_SOUND(iSoundId, "Concentration", fHeartBeat) ENDIF ENDPROC /// PURPOSE: /// Works out where to start the concentration level from based on the players previous movement. /// PARAMS: /// fConc - /// fHeart - PROC WORK_OUT_INITAL_CONCENTRATION(FLOAT &fConc, FLOAT &fHeart) IF IS_PED_UNINJURED(PLAYER_PED_ID()) IF IS_PED_RUNNING(PLAYER_PED_ID()) fConc = 0.2 fHeart = 20 ELIF IS_PED_SPRINTING(PLAYER_PED_ID()) fConc = 0.0 fHeart = 0 ELSE fConc = 0.3 fHeart = 30 ENDIF ENDIF ENDPROC /// PURPOSE: /// Works out the current concentration value. PROC WORK_OUT_CONCENTRATION(FLOAT &fConc, FLOAT &fHeart) IF IS_PED_UNINJURED(PLAYER_PED_ID()) fConc += 0.05 fHeart += 0.05 IF fConc < 0.0 fConc = 0.0 ELIF fConc > 1.0 fConc = 1.0 ENDIF IF fHeart < 0.0 fHeart = 0.0 ELIF fHeart > 100.0 fHeart = 100.0 ENDIF ENDIF ENDPROC /// PURPOSE: /// Plays the correct sfx when the player is looking down the scope. PROC MONITER_PLAYER_AIMING_SOUNDS() IF NOT IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID(), TRUE) IF DOES_PLAYER_HAVE_RIFLE_EQUIPT() AND NOT bIsPlayerOutsideHuntArea AND IS_PLAYER_FREE_AIMING(PLAYER_ID()) AND IS_FIRST_PERSON_AIM_CAM_ACTIVE() IF iSoundID = -1 iSoundID = GET_SOUND_ID() ENDIF //sniper scope take a few frames to come on screen IF iSoundDelay >= 10 IF NOT IS_AUDIO_SCENE_ACTIVE("HUNTING_02_SETTINGS") START_AUDIO_SCENE("HUNTING_02_SETTINGS") WORK_OUT_INITAL_CONCENTRATION(fConcentration, fHeartBeat) SET_AUDIO_SCENE_VARIABLE("HUNTING_02_SETTINGS","Concentration",fConcentration) PLAY_SOUND_FROM_ENTITY(iSoundId, "Heart_Breathing", PLAYER_PED_ID()) ELSE WORK_OUT_CONCENTRATION(fConcentration, fHeartBeat) SET_AUDIO_SCENE_VARIABLE("HUNTING_02_SETTINGS","Concentration",fConcentration) ENDIF SET_VARIABLE_ON_SOUND(iSoundId, "Concentration", fHeartBeat) ELSE iSoundDelay++ ENDIF ELSE iSoundDelay = 0 RETURN_AUDIO() ENDIF ELSE IF IS_AUDIO_SCENE_ACTIVE("HUNTING_02_SETTINGS") STOP_AUDIO_SCENE("HUNTING_02_SETTINGS") STOP_SOUND(iSoundID) RELEASE_SOUND_ID(iSoundID) iSoundID = -1 ENDIF ENDIF ENDPROC /// PURPOSE: /// Addes the vector to the points that border the hunting area. /// PARAMS: /// polys - /// count - PROC POPULATE_POLY_CHECKS(VECTOR &polys[], INT count = MAX_POLY_TEST_VERTS) OPEN_TEST_POLY(mAreaCheck1) INT i FOR i = 0 TO (count-1) ADD_TEST_POLY_VERT(mAreaCheck1, polys[i]) ENDFOR CLOSE_TEST_POLY(mAreaCheck1) COPY_EXPANDED_POLY(mAreaCheck2, mAreaCheck1, 50) ENDPROC /// PURPOSE: /// Monitors if the player has made any unlean kills or killed /// elk not using a sniper rifle. /// RETURNS: /// TRUE if the player has made too many unclean kills. FUNC BOOL HT_HAS_PLAYER_FAILED_HUNT() IF bUncleanKill OR bPlayerKillElkIncorrectly iUncleanKills++ IF iUncleanKills >= 4 CPRINTLN(DEBUG_MISSION,"UNCLEAN FAIL!") RETURN TRUE ENDIF ENDIF RETURN FALSE ENDFUNC /// PURPOSE: /// Updates everything to do with the elk, controls the HUD display /// and tracks the timers. /// PARAMS: /// returnTime - the time passed back to the pass/fail function PROC UPDATE_HUNTING_ELK(BOOL bMissionEnded = FALSE, BOOL bTitleFinished = TRUE) INT i = 0 // Pasue timer when the mission has ended or paused due to the cancel screen showing, but the HUD is still displaying. IF NOT bPauseTimer IF bGotPauseTime iPauseEndTime = GET_GAME_TIMER() iPauseDuration = iPauseEndTime - iPauseStartTime iEndTime = iEndTime + iPauseDuration bGotPauseTime = FALSE ENDIF ELSE // If we're paused, grab the game timer and start timing the duration of the pause. IF NOT bGotPauseTime iPauseStartTime = (GET_GAME_TIMER()) bGotPauseTime = TRUE ENDIF ENDIF // Store off the player's zoom level. fZoomLevel = 1.0 IF IS_AIM_CAM_ACTIVE() fZoomLevel = GET_FIRST_PERSON_AIM_CAM_ZOOM_FACTOR() ENDIF fDistanceThreshold = DISTANCE_HARD_BLIP_THRESHOLD * fZoomLevel // Process player calls. CHECK_FOR_CALLS() REPEAT MAX_ELKS i HAS_PLAYER_KILLED_ELK(i) CHECK_ELK_STATES(i) ENDREPEAT // If we've finished a random bleating cycle, extend the tim until our next random bleat. IF bRandomBleat bRandomBleat = FALSE iBleatInitiateTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(BLEAT_TRIGGER_MIN_DELAY, BLEAT_TRIGGER_MAX_DELAY) iBleatResponseTime = -1 iInitiatorIndex = -1 ENDIF IF DOES_PLAYER_HAVE_RIFLE_EQUIPT() bSniperEquiped = TRUE ENDIF // Don't show the HUD if the pause menu or quit menu is active. IF bPauseTimer OR IS_PHONE_ONSCREEN() OR IS_BROWSER_OPEN() EXIT ENDIF IF NOT bMissionEnded AND bTitleFinished SET_SNIPER_SCOPE_UNDER_HUD_THIS_FRAME() UPDATE_WIND_BLIP(FALSE) // Draw the next goal score here. IF Player_Hunt_Data.iScore >= Player_Hunt_Data.iScoreForGold IF Player_Hunt_Data.iScore > Player_Hunt_Data.iHighScore DRAW_GENERIC_SCORE(Player_Hunt_Data.iScore, "AHT_HIGHSCORE", -1, HUD_COLOUR_WHITE, HUDORDER_FOURTHBOTTOM) ELSE DRAW_GENERIC_SCORE(Player_Hunt_Data.iHighScore, "AHT_HIGHSCORE", -1, HUD_COLOUR_WHITE, HUDORDER_FOURTHBOTTOM) ENDIF ELIF Player_Hunt_Data.iScore >= Player_Hunt_Data.iScoreForSilver DRAW_GENERIC_SCORE(Player_Hunt_Data.iScoreForGold, "AHT_TGT_GOLD", -1, HUD_COLOUR_GOLD, HUDORDER_FOURTHBOTTOM) ELIF Player_Hunt_Data.iScore >= Player_Hunt_Data.iScoreForBronze DRAW_GENERIC_SCORE(Player_Hunt_Data.iScoreForSilver, "AHT_TGT_SILVER", -1, HUD_COLOUR_SILVER, HUDORDER_FOURTHBOTTOM) ELSE DRAW_GENERIC_SCORE(Player_Hunt_Data.iScoreForBronze, "AHT_TGT_BRONZE", -1, HUD_COLOUR_BRONZE, HUDORDER_FOURTHBOTTOM) ENDIF // Current score is bottom. DRAW_GENERIC_SCORE(Player_Hunt_Data.iScore, "AHT_SCRE_UPPR", -1, HUD_COLOUR_WHITE, HUDORDER_THIRDBOTTOM) // Current score is bottom. DRAW_GENERIC_SCORE(Player_Hunt_Data.iMoney, "AHT_MONY_UPPR", -1, HUD_COLOUR_WHITE, HUDORDER_SECONDBOTTOM, FALSE, "HUD_CASH") ENDIF // We do this outside of the loop because doing it in the loop would suppress it for one elk, but that's all. IF bShouldClearSuppressNearMissMsg bSuppressNearMissMessage = FALSE bShouldClearSuppressNearMissMsg = FALSE ENDIF ENDPROC