Files
2025-09-29 00:52:08 +02:00

3964 lines
124 KiB
Scheme
Executable File

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