Files
gtav-src/script/dev_ng/singleplayer/scripts/RandomChar/Barry/Barry2.sc
T
2025-09-29 00:52:08 +02:00

5968 lines
195 KiB
Python
Executable File

// *****************************************************************************************
// *****************************************************************************************
//
// MISSION NAME : Barry2.sc
// AUTHOR : Aaron Gandaa / Stefan Arnold
// DESCRIPTION : Second Barry Mission (clowns)
//
// *****************************************************************************************
// *****************************************************************************************
//Compile out Title Update changes to header functions.
//Must be before includes.
//CONST_INT USE_TU_CHANGES 0 // Removed by Kenneth R.
//----------------------
// INCLUDES
//----------------------
USING "rage_builtins.sch"
USING "globals.sch"
USING "cutscene_public.sch"
USING "commands_cutscene.sch"
USING "commands_entity.sch"
USING "commands_script.sch"
USING "commands_shapetest.sch"
USING "script_player.sch"
USING "randomChar_public.sch"
USING "rgeneral_include.sch"
USING "dialogue_public.sch"
USING "RC_Helper_Functions.sch"
USING "RC_Area_public.sch"
USING "RC_Asset_public.sch"
USING "cheat_controller_public.sch"
USING "CompletionPercentage_public.sch"
USING "replay_public.sch"
USING "shop_public.sch"
USING "initial_scenes_barry.sch"
USING "commands_recording.sch"
USING "taxi_functions.sch"
#IF IS_DEBUG_BUILD
USING "select_mission_stage.sch"
USING "shared_debug.sch"
#ENDIF
//----------------------
// ENUMS
//----------------------
ENUM CLOWN_STATE
CS_NULL,
CS_DELAY,
CS_TELEPORT,
CS_TELEPORT_OUT_START,
CS_TELEPORT_OUT,
CS_TELEPORT_SEEK_PLACE,
CS_DANCE_START,
CS_DANCE,
CS_PERFORM_START,
CS_PERFORM_SPAWN_GUN,
CS_ONROUTE_START,
CS_ONROUTE,
CS_ACTIVE,
CS_ATTACK_SPECTATORS,
CS_VEHICLE_DEPLOY,
CS_DYING,
CS_DEATH_FX,
CS_DEAD
ENDENUM
ENUM STAGE_ENUM
SE_LEAD_IN = -1,
SE_INTRO = 0,
SE_TEST,
SE_PERFORMANCE, // 1 clown performs, then shoots audience
SE_FIRSTCONTACT, // 3 guys
SE_WAVE1, // clown generator
SE_WAVE2, // clown generator
SE_WAVE3, // 5 guys
SE_WAVE4, // 2 generators
SE_WAVE5, // 2 generators
SE_WAVE6, // "boss" wave
SE_PASSOUT,
SE_OUTRO,
SE_FAILED
ENDENUM
// @SBA - different possible starting types for clowns
ENUM STARTING_CLOWN_TYPES
SCT_NORMAL, // Your typical killer clown
SCT_SPECIAL, // Used if clown needs to do something custom (currently for first performance clown lead-out)
SCT_PERFORM, // Used for clowns that are entertaining spectators (except first performance lead-out)
SCT_CHASE, // Used for clowns engaged in hunting down spectators
SCT_VAN_EXIT // Used for clowns exitng the back of a clown van
ENDENUM
ENUM PASS_OUT_STAGE
POS_SETUP,
POS_WAIT_FOR_TIRED,
POS_START_DIALOG,
POS_TRANSITION_FX,
POS_WAIT_DIALOGUE,
POS_WAIT_PASS_OUT
ENDENUM
//----------------------
// STRUCTURES
//----------------------
STRUCT CLOWN_PED
BOOL bIsActive
BOOL bIsDead = FALSE
CLOWN_STATE aState
PED_INDEX pedID
BLIP_INDEX blipID
INT laughSoundID = -1
FLOAT fClownAlpha = 255.0
TEXT_LABEL danceAnim
INT iDanceTimer = 0
INT iTimer
INT iLongevityTimer
STARTING_CLOWN_TYPES ClownType = SCT_NORMAL
PED_INDEX piClosestSpec = NULL
VECTOR vDeathPosition
ENDSTRUCT
STRUCT CLOWN_GENERATOR
BOOL bIsActive
BOOL bIsDead = FALSE
CLOWN_STATE aState
VEHICLE_INDEX generatorID
BLIP_INDEX blipID
FLOAT fClownAlpha = 255.0
INT iTimer
BOOL bIsInDynamicMix = FALSE
BOOL bHasStartedDeploying = FALSE
BOOL bHasPlayerApproached = FALSE
INT iClownPedsSpawned = 0
INT iForwardTime = 5000
INT iHBrakeTime = 500
INT iSwerveIn = 0
INT iDriverID = -1
ENDSTRUCT
//----------------------
// CONSTANTS
//----------------------
CONST_INT MISSION_VERSION 016 // this so i can be sure that my changes have been accepted
CONST_INT FAIL_WARNING_TIME 10000
CONST_INT CUTSCENE_TRANSITION_TIME 54000 // 1m 07 seconds 44000
CONST_INT CUTSCENE_CLOWN_TIME 59000 // 58000 // 46000
CONST_INT MAX_CLOWN_PEDS 8
CONST_INT CLOWN_FADE_TIME 500
CONST_INT TELEPORT_TIME 250
CONST_FLOAT TELEPORT_Z_DIFF 0.1
CONST_FLOAT CLOWN_APPEAR_SIZE 1.5
CONST_FLOAT GENERATOR_APPEAR_SIZE 3.0
CONST_FLOAT STAGE_BREAK_TIME 0.5
//----------------------
// CHECKPOINTS
//----------------------
CONST_INT CP_MISSION_START 0
CONST_INT CP_MID_STAGE 1 // stage 4
CONST_INT CP_OUTRO 2
CONST_INT Z_SKIP_TO_INTRO 0
CONST_INT Z_SKIP_TO_PERFORMANCE 1 //@SBA - inserted this stage
CONST_INT Z_SKIP_TO_FIRST_CONTACT 2
CONST_INT Z_SKIP_TO_FIRST_WAVE 3
CONST_INT Z_SKIP_TO_SECOND_WAVE 4
CONST_INT Z_SKIP_TO_THIRD_WAVE 5
CONST_INT Z_SKIP_TO_FOURTH_WAVE 6
CONST_INT Z_SKIP_TO_FIFTH_WAVE 7
CONST_INT Z_SKIP_TO_SIXTH_WAVE 8 //@SBA - inserted this stage
CONST_INT Z_SKIP_TO_PASSOUT 9
CONST_INT Z_SKIP_TO_OUTRO 10
CONST_INT Z_SKIP_TO_TEST 11
CONST_INT MAX_SKIP_MENU_LENGTH 12
// match up with object array in g_structRCScriptArgs (see initial_scenes_barry.sch)
CONST_INT OBJ_TABLE 0
CONST_INT OBJ_CHAIR 1
CONST_INT OBJ_PAPERS 2
CONST_INT OBJ_SIGN 3
//----------------------
// RC VARIABLES
//----------------------
g_structRCScriptArgs sRCLauncherDataLocal
//----------------------
// VARIABLES
//----------------------
INT iFailTimer
STRING sFailString = ""
STAGE_ENUM stageEnum = SE_LEAD_IN
PASS_OUT_STAGE ePassOutStage
STAGE_PROGRESS stageProgress
OBJECT_INDEX gunObject
INT iDbgStageJump // now also used in checkpoint / replay stuff
SCENARIO_BLOCKING_INDEX scenarioBlock
VECTOR vPlayerCarRespot = <<174.1703, -1012.2490, 28.3180>>
FLOAT fPlayerCarRespot = 27.4862
VECTOR vBattleCenter = <<180.5319, -970.6324, 29.0923>>
FLOAT fBattleRadius = 80.0
VECTOR vMissionStart = << 188.86, -955.83, 29.09 >>
FLOAT fMissionStart = 62.08
FLOAT fTimeScale = 0.8
ANGLED_AREA battleAreaOuter
ANGLED_AREA battleArea
ANGLED_AREA battleAreaInner
ANGLED_AREA respotVehicleArea
BOOL bIsPlayerInBattleArea = TRUE
INT iMissionAbandonedTimer = 0
BLIP_INDEX locationBlip
BOOL bDebugTTYSpew = FALSE
INT iAlphaCounter = 0
BOOL bTransitionStarted = FALSE
BOOL bInitialClowns = FALSE
ASSET_REQUESTER assetRequester
//----------------------
// ANIM / CS VARIABLES
//----------------------
STRING sSceneHandleBarry = "Barry"
STRING sSceneHandleChair = "Barrys_chair"
STRING sSceneHandleTable = "Barrys_protest_table"
STRING sSceneHandlePapers = "Barry_Pamphlet_1"
STRING FX_DrugsIn = "DrugsTrevorClownsFightIn"
STRING FX_DrugsSkip = "DrugsTrevorClownsFight"
STRING FX_DrugsOut = "DrugsTrevorClownsFightOut"
STRING sMissionAnimDictionary = "rcmbarry"
STRING sMissionAnimDanceDictionary = "rcm_barry2"
STRING sndAlienAmbientScene = "BARRY_02_DRUGS"
BOOL bHasPlayerCameraExitState = FALSE
//----------------------
// CLOWN VARIABLES
//----------------------
CLOWN_PED clownPed[MAX_CLOWN_PEDS]
CLOWN_GENERATOR clownGenerator[3]
MODEL_NAMES clownModel = S_M_Y_CLOWN_01
MODEL_NAMES clownCarModel = SPEEDO2
MODEL_NAMES mnProtestSign = Prop_Protest_Sign_01
WEAPON_TYPE playerWeapon = WEAPONTYPE_ASSAULTSHOTGUN
COMBAT_PARAMETERS combatParams
INT iNextSpawnTimer = 0
INT iMinPedSpawnTime = 500
INT iMaxPedSpawnTime = 2000
INT iMinGeneratorPedSpawnTime = 1500
INT iMaxGeneratorPedSpawnTime = 3000
FLOAT fNoSpawnPlayerDist = 12.0
INT iMaxActivePeds = 5
INT iClownPedsSpawned = 0
INT iClownPedsKilled = 0
INT iDancingClownPedsKilled = 0
INT iClownGeneratorsDestroyed = 0
FLOAT fClownGeneratorTriggerDist = 20.0
INT iAliveClownCount = 0
INT iAliveClownGeneratorCount = 0
FLOAT fClownSpawnRadius = 40.0
BOOL bGenerateAutoClowns = FALSE
BOOL bUseClownSpawnPoint = FALSE
VECTOR vClownSpawnPoint
VECTOR vClownCarSmokeOffset = <<0, -3.2, 0.6>>
FLOAT fClownCarPedSmokeSize = 1.5
FLOAT iStageTimer = 0
INT iStateTimeOut = 0
BOOL bUseIsAreaOccupied = FALSE
BOOL bHasClownGeneratorHelpDisplayed = FALSE
BOOL bHasTrevorClownGeneratorRanted = FALSE
INT iTrevorClownGeneratorRantTime = 0
INT iMinClownDanceDelay = 5000
INT iMaxClownDanceDelay = 20000
FLOAT fClownCarFwdSpeed = 8.5 //12.5
//----------------------
// AUDIO VARIABLES
//----------------------
BOOL bHasInitialOutburst = FALSE
INT iFirstDialogTime
INT iNextFightDialogTime
INT iNextFreakDialogTime
LOCATES_HEADER_DATA sLocateData
structPedsForConversation convoPlayer
STRING sAmbientZone = "AZ_BARRY_02_AMBIENCE"
//----------------------
// DEBUG VARIABLES
//----------------------
#IF IS_DEBUG_BUILD
MissionStageMenuTextStruct sSkipMenu[MAX_SKIP_MENU_LENGTH]
WIDGET_GROUP_ID m_WidgetGroup
BOOL bGenerateTestClown = FALSE
BOOL bUpdateWidgets = TRUE
BOOL bGenerateTestGenerator = FALSE
VECTOR vTestGenPoint = << 171.9, -978.4, 30.1 >>
FLOAT fTestHeading = 0
INT iTestSwerve = 0
INT iTestFwdTime = 5000
INT iTestBrakeTime = 500
#ENDIF
//----------------------
// @SBA - ADDITIONAL VARIABLES
//----------------------
// Anim phases we care about
// Phase at which to start the mime anim
CONST_FLOAT kfMimeStartPhase 0.625
// Phase in the mime anim in which gun should spawn
CONST_FLOAT kfMimeGunSpawnPhase 0.802
// End phase of the mime anim
CONST_FLOAT kfMimeEndPhase 0.815
// Ditto for the regular dance anims
CONST_FLOAT kfDanceGunSpawnPhase 0.95
CONST_FLOAT kfDanceEndPhase 0.99
// If a clown has been alive this long, he becomes aggresive
// Should help stragglers seek out the player
CONST_INT kiAggressiveTime 30000
// Min gap between fight/freak lines
CONST_INT kiDialogTimeCheck 2500
// cutscene skip
BOOL bSkipAllowed = FALSE
// Keep track of the armor the player stared with
INT iPlayerStartingArmor
// Flag to set last clown in wave aggressive
BOOL bLastClownAggressive = FALSE
// performance vars
BOOL bPerformancePedsCreated = FALSE
BOOL bPlayedGunSmokeFX = FALSE
INT i1stPerformanceClownID
INT i2ndPerformanceClownID
INT i3rdPerformanceClownID
BOOL bTrevFirstLine = FALSE
// cameras used in the opening performance
CAMERA_INDEX ciPerformCamera1
// @SBA - spectators
CONST_INT kiNumberOfSpectators 5
// The distance within which clowns engaged with the player will notice a spectator
CONST_FLOAT kiShortIgnoreSpectatorsDist 12.0
// All Clowns ignore spectators past this distance
CONST_FLOAT kiLongIgnoreSpectatorsDist 22.0
// Clowns run after spectators if farther than this distance
CONST_FLOAT kiCHaseSpectatorsDist 5.0
// Distance at which a spectator will notice another spectator dying
CONST_FLOAT kfMinSpectatorWitnessDist 20.0
MODEL_NAMES mnSpectatorMale = A_M_M_Business_01
MODEL_NAMES mnSpectatorFemale = A_F_M_BevHills_02
INT iSpecAlphaCounter = 0
INT iApplauseSound = -1
STRING sSpectatorFemAnimDict = "amb@world_human_cheering@female_d"
STRING sSpectatorFemAnimClip = "base"
STRING sSpectatorMaleAnimDict = "amb@world_human_cheering@male_d"
STRING sSpectatorMaleAnimClip = "base"
STRING sMimeAnimDict = "special_ped@mime"
STRING sMimeAnimClip = "idle_c"
VECTOR vSpectatorPerformOffsets[kiNumberOfSpectators]
ENUM SPECTATOR_STATE
SS_FADE_IN,
SS_WATCH_CLOWN,
SS_REACT_TO_DANGER,
SS_FLEEING,
SS_KILL,
SS_GOING,
SS_GONE,
SS_DONE
ENDENUM
STRUCT SPECTATOR_STRUCT
PED_INDEX piPed
MODEL_NAMES mnModel
VECTOR vSpawnPos
FLOAT fSpawnHead
SPECTATOR_STATE ssState
BOOL bIsActive = FALSE
INT iTimer
FLOAT fSpectAlpha = 255.0
BOOL bJustFlee = FALSE
ENDSTRUCT
SPECTATOR_STRUCT ssSpectator[kiNumberOfSpectators]
// states for the intro performance
ENUM PERFORMANCE_STATE
PS_MIME_CLOWN_MIME,
PS_MOVE_PLAYER,
PS_SPAWN_WEAPON,
PS_SPAWN_LAST_CLOWNS,
PS_CLOWNS_ATTACK_SPECTATORS,
PS_CLOWNS_ATTACK_SPECTATORS_2,
PS_KILLING_SPECTATORS,
PS_RETURN_PLAYER_CONTROL,
PS_CLOWNS_ATTACK_PLAYER,
PS_KILL_CLOWNS,
PS_DONE
ENDENUM
PERFORMANCE_STATE psPerformanceState = PS_MIME_CLOWN_MIME
// for timing out some of the performance states
structTIMER tmrPerformance
// ~~~ @SBA General Clown Performance Vars ~~~
// size of the performance data array
CONST_INT kiPerformDataSize 15
// Minimum distance the player should be from a performance spawn
CONST_FLOAT kfPerformMinSpawnDIst 7.0
// General spawn areas,
ENUM SPAWN_ZONES
SZ_ZONE_1, // Intro through Wave 2
SZ_ZONE_2,
SZ_ZONE_3,
SZ_NO_ZONE // for clearing data
ENDENUM
// data for performance clowns and spectators
STRUCT CLOWN_PERFORMANCE_DATA
SPAWN_ZONES SpawnZone
VECTOR vClownPos
FLOAT fClownHead
INT iNumSpectators = -1
BOOL bThisIsAFleeSpawn = FALSE
ENDSTRUCT
// Permanent struct to hold performance location data
CLOWN_PERFORMANCE_DATA CPD_PerformData[kiPerformDataSize]
// Used to hold valid data for specific performance spawns
// (@TODO - This array could be smaller, as it just needs a zone's worth of data)
CLOWN_PERFORMANCE_DATA CPD_SpecificData[kiPerformDataSize]
//
BOOL bClownGeneratorRantTimerSet = FALSE
BOOL bHasTrevorDupClownRanted = FALSE
// for timing out some general stuff (reusable)
structTIMER tmrGeneral
FLOAT fGeneralTime
// Boss wave
CONST_INT kiNumDuplicates 2
INT iDuplicatesCount = 0
//----------------------
// @SBA - END ADDITIONAL VARIABLES
//----------------------
//----------------------
// MISC FUNCTIONS
//----------------------
FUNC VECTOR GET_MODEL_SIZE(MODEL_NAMES mdlName)
VECTOR vMin, vMax, vSize
GET_MODEL_DIMENSIONS(mdlName, vMin, vMax)
vSize.x = ABSF(vMax.x - vMin.x)
vSize.y = ABSF(vMax.y - vMin.y)
vSize.z = ABSF(vMax.z - vMin.z)
RETURN vSize
ENDFUNC
/// PURPOSE:
/// Resolve cars for mission
PROC RESOLVE_MISSION_VEHICLES_FOR_CUTSCENE()
MODEL_NAMES mdlName
CPRINTLN(DEBUG_MISSION, "Vehicles Resolved For Intro")
IF NOT IS_ENTITY_ALIVE(GET_PLAYERS_LAST_VEHICLE())
EXIT
ENDIF
mdlName = GET_ENTITY_MODEL(GET_PLAYERS_LAST_VEHICLE())
IF IS_THIS_MODEL_A_HELI(mdlName) OR IS_THIS_MODEL_A_PLANE(mdlName)
vPlayerCarRespot = <<180.47, -1017.79, 30.01>>
fPlayerCarRespot = 206.45
CPRINTLN(DEBUG_MISSION, "RESOLVE_MISSION_VEHICLES_FOR_CUTSCENE() - THIS IS A PLANE OR HELI")
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(respotVehicleArea.vPosition[0], respotVehicleArea.vPosition[1], respotVehicleArea.fWidth,
vPlayerCarRespot, fPlayerCarRespot, <<0, 0, 0>>, TRUE, FALSE) // setVehicleAsVehGen parameter should no longer be used - SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN to handle it
//IF IS_REPLAY_START_VEHICLE_UNDER_SIZE_LIMIT(<<0, 0, 0>>, TRUE)
SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN(vPlayerCarRespot, fPlayerCarRespot, FALSE)
//ENDIF
ELSE
RESOLVE_VEHICLES_INSIDE_ANGLED_AREA_WITH_SIZE_LIMIT(respotVehicleArea.vPosition[0], respotVehicleArea.vPosition[1], respotVehicleArea.fWidth,
vPlayerCarRespot, fPlayerCarRespot, GET_DEFAULT_ALLOWABLE_VEHICLE_SIZE_VECTOR(), TRUE, FALSE) // setVehicleAsVehGen parameter should no longer be used - SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN to handle it
IF IS_REPLAY_START_VEHICLE_UNDER_SIZE_LIMIT(<<0, 0, 0>>, TRUE)
SET_MISSION_START_VEHICLE_AS_VEHICLE_GEN(vPlayerCarRespot, fPlayerCarRespot, FALSE)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Initializes the data for the general clown performances
PROC INITIAILIZE_PERFORMANCE_DATA()
// Most won't be flee spawns, so init these false
INT idx
REPEAT kiPerformDataSize idx
CPD_PerformData[idx].bThisIsAFleeSpawn = FALSE
ENDREPEAT
// Zone 1 - near start
CPD_PerformData[0].SpawnZone = SZ_ZONE_1
CPD_PerformData[0].vClownPos = <<174.1163, -979.6599, 30.0923>>
CPD_PerformData[0].fClownHead = 341.3244
CPD_PerformData[1].SpawnZone = SZ_ZONE_1
CPD_PerformData[1].vClownPos = <<184.8053, -980.3381, 30.0923>>
CPD_PerformData[1].fClownHead = 50.2065
CPD_PerformData[2].SpawnZone = SZ_ZONE_1
CPD_PerformData[2].vClownPos = <<192.9764, -972.7697, 30.0923>>
CPD_PerformData[2].fClownHead = 32.8447
CPD_PerformData[3].SpawnZone = SZ_ZONE_1
CPD_PerformData[3].vClownPos = <<195.3397, -989.3920, 30.0923>>
CPD_PerformData[3].fClownHead = 2.9484
// Zone 2 - near where first pair of vans drive up
CPD_PerformData[4].SpawnZone = SZ_ZONE_2
CPD_PerformData[4].vClownPos = <<185.1147, -917.4800, 29.6923>>
CPD_PerformData[4].fClownHead = 146.3272
CPD_PerformData[5].SpawnZone = SZ_ZONE_2
CPD_PerformData[5].vClownPos = <<212.4505, -945.4181, 30.6921>>
CPD_PerformData[5].fClownHead = 64.4890
CPD_PerformData[6].SpawnZone = SZ_ZONE_2
CPD_PerformData[6].vClownPos = <<209.6497, -926.5642, 30.6921>>
CPD_PerformData[6].fClownHead = 119.3868
CPD_PerformData[7].SpawnZone = SZ_ZONE_2
CPD_PerformData[7].vClownPos = <<197.8188, -916.9774, 30.6929>>
CPD_PerformData[7].fClownHead = 248.1600
CPD_PerformData[8].SpawnZone = SZ_ZONE_2
CPD_PerformData[8].vClownPos = <<168.9134, -916.1412, 30.6921>>
CPD_PerformData[8].fClownHead = 245.1600
CPD_PerformData[8].bThisIsAFleeSpawn = TRUE
CPD_PerformData[9].SpawnZone = SZ_ZONE_2
CPD_PerformData[9].vClownPos = <<220.6332, -952.7892, 30.0924>>
CPD_PerformData[9].fClownHead = 63.2940
CPD_PerformData[9].bThisIsAFleeSpawn = TRUE
CPD_PerformData[10].SpawnZone = SZ_ZONE_2
CPD_PerformData[10].vClownPos = <<226.5618, -909.9656, 30.6922>>
CPD_PerformData[10].fClownHead = 119.7046
CPD_PerformData[10].bThisIsAFleeSpawn = TRUE
// Zone 3 - last wave of vans
CPD_PerformData[11].SpawnZone = SZ_ZONE_3
CPD_PerformData[11].vClownPos = <<229.2508, -904.2552, 30.6922>>
CPD_PerformData[11].fClownHead = 56.9046
CPD_PerformData[12].SpawnZone = SZ_ZONE_3
CPD_PerformData[12].vClownPos = <<205.4078, -898.1343, 30.1166>>
CPD_PerformData[12].fClownHead = 144.7924
CPD_PerformData[13].SpawnZone = SZ_ZONE_3
CPD_PerformData[13].vClownPos = <<222.5962, -855.8390, 30.1816>>
CPD_PerformData[13].fClownHead = 204.4446
CPD_PerformData[13].bThisIsAFleeSpawn = TRUE
CPD_PerformData[14].SpawnZone = SZ_ZONE_3
CPD_PerformData[14].vClownPos = <<182.0917, -886.9590, 30.1164>>
CPD_PerformData[14].fClownHead = 236.4387
CPD_PerformData[14].bThisIsAFleeSpawn = TRUE
ENDPROC
/// PURPOSE:
/// Initializes the offsets for the spectators of a general clown performance
PROC INITIALIZE_SPECTATOR_OFFSET_DATA()
vSpectatorPerformOffsets[0] = <<0,2.0,0>>
vSpectatorPerformOffsets[1] = <<-1.0,1.75,0>>
vSpectatorPerformOffsets[2] = <<1.25,1.75,0>>
vSpectatorPerformOffsets[3] = <<2.0,2.25,0>>
vSpectatorPerformOffsets[4] = <<-2.25,2.5,0>>
ENDPROC
/// PURPOSE:
/// @SBA - Resets the CPD_SpecificData array to default values
PROC RESET_SPECIFIC_PERFORMANCE_DATA()
INT idx
REPEAT COUNT_OF(CPD_SpecificData) idx
CPD_SpecificData[idx].SpawnZone = SZ_NO_ZONE
CPD_SpecificData[idx].vClownPos = (<<0,0,0>>)
CPD_SpecificData[idx].fClownHead = -1.0
CPD_SpecificData[idx].iNumSpectators = -1
CPD_SpecificData[idx].bThisIsAFleeSpawn = FALSE
ENDREPEAT
ENDPROC
/// PURPOSE:
/// @SBA - Populates the given specifc datum from the given entry in the permanent data
/// PARAMS:
/// iPerformDataIndex - the index into the permanent CPD_PerformData array
/// iSpecificDataIndex - the index into the specific CPD_SpecificData array
PROC POPULATE_SPECIFIC_SPAWN_DATA(INT iPerformDataIndex, INT iSpecificDataIndex)
CPD_SpecificData[iSpecificDataIndex].SpawnZone = CPD_PerformData[iPerformDataIndex].SpawnZone
CPD_SpecificData[iSpecificDataIndex].vClownPos = CPD_PerformData[iPerformDataIndex].vClownPos
CPD_SpecificData[iSpecificDataIndex].fClownHead = CPD_PerformData[iPerformDataIndex].fClownHead
CPD_SpecificData[iSpecificDataIndex].bThisIsAFleeSpawn = CPD_PerformData[iPerformDataIndex].bThisIsAFleeSpawn
CPRINTLN(DEBUG_MISSION, "POPULATE_SPECIFIC_SPAWN_DATA: Populating specific array datum. Spawn location = ", CPD_SpecificData[iSpecificDataIndex].vClownPos)
ENDPROC
/// PURPOSE:
/// @SBA - Fills the CPD_SpecificData array with valid data, returns a randomized index into it
/// PARAMS:
/// SpawnZone - The zone to search for useable spawn data
/// iReturnSpecificIndex - Returns by ref the index into the re-build CPD_SpecificData array
/// bFleeOnly - if TRUE, will return only spawn data flagged to be flee only (no clown)
/// RETURNS:
/// TRUE if able to find useable data; FALSE otherwise
FUNC BOOL GET_SPECIFIC_PERFORMANCE_SPAWN_DATA(SPAWN_ZONES SpawnZone, INT &iReturnSpecificIndex, BOOL bFleeOnly)
INT idx, iCount = 0
RESET_SPECIFIC_PERFORMANCE_DATA()
// comb the permanent data of the appropriate zone for data
REPEAT kiPerformDataSize idx
IF CPD_PerformData[idx].SpawnZone = SpawnZone
// Make sure we're getting only the data we want re: fleeing
IF CPD_PerformData[idx].bThisIsAFleeSpawn = bFleeOnly
// Make sure there's room in the array
IF iCount < COUNT_OF(CPD_SpecificData)
// Make sure peds aren't too close to the prospective spawn location
// Any more condtions? Do we want a max distance too?
//IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), CPD_PerformData[idx].vClownPos) > kfPerformMinSpawnDist
IF NOT IS_ANY_PED_NEAR_POINT(CPD_PerformData[idx].vClownPos, kfPerformMinSpawnDist)
POPULATE_SPECIFIC_SPAWN_DATA(idx, iCount)
iCount ++
ELSE
CPRINTLN(DEBUG_MISSION, "GET_SPECIFIC_PERFORMANCE_SPAWN_DATA: *** Spawn point ", CPD_PerformData[idx].vClownPos, " is too close to an existing ped ***")
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, "GET_SPECIFIC_PERFORMANCE_SPAWN_DATA: *** Wha' hoppend? CPD_SpecificData Array Is Full! ***")
idx = kiPerformDataSize
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, "GET_SPECIFIC_PERFORMANCE_SPAWN_DATA: Expecting bFleeOnly = ", bFleeOnly, ". But got: ", NOT bFleeOnly)
ENDIF
ENDIF
ENDREPEAT
IF iCount = 0
CPRINTLN(DEBUG_MISSION, "GET_SPECIFIC_PERFORMANCE_SPAWN_DATA: *** No good spawn locations for clown performance! ***")
ELSE
// Pick a random index for the specific data array
iReturnSpecificIndex = GET_RANDOM_INT_IN_RANGE(0, iCount)
CPRINTLN(DEBUG_MISSION, "GET_SPECIFIC_PERFORMANCE_SPAWN_DATA: Returning TRUE. Random index = ", iReturnSpecificIndex,". Spawn location = ", CPD_SpecificData[iReturnSpecificIndex].vClownPos, ".")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Converts a rotation vector into a normalised direction vector (basically the direction an entity would move if it moved forward at the current rotation).
/// For example: a rotation of <<0.0, 0.0, 45.0>> gives a direction vector of <<-0.707107, 0.707107, 0.0>>
/// PARAMS:
/// v_rot - The rotation vector
/// RETURNS:
/// The direction vector
FUNC VECTOR B2_CONVERT_ROT_TO_DIR_VECTOR(VECTOR v_rot)
RETURN <<-SIN(v_rot.z) * COS(v_rot.x), COS(v_rot.z) * COS(v_rot.x), SIN(v_rot.x)>>
ENDFUNC
/// PURPOSE:
/// Set a random variation for a ped body part
/// PARAMS
/// ind - ped index
/// pc - ped component enum
PROC RESET_MISSION_VALUES()
fClownSpawnRadius = 40.0
iNextSpawnTimer = 0
iMinPedSpawnTime = 500
iMaxPedSpawnTime = 2000
iMinGeneratorPedSpawnTime = 1500
iMaxGeneratorPedSpawnTime = 3000
fNoSpawnPlayerDist = 12.0
iMaxActivePeds = 5
iClownPedsSpawned = 0
iClownPedsKilled = 0
iClownGeneratorsDestroyed = 0
bGenerateAutoClowns = FALSE
bInitialClowns = FALSE
iStageTimer = 0
iAliveClownCount = 0
iAliveClownGeneratorCount = 0
ePassOutStage = POS_SETUP
//@SBA - additional reinitializations
bSkipAllowed = FALSE
bLastClownAggressive = FALSE
psPerformanceState = PS_MIME_CLOWN_MIME
bPerformancePedsCreated = FALSE
bPlayedGunSmokeFX = FALSE
bTrevFirstLine = FALSE
bClownGeneratorRantTimerSet = FALSE
bHasTrevorDupClownRanted = FALSE
iDuplicatesCount = 0
INITIAILIZE_PERFORMANCE_DATA()
INITIALIZE_SPECTATOR_OFFSET_DATA()
ENDPROC
PROC CLEANUP_SCREEN_FX()
CPRINTLN(DEBUG_MISSION, "[BARRY 2] - CLEANING UP SCREEN FX")
IF ANIMPOSTFX_IS_RUNNING(FX_DrugsIn)
ANIMPOSTFX_STOP(FX_DrugsIn)
ENDIF
IF ANIMPOSTFX_IS_RUNNING(FX_DrugsSkip)
ANIMPOSTFX_STOP(FX_DrugsSkip)
ENDIF
IF ANIMPOSTFX_IS_RUNNING(FX_DrugsOut)
ANIMPOSTFX_STOP(FX_DrugsOut)
ENDIF
ENDPROC
/// PURPOSE:
/// Tells us if the mission is in combat state
FUNC BOOL IS_MISSION_IN_COMBAT_STAGE()
INT i1 = ENUM_TO_INT(SE_INTRO)
INT i2 = ENUM_TO_INT(SE_PASSOUT)
INT i = ENUM_TO_INT(stageEnum)
RETURN (i > i1) AND (i < i2)
ENDFUNC
/// PURPOSE:
/// Forces the players weapon
PROC FORCE_PLAYER_WEAPON()
WEAPON_TYPE wpn
//REMOVE_ALL_PED_WEAPONS(PLAYER_PED_ID())
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF NOT HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), playerWeapon)
GIVE_WEAPON_TO_PED(PLAYER_PED_ID(), playerWeapon, INFINITE_AMMO, TRUE, TRUE)
CPRINTLN(DEBUG_MISSION, "Player doesn't have a gun lets give him one.")
ELSE
IF NOT GET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), wpn) OR (wpn <> playerWeapon)
CPRINTLN(DEBUG_MISSION, "Player has a gun but doesn't want to equip it for some reason.")
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), playerWeapon, TRUE)
ELSE
CPRINTLN(DEBUG_MISSION, "Player - Should have the gun and it should in his hand")
ENDIF
ENDIF
ADD_AMMO_TO_PED(PLAYER_PED_ID(), playerWeapon, 10000)
SET_PED_INFINITE_AMMO(PLAYER_PED_ID(), TRUE, playerWeapon)
SET_PED_CURRENT_WEAPON_VISIBLE(PLAYER_PED_ID(), TRUE)
SET_PED_CAN_SWITCH_WEAPON(PLAYER_PED_ID(), FALSE)
IF DOES_WEAPON_TAKE_WEAPON_COMPONENT(playerWeapon, WEAPONCOMPONENT_ASSAULTSHOTGUN_CLIP_02)
GIVE_WEAPON_COMPONENT_TO_PED(PLAYER_PED_ID(), playerWeapon, WEAPONCOMPONENT_ASSAULTSHOTGUN_CLIP_02)
CPRINTLN(DEBUG_MISSION, "Player - Should have the gun clip component")
ENDIF
SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), TRUE, -1)
//FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ACTIONMODE_IDLE, TRUE)
ENDIF
ENDPROC
PROC HANDLE_LOCK_PLAYER_IN_FRONT_OF_TABLE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_PLAYER_CONTROL_ON(PLAYER_ID())
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), (<<189.13988, -955.80487, 29.09192>>), (<<187.52740, -955.01056,31.091919>>), 2.5000000)
CPRINTLN(DEBUG_MISSION, "HANDLE_LOCK_PLAYER_IN_FRONT_OF_TABLE: Locking player")
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE, SPC_LEAVE_CAMERA_CONTROL_ON)
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
TASK_TURN_PED_TO_FACE_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[0])
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Set a random variation for a ped body part
/// PARAMS
/// ind - ped index
/// pc - ped component enum
PROC SET_RANDOM_PED_COMPONENT_VARIATION(PED_INDEX ind, PED_COMPONENT pc)
INT iDrawable = GET_RANDOM_INT_IN_RANGE(0, GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(ind, pc))
INT iTexture = GET_RANDOM_INT_IN_RANGE(0, GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(ind, pc, iDrawable))
SET_PED_COMPONENT_VARIATION(ind, pc, iDrawable, iTexture)
ENDPROC
/// PURPOSE:
/// Reset combat parameters
/// PARAMS:
/// cpm - combat param reference
PROC RESET_MISSION_COMBAT_PARAMETERS(COMBAT_PARAMETERS &cpm)
cpm.hFiringPattern = FIRING_PATTERN_DELAY_FIRE_BY_ONE_SEC
cpm.fWeaponAccuracy1 = 0.12
cpm.fWeaponAccuracy2 = 0.12
cpm.fNearBlankChance = 0.1
cpm.fFarBlankChance = 0.3
cpm.fMinTimeBetweenPeeks = 10.0
cpm.fMaxTimeBetweenPeeks = 11.0
cpm.fMinTimeBetweenCoverBurst = 1.25
cpm.fMaxTimeBetweenCoverBurst = 2.25
cpm.fMinBurstDurationTime = 2.0
cpm.fMaxBurstDurationTime = 2.5
cpm.iMinShootRate = 25
cpm.iMaxShootRate = 60
cpm.fPlayerWeaponDefenseModifier = 0.2
ENDPROC
/// PURPOSE:
/// Sets the mission fail reason and goes into the fail state
/// PARAMS:
/// sFailReason - text label of fail reason
PROC SET_MISSION_FAILED(STRING sFailReason)
IF stageEnum <> SE_FAILED
CPRINTLN(DEBUG_MISSION, "Setting mission as failed. ", sFailReason)
sFailString = sFailReason
stageProgress = SP_LOADING
stageEnum = SE_FAILED
ENDIF
ENDPROC
// Check if any clown in the array is within a given radius of a given point (True if so)
FUNC BOOL IS_ANY_CLOWN_NEAR_POINT(VECTOR vPoint, FLOAT fRadius)
INT i
REPEAT (COUNT_OF(clownPed)) i
IF DOES_ENTITY_EXIST(clownPed[i].pedID)
IF GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(clownPed[i].pedID, vPoint) < fRadius
RETURN TRUE
ENDIF
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Given a point does a ground z check, checks it not in a no spawn zone and there are no peds too close
/// PARAMS:
/// pos -
/// RETURNS:
/// True / False
FUNC BOOL CHECK_SPAWN_POINT_IS_OK(VECTOR &pos)
VECTOR spawnPos
FLOAT z
FLOAT fPedCheckRadius = 2.0
#IF IS_DEBUG_BUILD
VECTOR vPlayerPos = GET_ENTITY_COORDS(PLAYER_PED_ID())
#ENDIF
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: START")
// do a safety check here (special case wave 6)
IF stageEnum != SE_WAVE6
IF NOT GET_SAFE_COORD_FOR_PED(pos, FALSE, spawnPos, GSC_FLAG_NOT_ISOLATED | GSC_FLAG_NOT_INTERIOR | GSC_FLAG_NOT_WATER)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - COULDN'T GET SAFE POINT FOR:", pos)
RETURN FALSE
ENDIF
// @SBA - for wave 6 we don't want to bother with the safe coords as it spawns clowns to far afield.
// Also tighten up the radius for checking if other peds are in the way
ELSE
spawnPos = pos
fPedCheckRadius = 0.5
// For last wave, keep above ground
IF spawnPos.z < 29.1
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: spawnPos.z = ", spawnPos.z, ". Setting to 30.0")
spawnPos.z = 30
ENDIF
ENDIF
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: spawnPos = ", spawnPos)
IF NOT GET_GROUND_Z_FOR_3D_COORD(spawnPos, z)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - COULDN'T GET GROUND Z FOR:", spawnPos)
RETURN FALSE
ENDIF
//CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: 2nd!")
spawnPos.z = z
// Ok to spawn anywhere if it's the last wave
IF stageEnum != SE_WAVE6
IF (GET_DISTANCE_BETWEEN_COORDS(spawnPos, vBattleCenter) > fBattleRadius)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - POINT IS OUT OF BATTLE RADIUS:", spawnPos)
RETURN FALSE
ENDIF
ENDIF
//CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: 3rd!")
IF (GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), spawnPos) < fNoSpawnPlayerDist)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - POINT IS WITHIN NOSPAWNPLAYERDIST:", spawnPos)
RETURN FALSE
ENDIF
//CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: 4th!")
// check there isn't a ped in the same area
//IF IS_ANY_PED_IN_SPHERE(spawnPos, fPedCheckRadius, PLAYER_PED_ID())
IF (bUseIsAreaOccupied)
IF IS_ANY_PED_IN_SPHERE(spawnPos, fPedCheckRadius, PLAYER_PED_ID())
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK SPAWN POINT IS OK - FAILED - IS_ANY_PED_IN_SPHERE - SPAWN POS:[", spawnPos.x, ",", spawnPos.y, ",", spawnPos.z, "] THERE IS ANOTHER ALIEN WITHIN ", fPedCheckRadius, " METERS")
RETURN FALSE
ENDIF
ELSE
IF IS_ANY_PED_NEAR_POINT(spawnPos, fPedCheckRadius)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK SPAWN POINT IS OK - FAILED - IS_ANY_PED_NEAR_POINT - SPAWN POS:[", spawnPos.x, ",", spawnPos.y, ",", spawnPos.z, "] THERE IS ANOTHER ALIEN WITHIN ", fPedCheckRadius, " METERS")
RETURN FALSE
ENDIF
ENDIF
// last stage
IF stageEnum = SE_WAVE6
VECTOR temppos = spawnPos
IF NOT GET_SAFE_COORD_FOR_PED(spawnPos, FALSE, temppos, GSC_FLAG_NOT_ISOLATED | GSC_FLAG_NOT_INTERIOR | GSC_FLAG_NOT_WATER)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: FINAL WAVE - FAILED - COULDN'T GET SAFE POINT FOR: spawnPos = ", spawnPos)
RETURN FALSE
ENDIF
ENDIF
// to fix B*174705
IF IS_POINT_IN_ANGLED_AREA(spawnPos, <<211.885208,-931.168457,29.691504>>, <<220.750351,-918.622864,32.441525>>, 2.000000)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - POINT IS BURIED IN WALL DESCRIBED IN B*174705 - POINT:", spawnPos)
RETURN FALSE
ENDIF
IF (spawnPos.z < 28.58)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - PLAYER POSITION:", vPlayerPos)
CPRINTLN(DEBUG_MISSION, "CHECK_SPAWN_POINT_IS_OK: - FAILED - POINT IS TOO FAR BELOW GROUND THIS WILL CAUSE - B*174705 - POINT:", spawnPos)
RETURN FALSE
ENDIF
pos = spawnPos
RETURN TRUE
ENDFUNC
//----------------------
// DIALOG FUNCTIONS
//----------------------
/// PURPOSE:
/// Returns True if God Text is on
FUNC BOOL ARE_OBJECTIVES_BEING_DISPLAYED()
IF IS_THIS_PRINT_BEING_DISPLAYED("B2_PRIME") // Kill the ~r~clowns.~s~
RETURN TRUE
ENDIF
IF IS_THIS_PRINT_BEING_DISPLAYED("B2_WARN") // Return to the ~r~battle.~s~
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Returns True if God Text is on
FUNC BOOL ARE_OBJECTIVES_OR_TEXT_BEING_DISPLAYED()
IF IS_THIS_PRINT_BEING_DISPLAYED("B2_PRIME") // Kill the ~r~clowns.~s~
RETURN TRUE
ENDIF
IF IS_THIS_PRINT_BEING_DISPLAYED("B2_WARN") // Return to the ~r~battle.~s~
RETURN TRUE
ENDIF
IF IS_ANY_TEXT_BEING_DISPLAYED(sLocateData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Initial sets up Trevors Ranting during the battle
PROC SETUP_TREVOR_DIALOG()
ADD_PED_FOR_DIALOGUE(convoPlayer, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
iNextFreakDialogTime = GET_RANDOM_INT_IN_RANGE(20000, 30000)
iNextFightDialogTime = GET_RANDOM_INT_IN_RANGE(10000, 20000)
bHasInitialOutburst = FALSE
ENDPROC
/// PURPOSE:
/// Runs the fight rants Trevor can shout out during the battle
PROC PLAY_TREVOR_FREAK_DIALOG_LINES()
IF IS_SCRIPTED_CONVERSATION_ONGOING()
EXIT
ENDIF
// stop if we're outside the battle area
IF NOT bIsPlayerInBattleArea
EXIT
ENDIF
IF (GET_GAME_TIMER() < iNextFreakDialogTime)
EXIT
ENDIF
IF (NOT bHasInitialOutburst)
EXIT
ENDIF
IF ARE_OBJECTIVES_OR_TEXT_BEING_DISPLAYED()
EXIT
ENDIF
#IF IS_DEBUG_BUILD
IF bDebugTTYSpew = TRUE
CPRINTLN(DEBUG_MISSION, "Trying to play Freak Rant - Time:", (GET_GAME_TIMER() - iMissionDebugTime) / 1000)
ENDIF
#ENDIF
ADD_PED_FOR_DIALOGUE(convoPlayer, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
IF CREATE_CONVERSATION(convoPlayer, "BARY2AU", "BARY2_FREAK", CONV_PRIORITY_LOW)
CPRINTLN(DEBUG_MISSION, "Freak Rant - Time:", (GET_GAME_TIMER() - iMissionDebugTime) / 1000)
iNextFreakDialogTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(20000, 40000)
// don't let fight line play too quickly after
IF iNextFightDialogTime - GET_GAME_TIMER() < kiDialogTimeCheck
CPRINTLN(DEBUG_MISSION, "Fight Rant Time too soon: resetting.")
iNextFightDialogTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(3000, 5000)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Runs the fight rants Trevor can shout out during the battle
PROC PLAY_TREVOR_FIGHT_DIALOG_LINES()
IF IS_SCRIPTED_CONVERSATION_ONGOING()
EXIT
ENDIF
IF (GET_GAME_TIMER() < iNextFightDialogTime)
EXIT
ENDIF
IF (NOT bHasInitialOutburst)
EXIT
ENDIF
IF ARE_OBJECTIVES_OR_TEXT_BEING_DISPLAYED()
EXIT
ENDIF
#IF IS_DEBUG_BUILD
IF bDebugTTYSpew = TRUE
CPRINTLN(DEBUG_MISSION, "Trying to play Trevor Fight Rant - Time:", (GET_GAME_TIMER() - iMissionDebugTime) / 1000)
ENDIF
#ENDIF
ADD_PED_FOR_DIALOGUE(convoPlayer, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
IF CREATE_CONVERSATION(convoPlayer, "BARY2AU", "BARY2_FIGHT", CONV_PRIORITY_LOW)
CPRINTLN(DEBUG_MISSION, "Fight Rant - Time:", (GET_GAME_TIMER() - iMissionDebugTime) / 1000)
iNextFightDialogTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(10000, 20000)
// don't let freak line play too quickly after
IF iNextFreakDialogTime - GET_GAME_TIMER() < kiDialogTimeCheck
CPRINTLN(DEBUG_MISSION, "Freak Rant Time too soon: resetting.")
iNextFreakDialogTime = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(3000, 5000)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// This handles playing Trevor's shouts during battle
PROC PLAY_TREVOR_CLOWN_GENERATOR_RANT()
IF ARE_OBJECTIVES_BEING_DISPLAYED()
IF IS_ANY_TEXT_BEING_DISPLAYED(sLocateData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
EXIT
ENDIF
ENDIF
IF IS_SCRIPTED_CONVERSATION_ONGOING()
EXIT
ENDIF
ADD_PED_FOR_DIALOGUE(convoPlayer, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
IF CREATE_CONVERSATION(convoPlayer, "BARY2AU", "BARY2_ONEOFF", CONV_PRIORITY_MEDIUM)
CPRINTLN(DEBUG_MISSION, "Trevor Destroy Clown Car Ranting")
bHasTrevorClownGeneratorRanted = TRUE
ENDIF
ENDPROC
/// PURPOSE:
/// This handles playing a specific Trevor shouts during battle
PROC HANDLE_PLAY_TREVOR_CLOWN_DUPLICATION_RANT()
IF bHasTrevorDupClownRanted
EXIT
ENDIF
IF iClownPedsSpawned < kiNumDuplicates
EXIT
ENDIF
START_TIMER_NOW(tmrGeneral)
IF NOT TIMER_DO_WHEN_READY(tmrGeneral, 1.500)
EXIT
ENDIF
IF ARE_OBJECTIVES_BEING_DISPLAYED()
IF IS_ANY_TEXT_BEING_DISPLAYED(sLocateData, IAT_IGNORE_GOD_TEXT_IF_SUBTITLES_OFF)
EXIT
ENDIF
ENDIF
IF IS_SCRIPTED_CONVERSATION_ONGOING()
EXIT
ENDIF
ADD_PED_FOR_DIALOGUE(convoPlayer, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
IF CREATE_CONVERSATION(convoPlayer, "BARY2AU", "BARY2_DUPE", CONV_PRIORITY_HIGH)
CPRINTLN(DEBUG_MISSION, "Trevor Duplicate Clown Ranting")
bHasTrevorDupClownRanted = TRUE
ENDIF
ENDPROC
//----------------------
// @SBA - SPECTATOR FUNCTIONS
//----------------------
/// PURPOSE:
/// Initializes data for a spectator
/// PARAMS:
/// iIndex - index in the struct array
/// mnModel - ped model to use
/// vSpawnPos - where to spawn
/// fSpawnHead - what heading to use when spawned
PROC INITIALIZE_SPECTATOR_DATA(INT iIndex, VECTOR vSpawnPos, FLOAT fSpawnHead)
CPRINTLN(DEBUG_MISSION, "INITIALIZE_SPECTATOR_DATA: Initializing Spectator ", iIndex)
IF GET_RANDOM_BOOL()
ssSpectator[iIndex].mnModel = mnSpectatorFemale
ELSE
ssSpectator[iIndex].mnModel = mnSpectatorMale
ENDIF
ssSpectator[iIndex].vSpawnPos = vSpawnPos
ssSpectator[iIndex].fSpawnHead = fSpawnHead
ssSpectator[iIndex].bIsActive = FALSE
ENDPROC
/// PURPOSE:
/// Initializes the data for all the spectators
PROC INITIALIZE_PERFORMANCE_SPECTATOR_DATA()
INITIALIZE_SPECTATOR_DATA(0, (<<177.0773, -961.4605, 30.0923>>), 27.2)
INITIALIZE_SPECTATOR_DATA(1, (<<177.190, -959.988, 30.0923>>), 22.8)
INITIALIZE_SPECTATOR_DATA(2, (<<178.863, -960.405, 30.0923>>), 62.8)
INITIALIZE_SPECTATOR_DATA(3, (<<178.8338, -959.1136, 30.0923>>), 67.8)
INITIALIZE_SPECTATOR_DATA(4, (<<178.2160, -956.9438, 30.0923>>), 115.1)
ENDPROC
/// PURPOSE:
/// Returns True if a spectator ped is ready to be re-used
/// PARAMS:
/// out - index in array to next free clown (this gets overwritten)
FUNC BOOL GET_FREE_SPECTATOR_INDEX(INT &out)
INT i = 0
out = -1
REPEAT (COUNT_OF(ssSpectator)) i
IF (ssSpectator[i].bIsActive = FALSE)
out = i
RETURN TRUE
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Creates a spectator for the given array index
/// RETURNS:
/// TRUE when they are created
FUNC BOOL CREATE_SPECTATOR_PED(INT iIndex)
FLOAT z
IF GET_GROUND_Z_FOR_3D_COORD(ssSpectator[iIndex].vSpawnPos, z)
ssSpectator[iIndex].vSpawnPos.z = z
ENDIF
IF (ssSpectator[iIndex].vSpawnPos.z < 28.0)
CPRINTLN(DEBUG_MISSION, "FAILED - TRYING TO CREATE SPECTATOR ", iIndex," AT POS ", ssSpectator[iIndex].vSpawnPos ," Z IS TOO LOW.")
RETURN FALSE
ENDIF
ssSpectator[iIndex].piPed = CREATE_PED(PEDTYPE_MISSION, ssSpectator[iIndex].mnModel, ssSpectator[iIndex].vSpawnPos, ssSpectator[iIndex].fSPawnHead)
IF NOT DOES_ENTITY_EXIST(ssSpectator[iIndex].piPed)
CPRINTLN(DEBUG_MISSION, "FAILED - TRYING TO CREATE SPECTATOR ", iIndex," AT POS ", ssSpectator[iIndex].vSpawnPos ," - PED ISN'T VALID")
RETURN FALSE
ENDIF
DISABLE_PED_INJURED_ON_GROUND_BEHAVIOUR(ssSpectator[iIndex].piPed)
STOP_PED_SPEAKING(ssSpectator[iIndex].piPed, TRUE)
SET_PED_DIES_WHEN_INJURED(ssSpectator[iIndex].piPed, TRUE)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(ssSpectator[iIndex].piPed, TRUE)
SET_PED_MONEY(ssSpectator[iIndex].piPed, 0)
SET_ENTITY_HEALTH(ssSpectator[iIndex].piPed, 100)
ssSpectator[iIndex].ssState = SS_FADE_IN
ssSpectator[iIndex].bIsActive = TRUE
ssSpectator[iIndex].bJustFlee = FALSE
CPRINTLN(DEBUG_MISSION, "CREATED SPECTATOR ", iIndex," AT POS ", ssSpectator[iIndex].vSpawnPos)
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Cleans up a single spectator ped
/// PARAMS:
/// ent - reference to spectator ped
/// keepTask - set this to keep tasks after cleanup
PROC CLEANUP_SPECTATOR_PED(SPECTATOR_STRUCT &ent, BOOL keepTask = TRUE)
// IF (ent.bIsActive = FALSE)
// EXIT
// ENDIF
SAFE_RELEASE_PED(ent.piPed, keepTask, TRUE)
ENDPROC
/// PURPOSE:
/// Deletes a single spectator ped
/// PARAMS:
/// ent - reference to spectator ped
PROC DELETE_SPECTATOR_PED(SPECTATOR_STRUCT &ent)
// clear active flag
IF (ent.bIsActive = TRUE)
ent.bIsActive = FALSE
ENDIF
SAFE_DELETE_PED(ent.piPed)
ENDPROC
/// PURPOSE:
/// Cleans all spectator peds
/// PARAMS:
/// keepTask - set this to keep tasks after cleanup
PROC CLEANUP_ALL_SPECTATOR_PEDS(BOOL keepTask = TRUE)
INT i = 0
REPEAT COUNT_OF(ssSpectator) i
CLEANUP_SPECTATOR_PED(ssSpectator[i], keepTask)
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Deletes all spectator peds
PROC DELETE_ALL_SPECTATOR_PEDS()
INT i = 0
REPEAT COUNT_OF(ssSpectator) i
DELETE_SPECTATOR_PED(ssSpectator[i])
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Returns active number of spectator peds
FUNC INT GET_ALIVE_SPECTATOR_PED_COUNT()
INT i = 0
INT cnt = 0
REPEAT (COUNT_OF(ssSpectator)) i
IF DOES_ENTITY_EXIST(ssSpectator[i].piPed)
IF NOT IS_PED_INJURED(ssSpectator[i].piPed)
cnt ++
ENDIF
ENDIF
ENDREPEAT
//CPRINTLN(DEBUG_MISSION, "GET_ALIVE_SPECTATOR_PED_COUNT: Number of alive spectators = ", cnt)
RETURN cnt
ENDFUNC
/// PURPOSE:
/// Spawn the spectators for a clown performance
/// PARAMS:
/// SpawnData - preset Spawn data
/// iNumberOfSpectators - How many spectators to make
/// bJustFlee - If set TRUE, spectators will instantly go into flee state once faded in
PROC SPAWN_SPECTATORS_FOR_GENERAL_PERFORMANCE(CLOWN_PERFORMANCE_DATA &SpawnData, INT iNumberOfSpectators, BOOL bJustFlee = FALSE)
INT idx // The counter
INT iIndex // Valid index of spectator
IF iNumberOfSpectators > kiNumberOfSpectators
CPRINTLN(DEBUG_MISSION, "*** SPAWN_SPECTATORS_FOR_GENERAL_PERFORMANCE: Too many spectators requested! iNumberOfSpectators = ", iNumberOfSpectators)
EXIT
ENDIF
FLOAT fHead
REPEAT iNumberOfSpectators idx
CPRINTLN(DEBUG_MISSION, "SPAWN_SPECTATORS_FOR_GENERAL_PERFORMANCE: idx = ", idx)
IF GET_FREE_SPECTATOR_INDEX(iIndex)
CPRINTLN(DEBUG_MISSION, "SPAWN_SPECTATORS_FOR_GENERAL_PERFORMANCE: Found free spectator index: ", iIndex)
VECTOR vPos = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(SpawnData.vClownPos, SpawnData.fClownHead, vSpectatorPerformOffsets[idx])
// We want the spectators to face the opposite direction if there is no clown
IF bJustFlee
fHead = GET_HEADING_BETWEEN_VECTORS_2D(SpawnData.vClownPos, vPos)
ELSE
fHead = GET_HEADING_BETWEEN_VECTORS_2D(vPos, SpawnData.vClownPos)
ENDIF
INITIALIZE_SPECTATOR_DATA(iIndex, vPos, fHead)
CREATE_SPECTATOR_PED(iIndex)
IF iApplauseSound = -1
AND NOT bJustFlee
PLAY_SOUND_FROM_ENTITY(iApplauseSound, "CROWD_WATCHING", ssSpectator[iIndex].piPed)
ENDIF
ssSpectator[iIndex].bJustFlee = bJustFlee
ELSE
CPRINTLN(DEBUG_MISSION, "SPAWN_SPECTATORS_FOR_GENERAL_PERFORMANCE: Spectator index NOT free: ", iIndex)
ENDIF
ENDREPEAT
ENDPROC
/// PURPOSE:
/// @SBA - determines if the spectator with the given index should run away
/// PARAMS:
/// iSpecIndex - index of current spectator we're checking
/// RETURNS:
/// TRUE if spectator should start running
FUNC BOOL SHOULD_SPECTATOR_FLEE(INT iSpecIndex)
// bail if this is the intro lead-out, as we want them to stay to get killed
IF stageEnum = SE_PERFORMANCE
RETURN FALSE
ENDIF
VECTOR vPedLoc = GET_ENTITY_COORDS(ssSpectator[iSpecIndex].piPed, FALSE)
IF ssSpectator[iSpecIndex].bJustFlee
CPRINTLN(DEBUG_MISSION, "SHOULD_SPECTATOR_FLEE: This spectator was set to flee: ", iSpecIndex)
RETURN TRUE
ENDIF
IF HAS_BULLET_IMPACTED_IN_AREA(vPedLoc, kiCHaseSpectatorsDist - 1)
CPRINTLN(DEBUG_MISSION, "SHOULD_SPECTATOR_FLEE: Bullet impact! This spectator should flee: ", iSpecIndex)
RETURN TRUE
ENDIF
INT idx
REPEAT COUNT_OF(ssSpectator) idx
IF idx != iSpecIndex
IF DOES_ENTITY_EXIST(ssSpectator[idx].piPed)
IF IS_PED_DEAD_OR_DYING(ssSpectator[idx].piPed)
OR IS_PED_INJURED(ssSpectator[idx].piPed)
IF GET_DISTANCE_BETWEEN_COORDS(vPedLoc, GET_ENTITY_COORDS(ssSpectator[idx].piPed, FALSE), FALSE) < kfMinSpectatorWitnessDist
CPRINTLN(DEBUG_MISSION, "SHOULD_SPECTATOR_FLEE: Nearby spectator death! This spectator should flee: ", iSpecIndex)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// @SBA - start and maintain spectator clown-watching anim
/// PARAMS:
/// iIndex - index into the spectator array
PROC HANDLE_SPECTATOR_CLOWN_WATCHING_ANIM(INT iIndex)
IF ssSpectator[iIndex].mnModel = mnSpectatorMale
IF NOT IS_ENTITY_PLAYING_ANIM(ssSpectator[iIndex].piPed, sSpectatorMaleAnimDict, sSpectatorMaleAnimClip)
TASK_PLAY_ANIM(ssSpectator[iIndex].piPed, sSpectatorMaleAnimDict, sSpectatorMaleAnimClip, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1,
AF_LOOPING, GET_RANDOM_FLOAT_IN_RANGE(0,0.5))
ENDIF
ELSE
IF NOT IS_ENTITY_PLAYING_ANIM(ssSpectator[iIndex].piPed, sSpectatorFemAnimDict, sSpectatorFemAnimClip)
TASK_PLAY_ANIM(ssSpectator[iIndex].piPed, sSpectatorFemAnimDict, sSpectatorFemAnimClip, NORMAL_BLEND_IN, NORMAL_BLEND_OUT, -1,
AF_LOOPING, GET_RANDOM_FLOAT_IN_RANGE(0,0.5))
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// @SBA - handles thew state machine for spectators
/// PARAMS:
/// iIndex -
PROC UPDATE_SPECTATOR(INT iIndex)
IF NOT DOES_ENTITY_EXIST(ssSpectator[iIndex].piPed)
EXIT
ENDIF
IF NOT ssSpectator[iIndex].bIsActive
EXIT
ENDIF
IF IS_ENTITY_DEAD(ssSpectator[iIndex].piPed)
OR IS_PED_DEAD_OR_DYING(ssSpectator[iIndex].piPed)
// Checking here for safety, since one shot from player may kill spectator
IF ssSpectator[iIndex].ssState < SS_GOING
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: Spectator ", iIndex," has been killed!")
IF HAS_PED_BEEN_DAMAGED_BY_WEAPON(ssSpectator[iIndex].piPed, playerWeapon)
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: Spectator ", iIndex," has been killed by player!")
ENDIF
SAFE_STOP_AND_RELEASE_SOUND_ID(iApplauseSound)
ssSpectator[iIndex].iTimer = GET_GAME_TIMER() + CLOWN_FADE_TIME
ssSpectator[iIndex].ssState = SS_GOING
ENDIF
ENDIF
SWITCH ssSpectator[iIndex].ssState
CASE SS_FADE_IN
ssSpectator[iIndex].fSpectAlpha += GET_FRAME_TIME() * 512.0 // HALF SECOND FADE OUT
IF (ssSpectator[iIndex].fSpectAlpha < 2.0)
SET_ENTITY_VISIBLE(ssSpectator[iIndex].piPed, FALSE)
ELSE
SET_ENTITY_VISIBLE(ssSpectator[iIndex].piPed, TRUE)
IF (ssSpectator[iIndex].fSpectAlpha > 255.0)
ssSpectator[iIndex].fSpectAlpha = 255.0
RESET_ENTITY_ALPHA(ssSpectator[iIndex].piPed)
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: Spectator ", iIndex, " has faded in.")
ssSpectator[iIndex].ssState = SS_WATCH_CLOWN
ELSE
IF IS_ENTITY_ON_SCREEN(ssSpectator[iIndex].piPed)
SET_PED_ALPHA(ssSpectator[iIndex].piPed, FLOOR(ssSpectator[iIndex].fSpectAlpha), iSpecAlphaCounter)
ELSE
RESET_ENTITY_ALPHA(ssSpectator[iIndex].piPed)
ENDIF
ENDIF
ENDIF
BREAK
CASE SS_WATCH_CLOWN
// @SBA - if a spectator is shot, advance to killing them
IF HAS_ENTITY_BEEN_DAMAGED_BY_ANY_PED(ssSpectator[iIndex].piPed)
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: SS_WATCH_CLOWN: Spectator ", iIndex," has been damaged!")
ssSpectator[iIndex].ssState = SS_KILL
// @SBA - if the player's weapon type was used, set flag so remaining spec's flee
IF HAS_PED_BEEN_DAMAGED_BY_WEAPON(ssSpectator[iIndex].piPed, playerWeapon)
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: Spectator ", iIndex," was damaged by player!")
ENDIF
SAFE_STOP_AND_RELEASE_SOUND_ID(iApplauseSound)
ELIF SHOULD_SPECTATOR_FLEE(iIndex)
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: SS_WATCH_CLOWN: Spectator ", iIndex," is going to flee!")
ssSpectator[iIndex].ssState = SS_REACT_TO_DANGER
SAFE_STOP_AND_RELEASE_SOUND_ID(iApplauseSound)
ELSE
HANDLE_SPECTATOR_CLOWN_WATCHING_ANIM(iIndex)
ENDIF
BREAK
CASE SS_REACT_TO_DANGER
// Have remaining living spectators flee
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_ENTITY_ALIVE(ssSpectator[iIndex].piPed)
// If spectator was told to just flee, change flee origin to behind them
VECTOR vFleeOrigin
IF ssSpectator[iIndex].bJustFlee
vFleeOrigin = <<0,-2.5,0>>
ELSE
vFleeOrigin = <<0,1.75,0>>
ENDIF
SEQUENCE_INDEX seq
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: SS_REACT_TO_DANGER for Spectator ", iIndex)
OPEN_SEQUENCE_TASK(seq)
// @SBA - the pause looks bad and cower isn't quick enough. Something else?
//TASK_PAUSE(NULL, GET_RANDOM_INT_IN_RANGE(200, 600))
TASK_SMART_FLEE_COORD(NULL, GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ssSpectator[iIndex].piPed, vFleeOrigin), 200.0, -1)
CLOSE_SEQUENCE_TASK(seq)
CLEAR_PED_TASKS(ssSpectator[iIndex].piPed)
TASK_PERFORM_SEQUENCE(ssSpectator[iIndex].piPed, seq)
CLEAR_SEQUENCE_TASK(seq)
// @SBA - commenting out per audio feedback
//IF GET_RANDOM_BOOL()
// MAKE_PED_SCREAM(ssSpectator[iIndex].piPed)
//ENDIF
// send this to a fleeing handler
ssSpectator[iIndex].ssState = SS_FLEEING
ENDIF
ENDIF
BREAK
CASE SS_FLEEING
// See if fleeing spectator has gotten far enough
IF NOT IS_ENTITY_IN_ANGLED_AREA(ssSpectator[iIndex].piPed, battleAreaOuter.vPosition[0], battleAreaOuter.vPosition[1], battleAreaOuter.fWidth)
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: Spectator ", iIndex, " is done fleeing. Going to SS_GOING.")
ssSpectator[iIndex].iTimer = GET_GAME_TIMER() + 500
ssSpectator[iIndex].ssState = SS_KILL
ENDIF
BREAK
CASE SS_KILL
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: SS_KILL for Spectator ", iIndex)
EXPLODE_PED_HEAD(ssSpectator[iIndex].piPed)
APPLY_DAMAGE_TO_PED(ssSpectator[iIndex].piPed, 1000, TRUE)
ssSpectator[iIndex].iTimer = GET_GAME_TIMER() + 500
ssSpectator[iIndex].ssState = SS_GOING
BREAK
CASE SS_GOING
IF (GET_GAME_TIMER() > ssSpectator[iIndex].iTimer)
IF IS_ENTITY_DEAD(ssSpectator[iIndex].piPed) OR IS_PED_INJURED(ssSpectator[iIndex].piPed)
// @SBA - keeping this in case we want to get fancier
// IF NOT IS_ENTITY_IN_AIR(ssSpectator[iIndex].piPed)
// vec = GET_ENTITY_COORDS(ssSpectator[iIndex].piPed)
// IF GET_GROUND_Z_FOR_3D_COORD(vec, z)
// vec.z = z
// vec.z += 1.0
// ENDIF
//
// START_PARTICLE_FX_NON_LOOPED_AT_COORD("scr_clown_death", vec, GET_ENTITY_ROTATION(ssSpectator[iIndex].piPed), 2.0)
// PLAY_SOUND_FROM_COORD(-1, "clown_die_wrapper", vec, "BARRY_02_SOUNDSET")
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: SS_GOING for Spectator ", iIndex)
ssSpectator[iIndex].iTimer = GET_GAME_TIMER() + CLOWN_FADE_TIME
ssSpectator[iIndex].fSpectAlpha = 255.0
ssSpectator[iIndex].ssState = SS_GONE
// ENDIF
ENDIF
ENDIF
BREAK
CASE SS_GONE
IF (GET_GAME_TIMER() > ssSpectator[iIndex].iTimer)
ssSpectator[iIndex].fSpectAlpha -= GET_FRAME_TIME() * 1024.0 // HALF SECOND FADE OUT
IF (ssSpectator[iIndex].fSpectAlpha < 0.0)
ssSpectator[iIndex].fSpectAlpha = 0.0
ENDIF
SET_PED_ALPHA(ssSpectator[iIndex].piPed, FLOOR(ssSpectator[iIndex].fSpectAlpha), iSpecAlphaCounter) // @SBA - do we want a separate counter?
IF (ssSpectator[iIndex].fSpectAlpha <= 0.0) OR NOT IS_ENTITY_ON_SCREEN(ssSpectator[iIndex].piPed)
CPRINTLN(DEBUG_MISSION, "UPDATE_SPECTATOR: SS_GONE for Spectator ", iIndex)
ssSpectator[iIndex].bIsActive = FALSE
DELETE_SPECTATOR_PED(ssSpectator[iIndex])
ssSpectator[iIndex].ssState = SS_DONE
ENDIF
ENDIF
BREAK
CASE SS_DONE
// nothing
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// @SBA - iterates over whole spectator array and updates state machine
PROC UPDATE_SPECTATOR_PEDS()
INT i = 0
REPEAT (COUNT_OF(ssSpectator)) i
UPDATE_SPECTATOR(i)
ENDREPEAT
ENDPROC
/// PURPOSE:
/// @SBA - Finds the closest spectator to the passed in ped
/// PARAMS:
/// piPedToCheck - the ped from which you are measuring the distance
/// piClosestSpectator - returns index of closest spectator
/// RETURNS:
/// TRUE if there is a valid ped that is close enough
FUNC BOOL GET_CLOSEST_SPECTATOR_TO_PED(PED_INDEX piPedToCheck, PED_INDEX &piClosestSpectator, FLOAT fIgnoreDist = kiLongIgnoreSpectatorsDist)
IF IS_PED_INJURED(piPedToCheck)
RETURN FALSE
ENDIF
INT i
FLOAT fNewDistance, fClosestDistance = 1000
// reset this
piClosestSpectator = NULL
// iterate over spectators to find the closest who's still alive
FOR i = 0 TO COUNT_OF(ssSpectator) - 1
IF DOES_ENTITY_EXIST(ssSpectator[i].piPed)
IF NOT IS_ENTITY_DEAD(ssSpectator[i].piPed)
IF NOT IS_PED_INJURED(ssSpectator[i].piPed)
AND NOT IS_PED_DEAD_OR_DYING(ssSpectator[i].piPed)
fNewDistance = GET_DISTANCE_BETWEEN_PEDS(piPedToCheck, ssSpectator[i].piPed)
IF fNewDistance < fClosestDistance
fClosestDistance = fNewDistance
piClosestSpectator = ssSpectator[i].piPed
ENDIF
ENDIF
ENDIF
ENDIF
ENDFOR
// If there is a valid target that is not too far away, return TRUE
IF piClosestSpectator != NULL
AND fClosestDistance < fIgnoreDist
RETURN TRUE
ENDIF
// reset this to NULL since we're not returning TRUE
piClosestSpectator = NULL
RETURN FALSE
ENDFUNC
//----------------------
// CLOWN FUNCTIONS
//----------------------
/// PURPOSE:
/// This is stuff which is common to both cleaning up and deleting a clown ped
/// PARAMS:
/// ent - reference to clown ped
PROC SHARED_CLEANUP_AND_DELETE_CLOWN_PED(CLOWN_PED &ent)
SAFE_STOP_AND_RELEASE_SOUND_ID(ent.laughSoundID)
SAFE_REMOVE_BLIP(ent.blipID)
ent.bIsActive = FALSE
ent.pedID = NULL
ent.blipID = NULL
ent.bIsDead = FALSE
ENDPROC
/// PURPOSE:
/// Cleans up a single clown ped
/// PARAMS:
/// ent - reference to clown ped
/// keepTask - set this to keep tasks after cleanup
PROC CLEANUP_CLOWN_PED(CLOWN_PED &ent, BOOL keepTask = TRUE)
IF (ent.bIsActive = FALSE)
EXIT
ENDIF
SAFE_RELEASE_PED(ent.pedID, keepTask, TRUE)
SHARED_CLEANUP_AND_DELETE_CLOWN_PED(ent)
ENDPROC
/// PURPOSE:
/// Deletes a single clown ped
/// PARAMS:
/// ent - reference to clown ped
PROC DELETE_CLOWN_PED(CLOWN_PED &ent)
IF (ent.bIsActive = FALSE)
EXIT
ENDIF
SAFE_DELETE_PED(ent.pedID)
SHARED_CLEANUP_AND_DELETE_CLOWN_PED(ent)
ENDPROC
/// PURPOSE:
/// Cleans all clown peds
/// PARAMS:
/// keepTask - set this to keep tasks after cleanup
PROC CLEANUP_ALL_CLOWN_PEDS(BOOL keepTask = TRUE)
INT i = 0
REPEAT COUNT_OF(clownPed) i
CLEANUP_CLOWN_PED(clownPed[i], keepTask)
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Deletes all clown peds
PROC DELETE_ALL_CLOWN_PEDS()
INT i = 0
REPEAT COUNT_OF(clownPed) i
DELETE_CLOWN_PED(clownPed[i])
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Returns True if clown ped is living
/// PARAMS:
/// rp - reference to clown ped
FUNC BOOL IS_CLOWN_PED_ALIVE(CLOWN_PED &rp)
IF NOT rp.bIsActive
RETURN FALSE
ENDIF
IF NOT DOES_ENTITY_EXIST(rp.pedID)
RETURN FALSE
ENDIF
RETURN NOT rp.bIsDead AND NOT (rp.aState = CS_DEAD) AND NOT IS_PED_INJURED(rp.pedID)
ENDFUNC
/// PURPOSE:
/// Go through clown array and find the first living clown
/// RETURNS:
/// the index of that clown
FUNC INT GET_INDEX_OF_FIRST_LIVING_CLOWN_IN_ARRAY()
INT i = 0
REPEAT (COUNT_OF(clownPed)) i
IF IS_CLOWN_PED_ALIVE(clownPed[i])
CPRINTLN(DEBUG_MISSION, "GET_INDEX_OF_FIRST_LIVING_CLOWN_IN_ARRAY: Returning an index for clown: ", i)
RETURN i
ENDIF
ENDREPEAT
RETURN -1
ENDFUNC
/// PURPOSE:
/// Returns True if clown ped is in dying state (or dead)
/// PARAMS:
/// rp - reference to clown ped
FUNC BOOL IS_CLOWN_DYING(CLOWN_PED &rp)
RETURN (rp.aState = CS_DYING) OR (rp.aState = CS_DEAD)
ENDFUNC
/// PURPOSE:
/// Returns True if clown ped is ready to be re-used
/// PARAMS:
/// rp - reference to clown ped
FUNC BOOL IS_CLOWN_PED_FREE(CLOWN_PED &rp)
IF NOT rp.bIsActive
RETURN TRUE
ENDIF
IF NOT DOES_ENTITY_EXIST(rp.pedID)
RETURN TRUE
ENDIF
RETURN NOT rp.bIsDead AND NOT (rp.aState = CS_DEAD)
ENDFUNC
/// PURPOSE:
/// Sets the type of the clown.
/// PARAMS:
/// clown - the struct of the clown
/// TypeOfClown - The clown's starting type enum that you want to switch the clown to
PROC SET_CLOWN_TYPE(CLOWN_PED &clown, STARTING_CLOWN_TYPES TypeOfClown)
clown.ClownType = TypeOfClown
CPRINTLN(DEBUG_MISSION, "SET_CLOWN_TYPE: Clown type has been set to: ", ENUM_TO_INT(clown.ClownType))
ENDPROC
/// PURPOSE:
/// Gets the clown's starting type
/// PARAMS:
/// clown - struct
/// RETURNS:
/// The clown's starting type enum
FUNC STARTING_CLOWN_TYPES GET_CLOWN_TYPE(CLOWN_PED &clown)
RETURN clown.ClownType
ENDFUNC
/// PURPOSE:
/// Returns active number of clown peds
FUNC INT GET_ALIVE_CLOWN_PED_COUNT()
INT i = 0
INT cnt = 0
REPEAT (COUNT_OF(clownPed)) i
IF IS_CLOWN_PED_ALIVE(clownPed[i])
cnt ++
ENDIF
ENDREPEAT
RETURN cnt
ENDFUNC
/// PURPOSE:
/// Returns True if a clown ped is ready to be re-used
/// PARAMS:
/// out - index in array to next free clown (this gets overwritten)
FUNC BOOL GET_FREE_CLOWN_PED_INDEX(INT &out)
INT i = 0
out = -1
REPEAT (COUNT_OF(clownPed)) i
IF (clownPed[i].bIsActive = FALSE)
out = i
RETURN TRUE
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Determines if the clown should do a performance for spectators
/// PARAMS:
/// clown - struct
/// RETURNS:
/// TRUE if the clown is set to perform and there are avaialble spectators to spawn; False otherwise.
FUNC BOOL SHOULD_CLOWN_PERFORM(CLOWN_PED &clown)
// If he's not set to perform, then he shouldn't perform
IF GET_CLOWN_TYPE(clown) != SCT_PERFORM
RETURN FALSE
ENDIF
// Are there any available spectator slots? If so, ok to perform
IF GET_ALIVE_SPECTATOR_PED_COUNT() < kiNumberOfSpectators
CPRINTLN(DEBUG_MISSION, "SHOULD_CLOWN_PERFORM: Returning TRUE!")
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// @SBA - checks if the clown has a valid spectator target
/// PARAMS:
/// clown - the clown struct
/// RETURNS:
/// TRUE if the clown has a valid, living target, FALSE if not
FUNC BOOL DOES_CLOWN_HAVE_SPECTATOR_TARGET(CLOWN_PED &clown)
IF IS_CLOWN_PED_ALIVE(clown)
IF clown.piClosestSpec != NULL
IF NOT IS_ENTITY_DEAD(clown.piClosestSpec)
IF NOT IS_PED_INJURED(clown.piClosestSpec)
AND NOT IS_PED_DEAD_OR_DYING(clown.piClosestSpec)
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// @SBA - checks if any clown currently has a valid spectator target
/// RETURNS:
/// TRUE if any clown has a valid target, FALSE if not
FUNC BOOL DOES_ANY_CLOWN_HAVE_SPECTATOR_TARGET()
INT i = 0
REPEAT COUNT_OF(clownPed) i
IF DOES_CLOWN_HAVE_SPECTATOR_TARGET(clownPed[i])
RETURN TRUE
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Toggle clown's aggressiveness (used for combatting spectators)
/// PARAMS:
/// clown -
/// bMakeAggressive - TRUE = make agressive; FALSE = remove agressiveness
/// bForPlayer - If TRUE, soften the deadliness for combat with the player
PROC MAKE_CLOWN_MORE_AGGRESSIVE(CLOWN_PED &clown, BOOL bMakeAggressive, BOOL bForPlayer = FALSE)
// Hijack the reset if this is the last clown to keep him aggressive to the player
IF bLastClownAggressive
IF NOT bMakeAggressive
bMakeAggressive = TRUE
bForPlayer = TRUE
CPRINTLN(DEBUG_MISSION, "MAKE_CLOWN_MORE_AGGRESSIVE: LAST CLOWN!")
ENDIF
ENDIF
CPRINTLN(DEBUG_MISSION, "MAKE_CLOWN_MORE_AGGRESSIVE: Clown Aggressiveness = ", bMakeAggressive, ". For Player = ", bForPlayer)
IF NOT bForPlayer
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_PROXIMITY_FIRING_RATE, bMakeAggressive)
ELSE
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_CAN_CHARGE, TRUE)
ENDIF
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_AGGRESSIVE, bMakeAggressive)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_COVER, NOT bMakeAggressive)
// Turning on
IF bMakeAggressive
IF NOT bForPlayer
SET_PED_COMBAT_ABILITY(clown.pedID, CAL_PROFESSIONAL)
SET_PED_ACCURACY(clown.pedID, 70)
ELSE
SET_PED_ACCURACY(clown.pedID, 12)
SET_PED_COMBAT_ABILITY(clown.pedID, CAL_AVERAGE)
REMOVE_PED_DEFENSIVE_AREA(clown.pedID, TRUE)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(clown.pedID, PLAYER_PED_ID(), <<0, 0, 0>>, GET_RANDOM_FLOAT_IN_RANGE(20.0, 40.0), FALSE)
ENDIF
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_WILLADVANCE)
SET_PED_COMBAT_RANGE(clown.pedID, CR_NEAR)
// Turning off
ELSE
SET_PED_ACCURACY(clown.pedID, 12)
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_DEFENSIVE)
SET_PED_COMBAT_RANGE(clown.pedID, CR_MEDIUM)
SET_PED_COMBAT_ABILITY(clown.pedID, CAL_AVERAGE)
ENDIF
ENDPROC
/// PURPOSE:
/// Get the last living clown and make him go after the player so the player won't have to hunt
/// PARAMS:
/// bGateVar - Passes in by ref the gating bool. Be sure to rest after the last clown is dead.
PROC MAKE_LAST_CLOWN_AGGRESSIVE(BOOL &bGateVar)
IF NOT bGateVar
IF iAliveClownCount = 1
INT iLastClownIdx = GET_INDEX_OF_FIRST_LIVING_CLOWN_IN_ARRAY()
IF iLastClownIdx != -1
MAKE_CLOWN_MORE_AGGRESSIVE(ClownPed[iLastClownIdx], TRUE, TRUE)
// Don't dance soon
ClownPed[iLastClownIdx].iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMaxClownDanceDelay, iMaxClownDanceDelay + iMinClownDanceDelay)
REMOVE_PED_DEFENSIVE_AREA(ClownPed[iLastClownIdx].pedID)
ELSE
CPRINTLN(DEBUG_MISSION, "MAKE_LAST_CLOWN_AGGRESSIVE: last clown not found!")
ENDIF
bGateVar = TRUE
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// @SBA - Have the Clown shoot the spectators.
/// PARAMS:
/// piClown -
PROC CLOWN_ATTACKS_SPECTATORS(CLOWN_PED &clown)
IF IS_PED_INJURED(clown.pedID)
OR IS_PED_INJURED(clown.piClosestSpec)
EXIT
ENDIF
SEQUENCE_INDEX seqAttack
IF (GET_SCRIPT_TASK_STATUS(clown.pedID, SCRIPT_TASK_PERFORM_SEQUENCE) <> PERFORMING_TASK)
CPRINTLN(DEBUG_MISSION, "CLOWN_ATTACKS_SPECTATORS: Clown shooting at spectator!")
OPEN_SEQUENCE_TASK(seqAttack)
// if target is close by, shoot first
IF GET_DISTANCE_BETWEEN_ENTITIES(clown.pedID, clown.piClosestSpec, FALSE) <= kiCHaseSpectatorsDist
TASK_AIM_GUN_AT_ENTITY(NULL, clown.piClosestSpec, GET_RANDOM_INT_IN_RANGE(250, 500))
TASK_SHOOT_AT_ENTITY(NULL, clown.piClosestSpec, GET_RANDOM_INT_IN_RANGE(250, 500), FIRING_TYPE_CONTINUOUS)
ENDIF
TASK_GO_TO_ENTITY_WHILE_AIMING_AT_ENTITY(NULL, clown.piClosestSpec, clown.piClosestSpec, PEDMOVE_RUN, TRUE, 3.0, 4.5)
TASK_COMBAT_PED(NULL, clown.piClosestSpec, COMBAT_PED_PREVENT_CHANGING_TARGET)
CLOSE_SEQUENCE_TASK(seqAttack)
//CLEAR_PED_TASKS(clown.pedID)
TASK_PERFORM_SEQUENCE(clown.pedID, seqAttack)
CLEAR_SEQUENCE_TASK(seqAttack)
IF GET_RANDOM_BOOL()
CPRINTLN(DEBUG_MISSION, "CLOWN_ATTACKS_SPECTATORS: Clown laughs!")
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(clown.pedID, "CLOWN_LAUGH", "CLOWNS", SPEECH_PARAMS_FORCE_SHOUTED_CLEAR)
ENDIF
ENDIF
ENDPROC
// ~~~~~~~~~~
/// PURPOSE:
/// Creates one clown ped
/// PARAMS
/// clown - clown ped reference
/// task - clown task
/// pos - clown spawn point
/// head - clown spawn heading
/// bForceHeavyWeapon - @SBA - some weapon variety
/// safecheck - do ground and safe check on pos before spawning
/// forcecombat - doesn't do delay after telportining in
/// areacheck - if this is true we check to see if no spawn areas are being used
FUNC BOOL CREATE_CLOWN_PED(CLOWN_PED &clown, VECTOR pos, FLOAT head = 0.0, BOOL bForceHeavyWeapon = FALSE, BOOL bNoWeapon = FALSE)
INT rnd
FLOAT z
// don't care about height for final wave - clowns need to spawn anywhere
IF stageEnum != SE_WAVE6
IF GET_GROUND_Z_FOR_3D_COORD(pos, z)
pos.z = z
ENDIF
IF (pos.z < 28.0)
RETURN FALSE
ENDIF
ENDIF
clown.pedID = CREATE_PED(PEDTYPE_MISSION, clownModel, pos, head)
IF NOT DOES_ENTITY_EXIST(clown.pedID)
CPRINTLN(DEBUG_MISSION, "FAILED - TRYING TO CREATE CLOWN PED AT POS ", pos ," - PED ISN'T VALID")
RETURN FALSE
ENDIF
clown.laughSoundID = -1
SET_ENTITY_HEADING_FACE_PLAYER(clown.pedID)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_PROXIMITY_FIRING_RATE, FALSE)
SET_PED_RANDOM_COMPONENT_VARIATION(clown.pedID)
SET_PED_RELATIONSHIP_GROUP_HASH(clown.pedID, RELGROUPHASH_HATES_PLAYER)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(clown.pedID, TRUE)
rnd = GET_ENTITY_MAX_HEALTH(clown.pedID) / 2
SET_ENTITY_HEALTH(clown.pedID, rnd)
SET_ENTITY_MAX_HEALTH(clown.pedID, rnd)
SET_ENTITY_IS_TARGET_PRIORITY(clown.pedID, TRUE)
SET_PED_MONEY(clown.pedID, 0)
//SET_ENTITY_HEALTH(clown.pedID, GET_ENTITY_MAX_HEALTH(clown.pedID))
SET_PED_ALERTNESS(clown.pedID, AS_MUST_GO_TO_COMBAT)
SET_PED_TARGET_LOSS_RESPONSE(clown.pedID, TLR_NEVER_LOSE_TARGET)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_AGGRESSIVE, FALSE)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_COVER, TRUE)
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_DEFENSIVE)
STOP_PED_SPEAKING(clown.pedID, TRUE)
SET_AMBIENT_VOICE_NAME(clown.pedID, "CLOWNS")
// @SBA - first performance clown starts with no weapon
IF NOT bNoWeapon
// @SBA - setup weapon randomly, weighted toward pistol
IF NOT bForceHeavyWeapon
rnd = GET_RANDOM_INT_IN_RANGE(0, 3)
IF rnd = 0
GIVE_WEAPON_TO_PED(clown.pedID, WEAPONTYPE_SMG, INFINITE_AMMO, TRUE)
ELSE
GIVE_WEAPON_TO_PED(clown.pedID, WEAPONTYPE_PISTOL, INFINITE_AMMO, TRUE)
ENDIF
// @SBA - otherwsie, give the heavier weapon
ELSE
GIVE_WEAPON_TO_PED(clown.pedID, WEAPONTYPE_SMG, INFINITE_AMMO, TRUE)
ENDIF
ENDIF
// setup combat movement
rnd = GET_RANDOM_INT_IN_RANGE(0, 3)
SWITCH (rnd)
CASE 0
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_DEFENSIVE) // Seeks a defensive position.
BREAK
CASE 1
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_WILLADVANCE) // Will advance forward in combat
BREAK
CASE 2
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_WILLRETREAT) // Will retreat if the enemy gets too close
BREAK
ENDSWITCH
clown.bIsActive = TRUE
clown.bIsDead = FALSE
clown.aState = CS_DELAY
clown.iDanceTimer = GET_GAME_TIMER()
// @SBA - setting normal type by default. Change it separately.
SET_CLOWN_TYPE(clown, SCT_NORMAL)
clown.vDeathPosition = <<0,0,0>>
SET_PED_CAN_PEEK_IN_COVER(clown.pedID, TRUE)
SAFE_REMOVE_BLIP(clown.blipID)
IF GET_RANDOM_BOOL()
SET_PED_PROP_INDEX(clown.pedID, ANCHOR_HEAD, 0)
ENDIF
SET_PED_CAN_COWER_IN_COVER(clown.pedID, FALSE)
SET_PED_CAN_PEEK_IN_COVER(clown.pedID, TRUE)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_VEHICLE, FALSE)
SET_PED_AS_ENEMY(clown.pedID, TRUE)
SET_PED_DIES_WHEN_INJURED(clown.pedID, TRUE)
SET_PED_SUFFERS_CRITICAL_HITS(clown.pedID, TRUE)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(clown.pedID, PLAYER_PED_ID(), <<0, 0, 0>>, GET_RANDOM_FLOAT_IN_RANGE(12.0, 50.0))
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(clown.pedID, TRUE)
SET_ENTITY_INVINCIBLE(clown.pedID, TRUE)
SET_ENTITY_VISIBLE(clown.pedID, FALSE)
FREEZE_ENTITY_POSITION(clown.pedID, TRUE)
clown.iTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(125, 1000)
APPLY_COMBAT_PARAMETERS_TO_PED(clown.pedID, combatParams)
clown.danceAnim = "clown_idle_"
clown.danceAnim += GET_RANDOM_INT_IN_RANGE(0, 6)
TASK_PLAY_ANIM(clown.pedID, sMissionAnimDanceDictionary, clown.danceAnim, NORMAL_BLEND_IN, REALLY_SLOW_BLEND_OUT, -1)
// for checking how long the clown has been around
clown.iLongevityTimer = GET_GAME_TIMER() + kiAggressiveTime
//TASK_AIM_GUN_AT_ENTITY(clown.pedID, PLAYER_PED_ID(), 6000, TRUE)
CPRINTLN(DEBUG_MISSION, "CREATED CLOWN PED AT POS ", pos)
iClownPedsSpawned ++
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Sets a ped to optionally hold a defense perimeter around a vehicle
/// PARAMS:
/// pass - ped index
/// veh - car to defend
PROC SET_PED_CAR_DEFENDER(PED_INDEX pass, VEHICLE_INDEX veh)
FLOAT x, y
SET_PED_COMBAT_ATTRIBUTES(pass, CA_LEAVE_VEHICLES, TRUE)
SET_PED_COMBAT_ATTRIBUTES(pass, CA_USE_VEHICLE, FALSE)
SET_PED_COMBAT_ATTRIBUTES(pass, CA_USE_COVER, TRUE)
TASK_COMBAT_PED(pass, PLAYER_PED_ID())
x = GET_RANDOM_FLOAT_IN_RANGE(-15.0, 15.0)
y = GET_RANDOM_FLOAT_IN_RANGE(-15.0, 15.0)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(pass, PLAYER_PED_ID(), <<x, y, 0>>, GET_RANDOM_FLOAT_IN_RANGE(20.0, 60.0), TRUE)
IF (GET_RANDOM_FLOAT_IN_RANGE() < 0.5)
SET_PED_SPHERE_DEFENSIVE_AREA(pass, GET_ENTITY_COORDS(veh), GET_RANDOM_FLOAT_IN_RANGE(10.0, 25.0), TRUE)
ELSE
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(pass, PLAYER_PED_ID(), <<0, 0, 0>>, GET_RANDOM_FLOAT_IN_RANGE(20.0, 60.0), FALSE)
ENDIF
ENDPROC
/// PURPOSE:
/// Creates one clown ped
/// PARAMS
/// clown - clown ped reference
/// task - clown task
/// pos - clown spawn point
/// head - clown spawn heading
/// safecheck - do ground and safe check on pos before spawning
/// forcecombat - doesn't do delay after telportining in
/// areacheck - if this is true we check to see if no spawn areas are being used
FUNC BOOL CREATE_CLOWN_PED_IN_VEHICLE(CLOWN_PED &clown, VEHICLE_INDEX veh, BOOL bForceDriver = FALSE)
INT rnd
VEHICLE_SEAT seat = VS_DRIVER
IF (bForceDriver = FALSE)
IF NOT DOES_VEHICLE_HAVE_FREE_SEAT(veh)
RETURN FALSE
ENDIF
IF IS_VEHICLE_SEAT_FREE(veh, VS_BACK_LEFT)
seat = VS_BACK_LEFT
ELIF IS_VEHICLE_SEAT_FREE(veh, VS_BACK_RIGHT)
seat = VS_BACK_RIGHT
ELSE
RETURN FALSE
ENDIF
ENDIF
clown.pedID = CREATE_PED_INSIDE_VEHICLE(veh, PEDTYPE_MISSION, clownModel, seat)
SAFE_REMOVE_BLIP(clown.blipID)
clown.blipID = CREATE_PED_BLIP(clown.pedID)
clown.laughSoundID = -1
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_PROXIMITY_FIRING_RATE, FALSE)
SET_PED_RANDOM_COMPONENT_VARIATION(clown.pedID)
SET_PED_RELATIONSHIP_GROUP_HASH(clown.pedID, RELGROUPHASH_HATES_PLAYER)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(clown.pedID, TRUE)
rnd = GET_ENTITY_MAX_HEALTH(clown.pedID) / 2
SET_ENTITY_HEALTH(clown.pedID, rnd)
SET_ENTITY_MAX_HEALTH(clown.pedID, rnd)
SET_ENTITY_IS_TARGET_PRIORITY(clown.pedID, TRUE)
SET_PED_MONEY(clown.pedID, 0)
SET_PED_ALERTNESS(clown.pedID, AS_MUST_GO_TO_COMBAT)
SET_PED_TARGET_LOSS_RESPONSE(clown.pedID, TLR_NEVER_LOSE_TARGET)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_AGGRESSIVE, FALSE)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_COVER, TRUE)
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_DEFENSIVE)
STOP_PED_SPEAKING(clown.pedID, TRUE)
SET_AMBIENT_VOICE_NAME(clown.pedID, "CLOWNS")
GIVE_WEAPON_TO_PED(clown.pedID, WEAPONTYPE_PISTOL, INFINITE_AMMO, TRUE)
// setup combat movement
rnd = GET_RANDOM_INT_IN_RANGE(0, 3)
SWITCH (rnd)
CASE 0
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_DEFENSIVE) // Seeks a defensive position.
BREAK
CASE 1
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_WILLADVANCE) // Will advance forward in combat
BREAK
CASE 2
SET_PED_COMBAT_MOVEMENT(clown.pedID, CM_WILLRETREAT) // Will retreat if the enemy gets too close
BREAK
ENDSWITCH
clown.bIsActive = TRUE
clown.bIsDead = FALSE
clown.aState = CS_NULL
// @SBA - setting normal type by default. Change it separately.
SET_CLOWN_TYPE(clown, SCT_NORMAL)
// @SBA - don't let them dance too soon so they get out of van first
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(ROUND(iMinClownDanceDelay * 1.5), iMaxClownDanceDelay)
SET_PED_CAN_COWER_IN_COVER(clown.pedID, FALSE)
SET_PED_CAN_PEEK_IN_COVER(clown.pedID, TRUE)
SET_PED_COMBAT_ATTRIBUTES(clown.pedID, CA_USE_VEHICLE, FALSE)
SET_PED_AS_ENEMY(clown.pedID, TRUE)
SET_PED_DIES_WHEN_INJURED(clown.pedID, TRUE)
SET_PED_SUFFERS_CRITICAL_HITS(clown.pedID, TRUE)
SET_PED_DEFENSIVE_SPHERE_ATTACHED_TO_PED(clown.pedID, PLAYER_PED_ID(), <<0, 0, 0>>, GET_RANDOM_FLOAT_IN_RANGE(12.0, 50.0))
CLEAR_PED_TASKS(clown.pedID)
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(clown.pedID, TRUE)
APPLY_COMBAT_PARAMETERS_TO_PED(clown.pedID, combatParams)
// IF GET_RANDOM_BOOL()
// SET_PED_CAR_DEFENDER(clown.pedID, veh)
// ELSE
// TASK_COMBAT_PED(clown.pedID, PLAYER_PED_ID())
// ENDIF
IF GET_RANDOM_BOOL()
SET_PED_PROP_INDEX(clown.pedID, ANCHOR_HEAD, 0)
ENDIF
// for checking how long the clown has been around (additional time for car spawns so car defenders will stick around longer)
clown.iLongevityTimer = GET_GAME_TIMER() + (kiAggressiveTime + ROUND(kiAggressiveTime * 0.5))
iClownPedsSpawned ++
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// @SBA - picks and plays the appropriate clown dance/perform anim
/// PARAMS:
/// clown - struct
/// bJustDanceClown - TRUE = just choose dance anims; FALSE = % chance of playing mime anim instead
PROC SELECT_AND_START_CLOWN_DANCE_ANIM(CLOWN_PED &clown, BOOL bJustDanceClown)
INT iValue = -1
// If we want a chance for mime, get a random number
IF NOT bJustDanceClown
iValue = GET_RANDOM_INT_IN_RANGE(0,5)
ENDIF
CPRINTLN(DEBUG_MISSION, "SELECT_AND_START_CLOWN_DANCE_ANIM: bJustDanceClown = ", bJustDanceClown, ". Value = ", iValue)
// Do mime anim
IF iValue = 0
clown.danceAnim = sMimeAnimClip
TASK_PLAY_ANIM(clown.pedID, sMimeAnimDict, clown.danceAnim, NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_DEFAULT, kfMimeStartPhase)
// do normal dance anim
ELSE
clown.danceAnim = "clown_idle_"
clown.danceAnim += GET_RANDOM_INT_IN_RANGE(0, 6)
TASK_PLAY_ANIM(clown.pedID, sMissionAnimDanceDictionary, clown.danceAnim, NORMAL_BLEND_IN, -1)
ENDIF
ENDPROC
/// PURPOSE:
/// Puts an SMG in a clown's hand in a puff of purple smoke
/// PARAMS:
/// clown - the individual clown struct
/// sAnimDict - which anim dict is being used for the performance
/// fSpawnGunPhase - the phase of the performance (dance) anim at which to play the smoke FX (should be close to end phase)
/// fEndAnimPhase - the phanse of the anim at which the performance ends and the gun spans in
/// bSmokeFX - passes ref to a bool to gate the playing of the smoke FX
/// RETURNS:
/// TRUE once the performance has ended and the clown has a gun
FUNC BOOL SPAWN_GUN_IN_CLOWNS_HAND(CLOWN_PED &clown, STRING sAnimDict, FLOAT fSpawnGunPhase, FLOAT fEndAnimPhase, BOOL &bSmokeFX)
IF IS_ENTITY_PLAYING_ANIM(clown.pedID, sAnimDict, clown.danceAnim)
// play FX for equiping gun
// @TODO - May need to change this global bool to something else if we have multiple performances at once!
IF NOT bSmokeFX
IF GET_ENTITY_ANIM_CURRENT_TIME(clown.pedID, sAnimDict, clown.danceAnim) >= fSpawnGunPhase
AND NOT HAS_PED_GOT_WEAPON(clown.pedID, WEAPONTYPE_SMG)
CPRINTLN(DEBUG_MISSION, "SPAWN_GUN_IN_CLOWNS_HAND: POOF...")
START_PARTICLE_FX_NON_LOOPED_AT_COORD("scr_clown_appears", GET_PED_BONE_COORDS(clown.pedID, BONETAG_R_HAND, (<<0,0,0>>)), (<<0,0,0>>), 0.3)
bSmokeFX = TRUE
ENDIF
ENDIF
// Kill anim early, supply weapon if needed
IF GET_ENTITY_ANIM_CURRENT_TIME(clown.pedID, sAnimDict, clown.danceAnim) >= fEndAnimPhase
CPRINTLN(DEBUG_MISSION, "SPAWN_GUN_IN_CLOWNS_HAND: ...A GUN!")
//CLEAR_PED_TASKS(clown.pedID)
IF NOT HAS_PED_GOT_WEAPON(clown.pedID, WEAPONTYPE_SMG)
GIVE_WEAPON_TO_PED(clown.pedID, WEAPONTYPE_SMG, INFINITE_AMMO, TRUE)
ENDIF
// reset flag
bSmokeFX = FALSE
RETURN TRUE
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, "*** SPAWN_GUN_IN_CLOWNS_HAND: Clown isn't playing his anim! Anim Dict = ", sAnimDict, ". Anim Clip = ", clown.danceAnim,". Resetting...")
SELECT_AND_START_CLOWN_DANCE_ANIM(clown, TRUE)
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// This handles the clowns day to day stuff
/// PARAMS
/// clown - clown ped reference
PROC UPDATE_CLOWN_PED(CLOWN_PED &clown)
VECTOR vec
FLOAT z
IF (clown.bIsActive = FALSE)
EXIT
ENDIF
IF NOT DOES_ENTITY_EXIST(clown.pedID)
CLEANUP_CLOWN_PED(clown)
EXIT
ENDIF
// to stop assert from crying at me constantly
// as we can some time call this after a wait (in the case of updating bosses)
IS_ENTITY_OK(clown.pedID)
IS_ENTITY_OK(PLAYER_PED_ID())
IF NOT IS_CLOWN_DYING(clown)
IF IS_ENTITY_DEAD(clown.pedID) OR IS_PED_INJURED(clown.pedID) OR IS_PED_DEAD_OR_DYING(clown.pedID, FALSE)
INT iDyingTime = 500
IF (clown.aState = CS_DANCE) OR (clown.aState = CS_DANCE_START)
OR (clown.aState = CS_PERFORM_START) OR (clown.aState = CS_PERFORM_SPAWN_GUN)// @SBA - adding conditions
IF (iDancingClownPedsKilled < 6)
CPRINTLN(DEBUG_MISSION, "INCREASE BA2_DANCING_CLOWNS_KILLED")
INFORM_MISSION_STATS_OF_INCREMENT(BA2_DANCING_CLOWNS_KILLED)
ENDIF
iDancingClownPedsKilled ++
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: DANCING CLOWNS DEAD:", iDancingClownPedsKilled)
ENDIF
// @SBA - shorten the timer if we're in wave 6
IF stageEnum = SE_WAVE6
iDyingTime = 100
ENDIF
PLAY_AMBIENT_SPEECH_FROM_POSITION("CLOWN_DEATH", "CLOWNS", GET_ENTITY_COORDS(clown.pedID), SPEECH_PARAMS_FORCE_SHOUTED_CLEAR)
clown.aState = CS_DYING
clown.iTimer = GET_GAME_TIMER() + iDyingTime
SAFE_STOP_AND_RELEASE_SOUND_ID(clown.laughSoundID)
// @SBA - clear any non-normal type
IF GET_CLOWN_TYPE(clown) != SCT_NORMAL
SET_CLOWN_TYPE(clown, SCT_NORMAL)
ENDIF
IF NOT IS_ENTITY_DEAD(clown.pedID)
EXPLODE_PED_HEAD(clown.pedID)
ENDIF
IF HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(clown.pedID, PLAYER_PED_ID())
PLAY_TREVOR_FIGHT_DIALOG_LINES()
ENDIF
// @SBA - Remember where the clown died if we're in the right stage
IF stageEnum = SE_WAVE6
clown.vDeathPosition = GET_ENTITY_COORDS(clown.pedID)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: DEAD CLOWN LOCATION = ", clown.vDeathPosition)
ENDIF
SAFE_REMOVE_BLIP(clown.blipID)
iClownPedsKilled ++
ENDIF
ENDIF
SWITCH (clown.aState)
CASE CS_DELAY
IF (GET_GAME_TIMER() >= clown.iTimer)
OR stageEnum = SE_WAVE6 // @SBA - if we're in this stage just spawn, don't wait
FREEZE_ENTITY_POSITION(clown.pedID, TRUE)
START_PARTICLE_FX_NON_LOOPED_ON_ENTITY("scr_clown_appears", clown.pedID, <<0, 0, -TELEPORT_Z_DIFF>>, <<0, 0, 0>>, CLOWN_APPEAR_SIZE)
clown.iTimer = GET_GAME_TIMER() + TELEPORT_TIME
vec = GET_ENTITY_COORDS(clown.pedID)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: CLOWN PED SPAWNED IN AT ", vec)
clown.aState = CS_TELEPORT
ENDIF
BREAK
CASE CS_TELEPORT
IF (GET_GAME_TIMER() > clown.iTimer)
SET_ENTITY_VISIBLE(clown.pedID, TRUE)
FREEZE_ENTITY_POSITION(clown.pedID, FALSE)
SET_ENTITY_INVINCIBLE(clown.pedID, FALSE)
SAFE_REMOVE_BLIP(clown.blipID)
clown.blipID = CREATE_PED_BLIP(clown.pedID)
// @SBA - Send clown ped to correct state
SWITCH clown.ClownType
// @SBA - is clown set "special"?
CASE SCT_SPECIAL
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: CLOWN is set SPECIAL, setting state to CS_NULL.")
clown.aState = CS_NULL
BREAK
// @SBA - is clown set to perform?
CASE SCT_PERFORM
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: CLOWN is OK to perform, setting state to CS_PERFORM_START.")
clown.aState = CS_PERFORM_START
BREAK
CASE SCT_NORMAL
clown.aState = CS_ACTIVE
IF (clown.iDanceTimer <> 0)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Setting clown state to CS_ACTIVE!")
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinClownDanceDelay, iMaxClownDanceDelay)
ELSE
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: DANCE CLOWN DANCE!!")
clown.aState = CS_DANCE_START
ENDIF
BREAK
DEFAULT
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Ruh Roh!! No clown type!")
clown.aState = CS_ACTIVE
BREAK
ENDSWITCH
IF GET_RANDOM_BOOL()
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Clown laughs!")
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(clown.pedID, "CLOWN_LAUGH", "CLOWNS", SPEECH_PARAMS_FORCE_SHOUTED_CLEAR)
ENDIF
ENDIF
BREAK
CASE CS_TELEPORT_OUT_START
SAFE_REMOVE_BLIP(clown.blipID)
SAFE_STOP_AND_RELEASE_SOUND_ID(clown.laughSoundID)
FREEZE_ENTITY_POSITION(clown.pedID, TRUE)
SET_ENTITY_INVINCIBLE(clown.pedID, TRUE)
START_PARTICLE_FX_NON_LOOPED_AT_COORD("scr_clown_appears", GET_ENTITY_COORDS(clown.pedID), GET_ENTITY_ROTATION(clown.pedID), CLOWN_APPEAR_SIZE)
clown.iTimer = GET_GAME_TIMER() + (TELEPORT_TIME / 2)
clown.aState = CS_TELEPORT_OUT
BREAK
CASE CS_TELEPORT_OUT
IF (GET_GAME_TIMER() > clown.iTimer)
DELETE_PED(clown.pedID)
CLEANUP_CLOWN_PED(clown)
clown.bIsActive = FALSE
ENDIF
BREAK
CASE CS_ACTIVE
// @SBA - check if the clown is set to be chasing spectators, so we can use longer dist check
IF GET_CLOWN_TYPE(clown) = SCT_CHASE
IF GET_CLOSEST_SPECTATOR_TO_PED(clown.pedID, clown.piClosestSpec, kiLongIgnoreSpectatorsDist)
// Make them more aggressive with the spectators
MAKE_CLOWN_MORE_AGGRESSIVE(clown, TRUE)
clown.aState = CS_ATTACK_SPECTATORS
EXIT
ENDIF
// @SBA - Check all clowns for short-distance targets
ELIF GET_CLOSEST_SPECTATOR_TO_PED(clown.pedID, clown.piClosestSpec, kiShortIgnoreSpectatorsDist)
// Make them more aggressive with the spectators
MAKE_CLOWN_MORE_AGGRESSIVE(clown, TRUE)
clown.aState = CS_ATTACK_SPECTATORS
EXIT
ENDIF
// wait for van exiters to finish exiting
IF (GET_CLOWN_TYPE(clown) = SCT_VAN_EXIT)
AND (GET_SCRIPT_TASK_STATUS(clown.pedID, SCRIPT_TASK_PERFORM_SEQUENCE) <= PERFORMING_TASK)
EXIT
// Clowns should be set normal when attacking the player
ELIF GET_CLOWN_TYPE(clown) != SCT_NORMAL
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Active Clown being set to SCT_NORMAL!")
SET_CLOWN_TYPE(clown, SCT_NORMAL)
ENDIF
// ~~~ @SBA - normal activity ~~~
// Attack player if not already doing so
IF (GET_SCRIPT_TASK_STATUS(clown.pedID, SCRIPT_TASK_COMBAT) > PERFORMING_TASK)
// If the clown has been alive a long time, make him aggressive in combat
IF GET_GAME_TIMER() > clown.iLongevityTimer
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Long-lived clown - make him aggressive!!")
MAKE_CLOWN_MORE_AGGRESSIVE(clown, TRUE, TRUE)
ELSE
MAKE_CLOWN_MORE_AGGRESSIVE(clown, FALSE)
ENDIF
TASK_COMBAT_PED(clown.pedID, PLAYER_PED_ID(), COMBAT_PED_DISABLE_AIM_INTRO)
IF GET_RANDOM_BOOL()
CPRINTLN(DEBUG_MISSION, "Attack player: Clown laughs!")
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(clown.pedID, "CLOWN_LAUGH", "CLOWNS", SPEECH_PARAMS_FORCE_SHOUTED_CLEAR)
ENDIF
ENDIF
// Time to dance
IF (GET_GAME_TIMER() > clown.iDanceTimer)
IF NOT IS_PED_IN_COVER(clown.pedID)
MAKE_CLOWN_MORE_AGGRESSIVE(clown, FALSE)
clown.aState = CS_DANCE_START
ELSE
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinClownDanceDelay, iMaxClownDanceDelay/2)
ENDIF
ENDIF
vec = GET_ENTITY_COORDS(clown.pedID)
IF (vec.z < 27.7)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: CLOWN PED IS TOO FAR BELOW GROUND THIS WILL CAUSE - B*174705 - POINT - EMERGENCY TELEPORT:", vec)
clown.aState = CS_TELEPORT_OUT
EXIT
ENDIF
IF IS_ENTITY_IN_ANGLED_AREA( clown.pedID, <<220.531845,-918.456665,27.533890>>, <<211.758118,-931.421509,39.691795>>, 2.500000)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: IN BOXED AREA - B*174705 - POINT - EMERGENCY TELEPORT:", vec)
clown.aState = CS_TELEPORT_OUT
EXIT
ENDIF
BREAK
// @SBA - adding new state for attacking spectators
CASE CS_ATTACK_SPECTATORS
// If we lost the target...
IF NOT DOES_CLOWN_HAVE_SPECTATOR_TARGET(clown)
OR GET_DISTANCE_BETWEEN_PEDS(clown.pedID, clown.piClosestSpec) > kiLongIgnoreSpectatorsDist
// @TODO - add timer to break off attack after awhile?
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Clown no longer has a spectator target!")
// reset target and go back to active state
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinClownDanceDelay, iMaxClownDanceDelay)
clown.piClosestSpec = NULL
clown.aState = CS_ACTIVE
// @TODO - Reset an eventual timer to check for spectators again
// otherwise attack the spectator target
ELSE
// Clowns should be set to chase when attacking spectators
IF GET_CLOWN_TYPE(clown) != SCT_CHASE
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Clown being set to SCT_CHASE!")
SET_CLOWN_TYPE(clown, SCT_CHASE)
ENDIF
CLOWN_ATTACKS_SPECTATORS(clown)
ENDIF
BREAK
CASE CS_DANCE_START
SELECT_AND_START_CLOWN_DANCE_ANIM(clown, TRUE)
clown.aState = CS_DANCE
BREAK
CASE CS_DANCE
IF NOT IS_ENTITY_PLAYING_ANIM(clown.pedID, sMissionAnimDanceDictionary, clown.danceAnim)
clown.aState = CS_ACTIVE
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinClownDanceDelay, iMaxClownDanceDelay)
ENDIF
BREAK
// @SBA - adding case for general performance start
CASE CS_PERFORM_START
SELECT_AND_START_CLOWN_DANCE_ANIM(clown, FALSE)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Setting clown state to CS_PERFORM_SPAWN_GUN!")
clown.aState = CS_PERFORM_SPAWN_GUN
BREAK
// @SBA - adding case for general performance gun spawn
CASE CS_PERFORM_SPAWN_GUN
STRING sAnimDict
FLOAT fSpawnGunPhase
FLOAT fEndAnimPhase
// @SBA - set appropriate data
IF ARE_STRINGS_EQUAL(clown.danceAnim, sMimeAnimClip)
sAnimDict = sMimeAnimDict
fSpawnGunPhase = kfMimeGunSpawnPhase
fEndAnimPhase = kfMimeEndPhase
ELSE
sAnimDict = sMissionAnimDanceDictionary
fSpawnGunPhase = kfDanceGunSpawnPhase
fEndAnimPhase = kfDanceEndPhase
ENDIF
// If clown has a gun now, move on
IF SPAWN_GUN_IN_CLOWNS_HAND(clown, sAnimDict, fSpawnGunPhase, fEndAnimPhase, bPlayedGunSmokeFX)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_PED: Setting clown state to CS_ACTIVE!")
// set to chase
SET_CLOWN_TYPE(clownPed[i1stPerformanceClownID], SCT_CHASE)
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinClownDanceDelay, iMaxClownDanceDelay)
clown.aState = CS_ACTIVE
ENDIF
BREAK
CASE CS_VEHICLE_DEPLOY
clown.fClownAlpha += GET_FRAME_TIME() * 512.0 // HALF SECOND FADE OUT
IF (clown.fClownAlpha < 2.0)
SET_ENTITY_VISIBLE(clown.pedID, FALSE)
ELSE
SET_ENTITY_VISIBLE(clown.pedID, TRUE)
IF (clown.fClownAlpha > 255.0)
clown.fClownAlpha = 255.0
RESET_ENTITY_ALPHA(clown.pedID)
clown.aState = CS_ACTIVE
ELSE
IF IS_ENTITY_ON_SCREEN(clown.pedID)
SET_PED_ALPHA(clown.pedID, FLOOR(clown.fClownAlpha), iAlphaCounter)
ELSE
RESET_ENTITY_ALPHA(clown.pedID)
ENDIF
ENDIF
ENDIF
BREAK
CASE CS_TELEPORT_SEEK_PLACE
/*
IF GENERATE_CLOWN_SPAWN_POINT_AROUND_PLAYER(vec)
clown.aState = CS_DELAY
clown.iTimer = GET_GAME_TIMER() + (TELEPORT_TIME / 2)
SET_ENTITY_COORDS(clown.pedID, vec)
SET_ENTITY_INVINCIBLE(clown.pedID, TRUE)
SET_ENTITY_VISIBLE(clown.pedID, FALSE)
FREEZE_ENTITY_POSITION(clown.pedID, TRUE)
SAFE_REMOVE_BLIP(clown.blipID)
CPRINTLN(DEBUG_MISSION, "CLOWN FOUND BETTER PLACE")
ENDIF
*/
BREAK
CASE CS_DYING
SAFE_REMOVE_BLIP(clown.blipID)
IF (GET_GAME_TIMER() > clown.iTimer)
IF IS_ENTITY_DEAD(clown.pedID) OR IS_PED_INJURED(clown.pedID)
SAFE_STOP_AND_RELEASE_SOUND_ID(clown.laughSoundID)
IF NOT IS_ENTITY_IN_AIR(clown.pedID)
vec = GET_ENTITY_COORDS(clown.pedID)
IF GET_GROUND_Z_FOR_3D_COORD(vec, z)
vec.z = z
vec.z += 1.0
ENDIF
START_PARTICLE_FX_NON_LOOPED_AT_COORD("scr_clown_death", vec, GET_ENTITY_ROTATION(clown.pedID), 2.0)
PLAY_SOUND_FROM_COORD(-1, "clown_die_wrapper", vec, "BARRY_02_SOUNDSET")
clown.aState = CS_DEAD
// @SBA - shorten timer for wave 6
IF stageEnum = SE_WAVE6
clown.iTimer = GET_GAME_TIMER() + (CLOWN_FADE_TIME - (CLOWN_FADE_TIME - 100))
ELSE
clown.iTimer = GET_GAME_TIMER() + CLOWN_FADE_TIME
ENDIF
clown.fClownAlpha = 255.0
SAFE_REMOVE_BLIP(clown.blipID)
ENDIF
ENDIF
ENDIF
BREAK
CASE CS_DEAD
IF (GET_GAME_TIMER() > clown.iTimer)
clown.fClownAlpha -= GET_FRAME_TIME() * 512.0 // HALF SECOND FADE OUT
IF (clown.fClownAlpha < 0.0)
clown.fClownAlpha = 0.0
ENDIF
SET_PED_ALPHA(clown.pedID, FLOOR(clown.fClownAlpha), iAlphaCounter)
IF (clown.fClownAlpha <= 0.0) OR NOT IS_ENTITY_ON_SCREEN(clown.pedID)
clown.bIsDead = TRUE
SAFE_STOP_AND_RELEASE_SOUND_ID(clown.laughSoundID)
DELETE_CLOWN_PED(clown)
clown.bIsActive = FALSE
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// This handles all clowns day to day stuff
PROC UPDATE_CLOWN_PEDS()
INT i = 0
REPEAT (COUNT_OF(clownPed)) i
UPDATE_CLOWN_PED(clownPed[i])
ENDREPEAT
iAliveClownCount = GET_ALIVE_CLOWN_PED_COUNT()
ENDPROC
/// PURPOSE:
/// This handles on foot auto spawner
PROC UPDATE_CLOWN_SPAWNER()
INT ind
VECTOR v
IF (iAliveClownCount >= iMaxActivePeds) OR (bGenerateAutoClowns = FALSE)
EXIT
ENDIF
//CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: 1st!")
IF (GET_GAME_TIMER() < iNextSpawnTimer)
EXIT
ENDIF
//CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: 2nd!")
IF NOT GET_FREE_CLOWN_PED_INDEX(ind)
EXIT
ENDIF
//CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: 3rd!")
// @SBA - special case for wave 6. if we've created enough duplicate replacements, we're good.
IF stageEnum = SE_WAVE6
IF iDuplicatesCount >= kiNumDuplicates
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: Duplicates Complete.")
bGenerateAutoClowns = FALSE
iDuplicatesCount = 0
EXIT
ENDIF
ENDIF
//CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: 4th! vClownSpawnPoint = ", vClownSpawnPoint)
IF ( bUseClownSpawnPoint )
v = GET_RANDOM_POINT_IN_DISC(vClownSpawnPoint, fClownSpawnRadius, 2.0)
ELSE
v = GET_RANDOM_POINT_IN_DISC(vBattleCenter, fClownSpawnRadius, 2.0)
ENDIF
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: Randomized Vector = ", v) //, " fClownSpawnRadius = ", fClownSpawnRadius)
IF NOT CHECK_SPAWN_POINT_IS_OK(v)
EXIT
ENDIF
//CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: 5th!")
IF CREATE_CLOWN_PED(clownPed[ind], v)
// @SBA - special case for wave 6
IF stageEnum = SE_WAVE6
iNextSpawnTimer = GET_GAME_TIMER() + 25
iDuplicatesCount ++
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: iDuplicatesCount = ", iDuplicatesCount)
CPRINTLN(DEBUG_MISSION, "UPDATE_CLOWN_SPAWNER: Clowns spawned this wave (including first) = ", iClownPedsSpawned)
ELSE
iNextSpawnTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinPedSpawnTime, iMaxPedSpawnTime)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// @SBA - for wave 6, check if more clowns need to spawn
PROC CHECK_FOR_SPAWNING_DUPLICATES()
INT i = 0
REPEAT (COUNT_OF(clownPed)) i
IF NOT ARE_VECTORS_EQUAL(clownPed[i].vDeathPosition, <<0,0,0>>)
CPRINTLN(DEBUG_MISSION, "We need to spawn duplicates! Index = ", i)
// ok to generate duplicates
bGenerateAutoClowns = TRUE
vClownSpawnPoint = clownPed[i].vDeathPosition
CPRINTLN(DEBUG_MISSION, "CHECK_FOR_SPAWNING_DUPLICATES: vClownSpawnPoint = ", vClownSpawnPoint)
// reset death vector
clownPed[i].vDeathPosition = <<0,0,0>>
// stop the repeat
i = COUNT_OF(clownPed) - 1
ENDIF
ENDREPEAT
ENDPROC
/// PURPOSE:
/// @SBA - set values to origin
PROC RESET_ALL_CLOWN_DEATH_VECTORS()
CPRINTLN(DEBUG_MISSION, "RESET_ALL_CLOWN_DEATH_VECTORS")
INT i = 0
REPEAT (COUNT_OF(clownPed)) i
clownPed[i].vDeathPosition = <<0,0,0>>
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Tells all clown peds to flee
PROC FLEE_ALL_CLOWN_PEDS()
INT i = 0
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
REPEAT (COUNT_OF(clownPed)) i
IF IS_CLOWN_PED_ALIVE(clownPed[i])
clownPed[i].aState = CS_NULL
TASK_SMART_FLEE_COORD(clownPed[i].pedID, GET_ENTITY_COORDS(PLAYER_PED_ID()), 400.0, -1)
ENDIF
ENDREPEAT
ENDIF
ENDPROC
//----------------------
// CAR FUNCTIONS
//----------------------
/// PURPOSE:
/// Tells us if a clown car is dead
/// PARAMS:
/// car - reference to clown car struct
FUNC BOOL IS_CLOWN_GENERATOR_DEAD(CLOWN_GENERATOR &car)
IF (car.bIsActive = FALSE)
RETURN TRUE
ENDIF
IF NOT DOES_ENTITY_EXIST(car.generatorID)
RETURN TRUE
ENDIF
RETURN IS_ENTITY_DEAD(car.generatorID)
ENDFUNC
/// PURPOSE:
/// Tells us if all clown cars is dead
FUNC BOOL ARE_ALL_CLOWN_GENERATORS_DEAD()
INT i
i = 0
REPEAT (COUNT_OF(clownGenerator)) i
IF NOT IS_CLOWN_GENERATOR_DEAD(clownGenerator[i])
RETURN FALSE
ENDIF
ENDREPEAT
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Returns active number of clown peds
FUNC INT GET_ALIVE_CLOWN_GENERATOR_COUNT()
INT i = 0
INT cnt = 0
REPEAT (COUNT_OF(clownGenerator)) i
IF NOT IS_CLOWN_GENERATOR_DEAD(clownGenerator[i])
cnt ++
ENDIF
ENDREPEAT
RETURN cnt
ENDFUNC
/// PURPOSE:
/// Gets a free slot in clown car array
/// PARAMS:
/// out - index into array which is free
/// RETURNS:
/// true if there is a free slot
FUNC BOOL GET_FREE_CLOWN_GENERATOR_INDEX(INT &out)
INT i = 0
out = -1
REPEAT (COUNT_OF(clownGenerator)) i
IF (clownGenerator[i].bIsActive = FALSE)
out = i
RETURN TRUE
ENDIF
ENDREPEAT
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// This is stuff which is common to both cleaning up and deleting a clown ped
/// PARAMS:
/// ent - reference to clown ped
PROC SHARED_CLEANUP_AND_DELETE_CLOWN_GENERATOR(CLOWN_GENERATOR &car)
SAFE_REMOVE_BLIP(car.blipID)
car.generatorID = NULL
car.bIsActive = FALSE
car.blipID = NULL
ENDPROC
/// PURPOSE:
/// Cleans up single clown car
/// PARAMS:
/// car - clown car reference
PROC CLEANUP_CLOWN_GENERATOR(CLOWN_GENERATOR &car)
IF (car.bIsActive = FALSE)
EXIT
ENDIF
IF NOT DOES_ENTITY_EXIST(car.generatorID)
EXIT
ENDIF
IF IS_ENTITY_DEAD(car.generatorID)
ENDIF
SET_VEHICLE_CAN_BE_TARGETTED(car.generatorID, FALSE)
SET_ENTITY_IS_TARGET_PRIORITY(car.generatorID, FALSE)
SAFE_RELEASE_VEHICLE(car.generatorID)
SHARED_CLEANUP_AND_DELETE_CLOWN_GENERATOR(car)
ENDPROC
/// PURPOSE:
/// Deletes single clown car
/// PARAMS:
/// car - clown car reference
PROC DELETE_CLOWN_GENERATOR(CLOWN_GENERATOR &car)
IF (car.bIsActive = FALSE)
EXIT
ENDIF
IF NOT DOES_ENTITY_EXIST(car.generatorID)
EXIT
ENDIF
SAFE_REMOVE_BLIP(car.blipID)
IF IS_ENTITY_OK(car.generatorID)
SET_VEHICLE_CAN_BE_TARGETTED(car.generatorID, FALSE)
SET_ENTITY_IS_TARGET_PRIORITY(car.generatorID, FALSE)
ENDIF
IF IS_ENTITY_OK(PLAYER_PED_ID())
IF IS_PED_IN_VEHICLE(PLAYER_PED_ID(), car.generatorID)
SAFE_RELEASE_VEHICLE(car.generatorID)
ELSE
SAFE_DELETE_VEHICLE(car.generatorID)
ENDIF
ENDIF
SHARED_CLEANUP_AND_DELETE_CLOWN_GENERATOR(car)
ENDPROC
/// PURPOSE:
/// Cleanups all clown cars
PROC CLEANUP_ALL_CLOWN_GENERATORS()
INT i = 0
REPEAT COUNT_OF(clownGenerator) i
CLEANUP_CLOWN_GENERATOR(clownGenerator[i])
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Deletes all clown cars
PROC DELETE_ALL_CLOWN_GENERATORS()
INT i = 0
REPEAT COUNT_OF(clownGenerator) i
DELETE_CLOWN_GENERATOR(clownGenerator[i])
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Update a single clown car
/// PARAMS:
/// car - reference to the vehicle
FUNC BOOL UPDATE_CLOWN_GENERATOR(CLOWN_GENERATOR &car)
INT ind
BOOL bBust
SEQUENCE_INDEX seqTask
VECTOR vec
// existence checks
IF (car.bIsActive = FALSE)
RETURN FALSE
ENDIF
IF NOT DOES_ENTITY_EXIST(car.generatorID)
RETURN FALSE
ENDIF
INT i1stGeneratorSpawnTime = iMinGeneratorPedSpawnTime *2
// @SBA Puting this here to avoid asserts beyond CS_DYING
bBust = IS_VEHICLE_BRUCK_UP(car.generatorID)
// dead check - we do this so we can jump into the delayed detonation state
IF (ENUM_TO_INT(car.aState) < ENUM_TO_INT(CS_DYING))
vec = GET_ENTITY_COORDS(car.generatorID)
//CPRINTLN(DEBUG_MISSION, "CLOWN GENERATOR HEALTH = ", GET_ENTITY_HEALTH(car.generatorID))
IF (vec.z < 21.0)
CPRINTLN(DEBUG_MISSION, "CLOWN GENERATOR FALLEN THROUGH WORLD?")
ENDIF
IF bBust OR (vec.z < 21.0)
car.aState = CS_DYING
// increase the stat in here
IF (car.bHasStartedDeploying = FALSE)
CPRINTLN(DEBUG_MISSION, "INCREASE BA2_VANS_DESTROYED")
IF (iClownGeneratorsDestroyed < 4)
INFORM_MISSION_STATS_OF_INCREMENT(BA2_VANS_DESTROYED)
ENDIF
ENDIF
iClownGeneratorsDestroyed ++
ENDIF
ENDIF
IF (car.bHasPlayerApproached = FALSE)
IF (GET_DISTANCE_BETWEEN_ENTITIES(car.generatorID, PLAYER_PED_ID()) < fClownGeneratorTriggerDist) OR HAS_ENTITY_BEEN_DAMAGED_BY_ENTITY(car.generatorID, PLAYER_PED_ID())
CPRINTLN(DEBUG_MISSION, "ACTIVE GENERATOR")
// @SBA - give some extra time here
car.iTimer = GET_GAME_TIMER() + i1stGeneratorSpawnTime
car.bHasPlayerApproached = TRUE
ENDIF
ENDIF
IF (bDebugTTYSpew)
IF (car.bHasPlayerApproached = FALSE)
DRAW_DEBUG_CIRCLE(GET_ENTITY_COORDS(car.generatorID), fClownGeneratorTriggerDist, 255, 0, 0)
ELSE
DRAW_DEBUG_CIRCLE(GET_ENTITY_COORDS(car.generatorID), fClownGeneratorTriggerDist, 0, 0, 255)
ENDIF
ENDIF
// handle states
SWITCH (car.aState)
CASE CS_DELAY
IF (GET_GAME_TIMER() >= car.iTimer)
#IF IS_DEBUG_BUILD
vec = GET_ENTITY_COORDS(car.generatorID)
CPRINTLN(DEBUG_MISSION, "CLOWN GENERATOR SPAWNED IN AT ", vec)
#ENDIF
START_PARTICLE_FX_NON_LOOPED_ON_ENTITY("scr_clown_appears", car.generatorID, <<0, 0, 0>>, <<0, 0, 0>>, GENERATOR_APPEAR_SIZE)
car.iTimer = GET_GAME_TIMER() + TELEPORT_TIME
car.aState = CS_TELEPORT
car.fClownAlpha = 0
SET_VEHICLE_ALPHA(car.generatorID, FLOOR(car.fClownAlpha), iAlphaCounter)
SET_ENTITY_VISIBLE(car.generatorID, TRUE)
// add to dynamic mix
IF (car.bIsInDynamicMix = FALSE)
ADD_ENTITY_TO_AUDIO_MIX_GROUP(car.generatorID, "BARRY_02_VEHICLE_SETTING")
car.bIsInDynamicMix = TRUE
ENDIF
IF NOT IS_ENTITY_ON_SCREEN(car.generatorID)
car.fClownAlpha = 255.0
ENDIF
ENDIF
BREAK
CASE CS_TELEPORT
car.fClownAlpha += GET_FRAME_TIME() * 1024.0 // HALF SECOND FADE OUT
IF (car.fClownAlpha > 255.0)
car.fClownAlpha = 255.0
ENDIF
IF IS_ENTITY_ON_SCREEN(car.generatorID)
SET_VEHICLE_ALPHA(car.generatorID, FLOOR(car.fClownAlpha), iAlphaCounter)
ELSE
RESET_ENTITY_ALPHA(car.generatorID)
ENDIF
IF (GET_GAME_TIMER() >= car.iTimer) OR (car.fClownAlpha >= 255.0)
SET_ENTITY_VISIBLE(car.generatorID, TRUE)
SET_ENTITY_COLLISION(car.generatorID, TRUE)
SET_ENTITY_INVINCIBLE(car.generatorID, FALSE)
FREEZE_ENTITY_POSITION(car.generatorID, FALSE)
RESET_ENTITY_ALPHA(car.generatorID)
SAFE_REMOVE_BLIP(car.blipID)
car.blipID = CREATE_VEHICLE_BLIP(car.generatorID, FALSE)
car.aState = CS_ACTIVE
START_VEHICLE_HORN(car.generatorID, 4000)
SET_VEHICLE_ENGINE_ON(car.generatorID, TRUE, TRUE)
SET_VEHICLE_FORWARD_SPEED(car.generatorID, fClownCarFwdSpeed)
car.iTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinGeneratorPedSpawnTime, iMaxGeneratorPedSpawnTime)
IF (car.iSwerveIn <> 0)
car.aState = CS_ONROUTE_START
ENDIF
ENDIF
BREAK
CASE CS_ONROUTE_START
IF (iAliveClownCount >= iMaxActivePeds)
RETURN TRUE
ENDIF
IF GET_FREE_CLOWN_PED_INDEX(ind)
car.iDriverID = ind
IF CREATE_CLOWN_PED_IN_VEHICLE(clownPed[car.iDriverID], car.generatorID, TRUE)
clownPed[car.iDriverID].aState = cs_null
SAFE_REMOVE_BLIP(clownPed[car.iDriverID].blipID)
CLEAR_PED_TASKS(clownPed[car.iDriverID].pedID)
OPEN_SEQUENCE_TASK(seqTask)
TASK_VEHICLE_TEMP_ACTION(null, car.generatorID, TEMPACT_GOFORWARD_HARD, car.iForwardTime)
IF (car.iSwerveIn = 1)
TASK_VEHICLE_TEMP_ACTION(null, car.generatorID, TEMPACT_HANDBRAKETURNRIGHT, car.iHBrakeTime)
ELIF (car.iSwerveIn = -1)
TASK_VEHICLE_TEMP_ACTION(null, car.generatorID, TEMPACT_HANDBRAKETURNLEFT, car.iHBrakeTime)
ENDIF
CLOSE_SEQUENCE_TASK(seqTask)
TASK_PERFORM_SEQUENCE(clownPed[car.iDriverID].pedID, seqTask)
CLEAR_SEQUENCE_TASK(seqTask)
CPRINTLN(DEBUG_MISSION, "Car has started on route - Time:", GET_GAME_TIMER())
car.aState = CS_ONROUTE
ENDIF
ENDIF
BREAK
CASE CS_ONROUTE
IF IS_ENTITY_ALIVE( clownPed[car.iDriverID].pedID )
IF GET_SCRIPT_TASK_STATUS(clownPed[car.iDriverID].pedID, SCRIPT_TASK_PERFORM_SEQUENCE) = FINISHED_TASK
CPRINTLN(DEBUG_MISSION, "Car has finished route - Time:", GET_GAME_TIMER())
SEQUENCE_INDEX seq
OPEN_SEQUENCE_TASK(seq)
TASK_LEAVE_VEHICLE(NULL, car.generatorID)
TASK_COMBAT_PED(NULL, PLAYER_PED_ID())
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(clownPed[car.iDriverID].pedID, seq)
CLEAR_SEQUENCE_TASK(seq)
clownPed[car.iDriverID].blipID = CREATE_PED_BLIP(clownPed[car.iDriverID].pedID)
clownPed[car.iDriverID].aState = CS_VEHICLE_DEPLOY
car.aState = CS_ACTIVE
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, "Car has aborted route as people are dead - Time:", GET_GAME_TIMER())
TASK_EVERYONE_LEAVE_VEHICLE(car.generatorID)
// @SBA - make sure to give a little time before we start spawning clowns
car.iTimer = GET_GAME_TIMER() + i1stGeneratorSpawnTime
car.aState = CS_ACTIVE
ENDIF
BREAK
CASE CS_ACTIVE
IF (bHasTrevorClownGeneratorRanted = FALSE) AND (bClownGeneratorRantTimerSet)
IF (GET_GAME_TIMER() > iTrevorClownGeneratorRantTime) AND IS_ENTITY_ON_SCREEN(car.generatorID)
// Don't comment if van is too far away
IF GET_DISTANCE_BETWEEN_ENTITIES(PLAYER_PED_ID(), car.generatorID) < 50.0
PLAY_TREVOR_CLOWN_GENERATOR_RANT()
ENDIF
ENDIF
ENDIF
IF (GET_GAME_TIMER() < car.iTimer)
RETURN TRUE
ENDIF
IF (iAliveClownCount >= iMaxActivePeds)
RETURN TRUE
ENDIF
VECTOR vPoint
vPoint = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(car.generatorID, (<<0.0, -3.3, -0.7>>))
// check if clown to close to rear of van
CPRINTLN(DEBUG_MISSION, "Exit sphere: ", vPoint)
IF (bDebugTTYSpew)
DRAW_DEBUG_CIRCLE(vPoint, 1.5, 255, 0, 0)
ENDIF
IF IS_ANY_CLOWN_NEAR_POINT(vPoint, 1.5)
RETURN TRUE
ENDIF
IF GET_FREE_CLOWN_PED_INDEX(ind)
IF CREATE_CLOWN_PED_IN_VEHICLE(clownPed[ind], car.generatorID)
START_PARTICLE_FX_NON_LOOPED_ON_ENTITY("scr_clown_appears", car.generatorID, vClownCarSmokeOffset, <<0, 0, 0>>, fClownCarPedSmokeSize)
clownPed[ind].aState = CS_VEHICLE_DEPLOY
SET_CLOWN_TYPE(clownPed[ind], SCT_VAN_EXIT)
car.bHasStartedDeploying = TRUE
car.iClownPedsSpawned ++
car.fClownAlpha = 0.0
SET_ENTITY_VISIBLE(clownPed[ind].pedID, FALSE)
vPoint = GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(car.generatorID, (<<GET_RANDOM_FLOAT_IN_RANGE(-2.5, 2.5), GET_RANDOM_FLOAT_IN_RANGE(-6.5, -10.0), -0.7>>))
CPRINTLN(DEBUG_MISSION, "Clown exiting vehicle - position: ", vPoint)
SEQUENCE_INDEX seq
OPEN_SEQUENCE_TASK(seq)
TASK_SWAP_WEAPON(NULL, TRUE)
TASK_LEAVE_VEHICLE(NULL, car.generatorID, ECF_DONT_CLOSE_DOOR)
TASK_GO_TO_COORD_WHILE_AIMING_AT_ENTITY(NULL, vPoint, PLAYER_PED_ID(), PEDMOVE_WALK, TRUE, 1.5, 2.0)
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(clownPed[ind].pedID, seq)
CLEAR_SEQUENCE_TASK(seq)
IF (car.bHasPlayerApproached = FALSE)
car.iTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinGeneratorPedSpawnTime * 4, iMaxGeneratorPedSpawnTime * 4)
ELSE
// increase times slightly, but don't change globally
car.iTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinGeneratorPedSpawnTime + 500, iMaxGeneratorPedSpawnTime)
ENDIF
// delay spawning after 5 have come out
IF (car.iClownPedsSpawned > 5)
car.iTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinGeneratorPedSpawnTime * 4, iMaxGeneratorPedSpawnTime * 4)
car.iClownPedsSpawned = 0
ENDIF
IF (bHasClownGeneratorHelpDisplayed = FALSE)
PRINT_HELP("B2_CAR_HLP") // Destroy clown vans to stop clowns regenerating.
bHasClownGeneratorHelpDisplayed = TRUE
ENDIF
// @SBA - set this timer separately from the help text in case Trevor
// doesn't have a chance to say his rant, so we can reset and try again on the next van
IF NOT bClownGeneratorRantTimerSet
iTrevorClownGeneratorRantTime = GET_GAME_TIMER() + (iMaxGeneratorPedSpawnTime + 500)
bClownGeneratorRantTimerSet = TRUE
ENDIF
ENDIF
ENDIF
BREAK
CASE CS_DYING
SAFE_REMOVE_BLIP(car.blipID)
IF car.bIsInDynamicMix
REMOVE_ENTITY_FROM_AUDIO_MIX_GROUP(car.generatorID)
car.bIsInDynamicMix = FALSE
ENDIF
FREEZE_ENTITY_POSITION(car.generatorID, FALSE)
//START_PARTICLE_FX_NON_LOOPED_AT_COORD("scr_clown_death", GET_ENTITY_COORDS(car.generatorID), GET_ENTITY_ROTATION(car.generatorID), 2.0)
EXPLODE_VEHICLE(car.generatorID)
CPRINTLN(DEBUG_MISSION, "CLOWN GENERATOR IS DEAD")
PLAY_SOUND_FRONTEND(-1, "HOORAY", "BARRY_02_SOUNDSET")
car.aState = CS_DEATH_FX
car.iTimer = GET_GAME_TIMER() + (CLOWN_FADE_TIME * 3)
car.fClownAlpha = 255.0
// @SBA - If the van died before Trevor ranted, reset flag so timer will reset next time around
IF NOT bHasTrevorClownGeneratorRanted
IF bClownGeneratorRantTimerSet
CPRINTLN(DEBUG_MISSION, "Didn't hear Trevor's clown generator rant - reseting timer flag")
bClownGeneratorRantTimerSet = FALSE
ENDIF
ENDIF
BREAK
// @SBA - want the fade and effect to coincide
CASE CS_DEATH_FX
IF (GET_GAME_TIMER() > car.iTimer)
CPRINTLN(DEBUG_MISSION, "CLOWN GENERATOR ABOUT TO DISAPPEAR - PLAY EFFECT")
START_PARTICLE_FX_NON_LOOPED_AT_COORD("scr_clown_death", GET_ENTITY_COORDS(car.generatorID, FALSE), GET_ENTITY_ROTATION(car.generatorID), 3.0)
car.iTimer = GET_GAME_TIMER() + (CLOWN_FADE_TIME - 100)
car.aState = CS_DEAD
ENDIF
BREAK
CASE CS_DEAD
IF (GET_GAME_TIMER() > car.iTimer)
car.fClownAlpha -= GET_FRAME_TIME() * 512.0 // HALF SECOND FADE OUT
IF (car.fClownAlpha < 0.0)
car.fClownAlpha = 0.0
ENDIF
IS_ENTITY_OK(car.generatorID)
IF IS_ENTITY_ON_SCREEN(car.generatorID)
SET_VEHICLE_ALPHA(car.generatorID, FLOOR(car.fClownAlpha), iAlphaCounter)
ENDIF
IF (car.fClownAlpha <= 0.0)
CPRINTLN(DEBUG_MISSION, "CLOWN GENERATOR IS GONE")
STOP_FIRE_IN_RANGE(GET_ENTITY_COORDS(car.generatorID), 2.0)
CPRINTLN(DEBUG_MISSION, "START RECORDING THE LAST 4 SECONDS AS A CLOWN CAR HAS BLOWN UP")
REPLAY_RECORD_BACK_FOR_TIME(4.0) // Clown car has blown up and faded out
DELETE_CLOWN_GENERATOR(car)
RETURN FALSE
ENDIF
ENDIF
BREAK
ENDSWITCH
RETURN TRUE
ENDFUNC
FUNC BOOL CREATE_CLOWN_GENERATOR(CLOWN_GENERATOR &car, VECTOR pos, FLOAT head = 0.0, INT swerve = 0, INT iDelay = 0, INT iFwdTime = 4625, INT iBrakeTime = 2000)
FLOAT hp
// get start point and work out direction
CPRINTLN(DEBUG_MISSION, "CLOUD GENERATOR INIT POSITION:", pos)
CLEAR_AREA_OF_VEHICLES(pos, 5.0)
IF GET_GROUND_Z_FOR_3D_COORD(pos + <<0, 0, 0.23>>, hp)
pos.z = hp
ENDIF
car.generatorID = CREATE_VEHICLE(clownCarModel, pos, head)
IF NOT DOES_ENTITY_EXIST(car.generatorID)
RETURN FALSE
ENDIF
// setup hp and degradation
CPRINTLN(DEBUG_MISSION, "CLOUD GENERATOR ACTUAL SPAWN POSITION:", pos)
// @SBA - decrease van health a bit
hp = TO_FLOAT(GET_ENTITY_HEALTH(car.generatorID)) / 1.5
SET_ENTITY_HEALTH(car.generatorID, FLOOR(hp))
car.bHasStartedDeploying = FALSE
car.bHasPlayerApproached = FALSE
// setup damage and targetting
SET_ENTITY_ONLY_DAMAGED_BY_RELATIONSHIP_GROUP(car.generatorID, TRUE, RELGROUPHASH_PLAYER)
SET_VEHICLE_CAN_BE_TARGETTED(car.generatorID, TRUE)
SET_ENTITY_IS_TARGET_PRIORITY(car.generatorID, TRUE)
// freeze and hide object
SET_ENTITY_VISIBLE(car.generatorID, FALSE)
SET_ENTITY_INVINCIBLE(car.generatorID, TRUE)
SET_ENTITY_COLLISION(car.generatorID, FALSE)
FREEZE_ENTITY_POSITION(car.generatorID, TRUE)
// make car fire proof or it will take damages as it drives through flames
SET_ENTITY_PROOFS(car.generatorID, FALSE, TRUE, FALSE, FALSE, FALSE)
// turn off vehicle cover so clowns won't block other clowns trying to exit the van
SET_VEHICLE_PROVIDES_COVER(car.generatorID, FALSE)
// finalize
car.bIsActive = TRUE
car.iTimer = GET_GAME_TIMER() + iDelay
car.bIsInDynamicMix = FALSE
car.aState = CS_DELAY
car.iClownPedsSpawned = 0
car.iSwerveIn = swerve
car.iForwardTime = iFwdTime
car.iHBrakeTime = iBrakeTime
RETURN TRUE
ENDFUNC
/// PURPOSE:
/// Update all clown cars
PROC UPDATE_CLOWN_GENERATORS()
INT i = 0
iAliveClownGeneratorCount = 0
REPEAT (COUNT_OF(clownGenerator)) i
IF UPDATE_CLOWN_GENERATOR(clownGenerator[i])
iAliveClownGeneratorCount ++
ENDIF
ENDREPEAT
ENDPROC
//----------------------
// DEBUG FUNCTIONS
//----------------------
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Initializes Debug Widgets
PROC SETUP_DEBUG_WIDGETS()
SET_PROFILING_OF_THIS_SCRIPT(TRUE)
m_WidgetGroup = START_WIDGET_GROUP("Barry 2 Config")
START_WIDGET_GROUP("Test Options")
ADD_WIDGET_BOOL("Show Debug Stuff", bDebugTTYSpew)
ADD_WIDGET_BOOL("Show Mission Timer", bShowDebugMissionTime)
ADD_WIDGET_BOOL("Update Widgets", bUpdateWidgets)
ADD_WIDGET_BOOL("bUseIsAreaOccupied", bUseIsAreaOccupied)
STOP_WIDGET_GROUP()
SETUP_COMBAT_PARAMETERS_WIDGET(combatParams, "Clown Combat Parameters")
START_WIDGET_GROUP("Clown Ped Options")
ADD_WIDGET_BOOL("Spawn Test Clown", bGenerateTestClown)
ADD_WIDGET_INT_SLIDER("Max Active", iMaxActivePeds, 0, COUNT_OF(clownPed), 1)
ADD_WIDGET_INT_SLIDER("Min Spawn Time", iMinPedSpawnTime, 0, 5000, 250)
ADD_WIDGET_INT_SLIDER("Max Spawn Time", iMaxPedSpawnTime, 50, 5500, 250)
ADD_WIDGET_FLOAT_SLIDER("No Player Spawn Dist", fNoSpawnPlayerDist, 5.0, 200.0, 0.5)
ADD_WIDGET_FLOAT_SLIDER("Spawn Range", fClownSpawnRadius, 5.0, 200.0, 0.5)
ADD_WIDGET_INT_READ_ONLY("Alive Clowns", iAliveClownCount)
ADD_WIDGET_INT_READ_ONLY("Clown Peds Spawned", iClownPedsSpawned)
ADD_WIDGET_INT_READ_ONLY("Clown Peds Killed", iClownPedsKilled)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Clown Generator Options")
START_WIDGET_GROUP("Test Generator")
ADD_WIDGET_BOOL("Spawn Generator", bGenerateTestGenerator)
ADD_WIDGET_VECTOR_SLIDER("Spawn Point", vTestGenPoint, -7000.0, 7000.0, 1.0)
ADD_WIDGET_FLOAT_SLIDER("Heading", fTestHeading, 0.0, 360.0, 0.5)
ADD_WIDGET_FLOAT_SLIDER("Forward Speed", fClownCarFwdSpeed, 0.0, 360.0, 0.25)
ADD_WIDGET_INT_SLIDER("Forward Time", iTestFwdTime, 0, 10000, 250)
ADD_WIDGET_INT_SLIDER("Brake Time", iTestBrakeTime, 50, 10500, 250)
ADD_WIDGET_INT_SLIDER("Swerve", iTestSwerve, -1, 1, 1)
ADD_WIDGET_VECTOR_SLIDER("Ped Spawn Smoke Offset", vClownCarSmokeOffset, -10.0, 10.0, 0.1)
ADD_WIDGET_FLOAT_SLIDER("Ped Spawn Smoke Size", fClownCarPedSmokeSize, 0.0, 10.0, 0.1)
STOP_WIDGET_GROUP()
ADD_WIDGET_INT_SLIDER("Min Ped Spawn Time", iMinGeneratorPedSpawnTime, 0, 5000, 250)
ADD_WIDGET_INT_SLIDER("Max Ped Spawn Time", iMaxGeneratorPedSpawnTime, 50, 5500, 250)
ADD_WIDGET_FLOAT_SLIDER("Trigger Distance", fClownGeneratorTriggerDist, 0.0, 100.0, 0.25)
ADD_WIDGET_INT_READ_ONLY("Alive Generators", iAliveClownGeneratorCount)
ADD_WIDGET_INT_READ_ONLY("Generators Destroyed", iClownGeneratorsDestroyed)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Area Options")
ADD_WIDGET_BOOL("Player In Battle Area", bIsPlayerInBattleArea)
ADD_WIDGET_VECTOR_SLIDER("Battle Center", vBattleCenter, -6000.0, 6000.0, 0.5)
ADD_WIDGET_FLOAT_SLIDER("Battle Range", fBattleRadius, 5.0, 1000.0, 0.5)
STOP_WIDGET_GROUP()
START_WIDGET_GROUP("Read Only Values")
ADD_WIDGET_INT_READ_ONLY("Next Spawn Time", iNextSpawnTimer)
ADD_WIDGET_INT_READ_ONLY("Current Game Time", iCurrentGameTime)
START_WIDGET_GROUP("Dialog Stats")
ADD_WIDGET_BOOL("Has First Outburst", bHasInitialOutburst)
ADD_WIDGET_INT_READ_ONLY("Initial Speech Time", iFirstDialogTime)
ADD_WIDGET_INT_READ_ONLY("Next Fight Dialog Time", iNextFightDialogTime)
ADD_WIDGET_INT_READ_ONLY("Next Freak Dialog Time", iNextFreakDialogTime)
STOP_WIDGET_GROUP()
STOP_WIDGET_GROUP()
STOP_WIDGET_GROUP()
ENDPROC
/// PURPOSE:
/// Removes Debug Widgets
PROC CLEANUP_DEBUG_WIDGETS()
IF DOES_WIDGET_GROUP_EXIST(m_WidgetGroup)
DELETE_WIDGET_GROUP(m_WidgetGroup)
ENDIF
ENDPROC
#ENDIF
//----------------------
// SCRIPT FLOW
//----------------------
/// PURPOSE:
/// Handles the Pass Out Sequence, it's animations and dialog
/// PARAMS:
/// pWait - Do we wait 2.5 seconds
FUNC BOOL PASS_OUT_SEQUENCE(BOOL bPass = FALSE)
VECTOR v
BOOL bOK = FALSE
CAMERA_INDEX cCamera
// do global stuff here
UPDATE_CLOWN_PEDS()
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Trevor", PLAYER_PED_ID(), GET_ENTITY_MODEL(PLAYER_PED_ID()))
ENDIF
SET_CUTSCENE_PED_PROP_VARIATION(sSceneHandleBarry, ANCHOR_EYES, 0)
CPRINTLN(DEBUG_MISSION, "PED CUTSCENE VARIATIONS SET")
ENDIF
// flow of the pass out sequence
SWITCH ePassOutStage
CASE POS_SETUP
// -----setup--------------------------------
IF (bPass = TRUE)
RC_REQUEST_CUTSCENE("bar_4_rcm")
REQUEST_SCRIPT("postRC_Barry1and2")
ENDIF
PREPARE_MUSIC_EVENT("RC18B_END")
CPRINTLN(DEBUG_MISSION, "Interactive Music Event: RC18A_COLLAPSE Prepared")
CPRINTLN(DEBUG_MISSION, "Pass Out - 2.5 Second Warm Up")
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ePassOutStage = POS_WAIT_FOR_TIRED
STOP_FIRE_IN_RANGE(GET_ENTITY_COORDS(PLAYER_PED_ID()), 2.0)
BREAK
CASE POS_WAIT_FOR_TIRED
// -----wait for tired--------------------------------
IF (bPass = FALSE)
IF IS_ENTITY_OK(gunObject)
DETACH_ENTITY(gunObject, DEFAULT, FALSE)
ENDIF
ENDIF
cCamera = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", GET_GAMEPLAY_CAM_COORD(), GET_GAMEPLAY_CAM_ROT(), GET_GAMEPLAY_CAM_FOV(), TRUE)
v = GET_ENTITY_COORDS(PLAYER_PED_ID()) - GET_GAMEPLAY_CAM_COORD()
ATTACH_CAM_TO_ENTITY(cCamera, PLAYER_PED_ID(), -v)
IF DOES_CAM_EXIST(cCamera)
SET_CAM_ACTIVE(cCamera, TRUE)
ENDIF
// fail safe
iFailTimer = GET_GAME_TIMER() + 6000
ADD_PED_FOR_DIALOGUE(convoPlayer, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
CPRINTLN(DEBUG_MISSION, "Pass Out - Start Dialog - Going to Start Dialog State")
ePassOutStage = POS_START_DIALOG
BREAK
CASE POS_START_DIALOG
// -----start dialog--------------------------------
bOK = FALSE
IF (bPass = TRUE)
IF CREATE_CONVERSATION(convoPlayer, "BARY2AU", "BARY2_PREOUT", CONV_PRIORITY_HIGH) OR (GET_GAME_TIMER() > iFailTimer)
IF (GET_GAME_TIMER() < iFailTimer)
CPRINTLN(DEBUG_MISSION, "Pass Out - Start Dialog - Conversation Created")
ELSE
CPRINTLN(DEBUG_MISSION, "Pass Out - Start Dialog - Conversation Not Created - Emergency Abort")
ENDIF
iFailTimer = GET_GAME_TIMER() + 5000
bOK = TRUE
ENDIF
ELSE
// @SBA - don't want a line played for the fail state - line was getting cut off anyway
//IF PLAY_SINGLE_LINE_FROM_CONVERSATION(convoPlayer, "BARY2AU", "BARY2_PREOUT", "BARY2_PREOUT_2", CONV_PRIORITY_HIGH) OR (GET_GAME_TIMER() > iFailTimer)
iFailTimer = GET_GAME_TIMER() + 2000
bOK = TRUE
//ENDIF
ENDIF
IF (bOK = TRUE)
CPRINTLN(DEBUG_MISSION, "Pass Out - Start Dialog - We should be ready to play line now")
ePassOutStage = POS_TRANSITION_FX
ENDIF
BREAK
CASE POS_TRANSITION_FX
bOK = FALSE
IF (bPass = TRUE)
IF (GET_GAME_TIMER() > iFailTimer)
// @SBA - filter for passing out
CLEANUP_SCREEN_FX()
ANIMPOSTFX_PLAY(FX_DrugsOut, 0, FALSE)
// wait for FX white out
iFailTimer = GET_GAME_TIMER() + 3500
bOK = TRUE
ENDIF
ELSE
bOK = TRUE
ENDIF
IF (bOK = TRUE)
CPRINTLN(DEBUG_MISSION, "Pass Out - FX should be transitioning")
ePassOutStage = POS_WAIT_DIALOGUE
ENDIF
BREAK
CASE POS_WAIT_DIALOGUE
IF (bPass = TRUE)
bOK = (GET_GAME_TIMER() > iFailTimer)
ELSE
IF (GET_GAME_TIMER() < iFailTimer)
CPRINTLN(DEBUG_MISSION, "Pass Out - Start Dialog - Conversation Finished")
ENDIF
// make the player pass out and drop weapon (add component)
//gunObject = CREATE_FAKE_WEAPON_FOR_PLAYER(playerWeapon)
gunObject = CREATE_WEAPON_OBJECT_FROM_CURRENT_PED_WEAPON_WITH_COMPONENTS(PLAYER_PED_ID())
IF DOES_ENTITY_EXIST(gunObject)
IF IS_ENTITY_OK(PLAYER_PED_ID())
ATTACH_ENTITY_TO_ENTITY(gunObject, PLAYER_PED_ID(), GET_PED_BONE_INDEX(PLAYER_PED_ID(), BONETAG_PH_R_HAND), <<0, 0, 0>>, <<0, 0, 0>>)
REMOVE_ALL_PED_WEAPONS(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_PED_TO_RAGDOLL(PLAYER_PED_ID(), 7000, 7500, TASK_RELAX, FALSE, FALSE)
// if for any reason the gun hasn't detached...
IF IS_ENTITY_OK(gunObject) AND IS_ENTITY_ATTACHED(gunObject)
DETACH_ENTITY(gunObject, DEFAULT, FALSE)
ENDIF
bOK = TRUE
ENDIF
// z-skip fix
ELSE
CPRINTLN(DEBUG_MISSION, "No weapon - just ending")
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
SET_PED_TO_RAGDOLL(PLAYER_PED_ID(), 7000, 7500, TASK_RELAX, FALSE, FALSE)
bOK = TRUE
ENDIF
ENDIF
IF (bOK = TRUE)
CPRINTLN(DEBUG_MISSION, "IM Trigger - RC18B_END")
TRIGGER_MUSIC_EVENT("RC18B_END")
iFailTimer = GET_GAME_TIMER() + 1000 //3500
ePassOutStage = POS_WAIT_PASS_OUT
ENDIF
BREAK
CASE POS_WAIT_PASS_OUT
// ----wait for player to pass out--------------------------------
IF GET_GAME_TIMER() > iFailTimer
IF (bPass = TRUE)
// put this in a proc and call in fail too???
//CLEANUP_ALL_ALIEN_PEDS(FALSE)
SAFE_DELETE_OBJECT(gunObject)
IF DOES_CAM_EXIST(cCamera)
SET_CAM_ACTIVE(cCamera, FALSE)
DESTROY_CAM(cCamera)
ENDIF
SHAKE_GAMEPLAY_CAM("DRUNK_SHAKE", 0)
SET_TIME_SCALE(1.0)
DEACTIVATE_AUDIO_SLOWMO_MODE("BARRY_02_SLOWMO")
SET_AUDIO_FLAG("AllowScriptedSpeechInSlowMo", FALSE)
SET_AUDIO_FLAG("AllowAmbientSpeechInSlowMo", FALSE)
CLEAR_AREA_OF_VEHICLES(vMissionStart, 200.0)
REMOVE_DECALS_IN_RANGE(vMissionStart, 500.0)
IF IS_ENTITY_OK(PLAYER_PED_ID())
RESET_PED_VISIBLE_DAMAGE(PLAYER_PED_ID())
CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
ENDIF
ENDIF
CPRINTLN(DEBUG_MISSION, "Pass Out - Complete")
RETURN TRUE // completed the pass out sequence
ENDIF
BREAK
ENDSWITCH
RETURN FALSE // not completed the pass out sequence
ENDFUNC
/// PURPOSE:
/// Loads Mission Assets
/// PARAMS:
/// loadWait - if this is true pause script until all assets are loaded
PROC REQUEST_MISSION_ASSETS()
//CLEAR_ASSET_REQUESTER(assetRequester)
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 0, ASSET_AUDIOBANK, "SCRIPT\\BARRY_02_CLOWN_A")
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 1, ASSET_AUDIOBANK, "SCRIPT\\BARRY_02_CLOWN_B")
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 2, ASSET_AUDIOBANK, "SCRIPT\\BARRY_02_CLOWN_C")
ADD_ASSET_REQUEST_FOR_MODEL(assetRequester, 3, clownModel)
ADD_ASSET_REQUEST_FOR_MODEL(assetRequester, 4, clownCarModel)
ADD_ASSET_REQUEST_FOR_TEXT(assetRequester, 5, "BARY2", MISSION_TEXT_SLOT)
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 6, ASSET_ANIMDICT, sMissionAnimDictionary)
ADD_ASSET_REQUEST_FOR_PTFX(assetRequester, 7)
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 8, ASSET_ANIMDICT, sMissionAnimDanceDictionary)
// @SBA Adding new requests here for simplicity and separation
ADD_ASSET_REQUEST_FOR_MODEL(assetRequester, 9, mnSpectatorMale)
ADD_ASSET_REQUEST_FOR_MODEL(assetRequester, 10, mnSpectatorFemale)
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 11, ASSET_ANIMDICT, sSpectatorFemAnimDict)
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 12, ASSET_ANIMDICT, sSpectatorMaleAnimDict)
ADD_ASSET_REQUEST_FROM_STRING(assetRequester, 13, ASSET_ANIMDICT, sMimeAnimDict)
ADD_ASSET_REQUEST_FOR_MODEL(assetRequester, 14, mnProtestSign)
ENDPROC
//----------------------
// CHECKPNT FUNCTIONS
//----------------------
/// PURPOSE:
/// Performs Z Skip
/// PARAMS:
/// iTargetStage - which stage to jump to
PROC DO_Z_SKIP(INT iTargetStage)
RC_START_Z_SKIP()
RESET_MISSION_VALUES()
// @SBA - adding spectators
DELETE_ALL_SPECTATOR_PEDS()
DELETE_ALL_CLOWN_PEDS()
DELETE_ALL_CLOWN_GENERATORS()
// @SBA - make sure to reset to game cam if needed
IF NOT IS_GAMEPLAY_CAM_RENDERING()
RENDER_SCRIPT_CAMS(FALSE, FALSE)
ENDIF
// Barry and Table Should Not Be Here
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
RC_CleanupSceneEntities(sRCLauncherDataLocal, TRUE, TRUE, FALSE)
SWITCH iTargetStage
CASE Z_SKIP_TO_INTRO
CPRINTLN(DEBUG_MISSION, "IM Trigger - RC18B_END")
TRIGGER_MUSIC_EVENT("RC18B_END")
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), vMissionStart)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fMissionStart)
iDbgStageJump = ENUM_TO_INT(SE_INTRO)
BREAK
// @SBA - adding new stage
// This is CP_MISSION_START
CASE Z_SKIP_TO_PERFORMANCE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: Performance")
#ENDIF
IF NOT IS_REPLAY_BEING_SET_UP()
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), vMissionStart)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fMissionStart)
ENDIF
// start performance cam on replay
ciPerformCamera1 = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", <<188.1366, -957.7827, 30.6514>>, <<-5.5067, -8.0000, 92.8053>>, 40.0)
IF DOES_CAM_EXIST(ciPerformCamera1)
CPRINTLN(DEBUG_MISSION, "EXIT STATE FOR CAMERA SET: start cam")
SET_CAM_ACTIVE(ciPerformCamera1, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
SHAKE_CAM(ciPerformCamera1, "DRUNK_SHAKE")
ENDIF
iDbgStageJump = ENUM_TO_INT(SE_PERFORMANCE)
BREAK
CASE Z_SKIP_TO_FIRST_CONTACT
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: 1st Contact")
#ENDIF
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), vMissionStart)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fMissionStart)
iDbgStageJump = ENUM_TO_INT(SE_FIRSTCONTACT)
BREAK
CASE Z_SKIP_TO_FIRST_WAVE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: 1st Wave")
#ENDIF
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<179.1285, -961.5800, 29.0923>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 143.3596)
iDbgStageJump = ENUM_TO_INT(SE_WAVE1)
BREAK
CASE Z_SKIP_TO_SECOND_WAVE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: 2nd Wave")
#ENDIF
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<176.0677, -976.4255, 29.0923>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 324.8268)
iDbgStageJump = ENUM_TO_INT(SE_WAVE2)
BREAK
CASE Z_SKIP_TO_THIRD_WAVE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: 3nd Wave")
#ENDIF
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<188.0644, -948.7751, 29.0923>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 329.9782)
iDbgStageJump = ENUM_TO_INT(SE_WAVE3)
BREAK
// @SBA this is CP_MID_STAGE
CASE Z_SKIP_TO_FOURTH_WAVE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: 4th Wave")
#ENDIF
IF NOT IS_REPLAY_BEING_SET_UP()
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<188.9320, -952.0983, 29.0923>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 325.7944)
ENDIF
iDbgStageJump = ENUM_TO_INT(SE_WAVE4)
BREAK
CASE Z_SKIP_TO_FIFTH_WAVE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: 5th Wave")
#ENDIF
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<213.3817, -919.8522, 29.6929>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 323.9430)
iDbgStageJump = ENUM_TO_INT(SE_WAVE5)
BREAK
// @SNA - new
CASE Z_SKIP_TO_SIXTH_WAVE
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: 6th Wave")
#ENDIF
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<209.8298, -912.4507, 29.6921>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 138.4911)
iDbgStageJump = ENUM_TO_INT(SE_WAVE6)
BREAK
CASE Z_SKIP_TO_PASSOUT
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: Pass out")
#ENDIF
iDbgStageJump = ENUM_TO_INT(SE_PASSOUT)
BREAK
// @SBA - this is CP_OUTRO
CASE Z_SKIP_TO_OUTRO
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: Outro")
#ENDIF
iDbgStageJump = ENUM_TO_INT(SE_OUTRO)
BREAK
CASE Z_SKIP_TO_TEST
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Z-Skip or Replay: TEST")
#ENDIF
iDbgStageJump = ENUM_TO_INT(SE_TEST)
BREAK
ENDSWITCH
// delete and unload everything
stageEnum = INT_TO_ENUM(STAGE_ENUM, iDbgStageJump)
stageProgress = SP_LOADING
IF (iDbgStageJump > ENUM_TO_INT(SE_TEST)) AND (iDbgStageJump < ENUM_TO_INT(SE_PASSOUT))
TRIGGER_MUSIC_EVENT("RC18B_START")
IF NOT IS_AUDIO_SCENE_ACTIVE(sndAlienAmbientScene)
START_AUDIO_SCENE(sndAlienAmbientScene)
ENDIF
CPRINTLN(DEBUG_MISSION, "[BARRY 2] - PLAY SCREEN FX - FX_DrugsSkip")
ANIMPOSTFX_PLAY(FX_DrugsSkip, 0, TRUE)
SET_TIME_SCALE(fTimeScale)
DEACTIVATE_AUDIO_SLOWMO_MODE("BARRY_02_SLOWMO")
ACTIVATE_AUDIO_SLOWMO_MODE("BARRY_02_SLOWMO")
SET_AUDIO_FLAG("AllowScriptedSpeechInSlowMo", TRUE)
SET_AUDIO_FLAG("AllowAmbientSpeechInSlowMo", TRUE)
FORCE_PLAYER_WEAPON()
ENDIF
ENABLE_AMBIENT_PEDS_AND_VEHICLES(FALSE, FALSE, TRUE, TRUE)
END_REPLAY_SETUP(NULL, VS_DRIVER, FALSE)
IF iDbgStageJump = ENUM_TO_INT(SE_OUTRO)
OR iDbgStageJump = ENUM_TO_INT(SE_PERFORMANCE)
RC_END_Z_SKIP(TRUE, FALSE, FALSE)
ELSE
RC_END_Z_SKIP()
ENDIF
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
ANIMPOSTFX_PLAY(FX_DrugsIn, 0, TRUE)
ENDPROC
/// PURPOSE:
/// Cleans mission
PROC MISSION_SETUP()
// my mission setup - these things are only done once
CPRINTLN(DEBUG_MISSION, " ")
CPRINTLN(DEBUG_MISSION, "BARRY 2 - VERSION:", MISSION_VERSION)
REQUEST_MISSION_ASSETS()
// areas
SET_ANGLED_AREA(battleArea, <<226.221329,-848.208069,25.421360>>, <<163.914642,-1012.380005,54.881466>>, 131.750000)
battleAreaInner = EXPAND_ANGLED_AREA(battleArea, -10.0)
battleAreaOuter = EXPAND_ANGLED_AREA(battleArea, 20.0)
//SET_ANGLED_AREA(battleAreaOuter, <<231.158264,-839.291626,25.425917>>, <<161.858002,-1023.933411,56.252029>>, 138.5)
// @SBA - set a lager area to cover most of the battle zone
// SET_ANGLED_AREA(respotVehicleArea, <<176.729996,-969.593384,37.092262>>, <<195.129456,-941.357605,27.191963>>, 21.500000)
SET_ANGLED_AREA(respotVehicleArea, <<168.850021,-1001.023804,23.091291>>, <<225.904175,-862.596924,34.092327>>, 55.000000)
// turn off debug lines just in case i forget and shops
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(FALSE)
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(TRUE)
SUPPRESS_PICKUP_REWARD_TYPE(PICKUP_REWARD_TYPE_ALL, TRUE)
// setup z skip menu
#IF IS_DEBUG_BUILD
sSkipMenu[Z_SKIP_TO_INTRO].sTxtLabel = "INTRO"
sSkipMenu[Z_SKIP_TO_PERFORMANCE].sTxtLabel = "PERFORMANCE"
sSkipMenu[Z_SKIP_TO_FIRST_CONTACT].sTxtLabel = "FIRST CONTACT"
sSkipMenu[Z_SKIP_TO_FIRST_WAVE].sTxtLabel = "1ST WAVE"
sSkipMenu[Z_SKIP_TO_SECOND_WAVE].sTxtLabel = "2ND WAVE"
sSkipMenu[Z_SKIP_TO_THIRD_WAVE].sTxtLabel = "3RD WAVE"
sSkipMenu[Z_SKIP_TO_FOURTH_WAVE].sTxtLabel = "4TH WAVE"
sSkipMenu[Z_SKIP_TO_FIFTH_WAVE].sTxtLabel = "5TH WAVE"
sSkipMenu[Z_SKIP_TO_SIXTH_WAVE].sTxtLabel = "6TH WAVE"
sSkipMenu[Z_SKIP_TO_PASSOUT].sTxtLabel = "COLLAPSE"
sSkipMenu[Z_SKIP_TO_OUTRO].sTxtLabel = "OUTRO"
sSkipMenu[Z_SKIP_TO_TEST].sTxtLabel = "TEST"
SETUP_DEBUG_WIDGETS()
#ENDIF
// stop police bothering me
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_MAX_WANTED_LEVEL(0)
SET_PLAYER_WANTED_LEVEL(GET_PLAYER_INDEX(), 0)
SET_PLAYER_WANTED_LEVEL_NOW(GET_PLAYER_INDEX())
// @SBA - remember armor level (since this isn't "real" he shouldn't lose armor once it's done)
iPlayerStartingArmor = GET_PED_ARMOUR(PLAYER_PED_ID())
CPRINTLN(DEBUG_MISSION, "MISSION_SETUP: Player's starting armor level = ", iPlayerStartingArmor)
ENDIF
ENABLE_ALL_DISPATCH_SERVICES(FALSE)
DISABLE_CELLPHONE(TRUE)
// set weather transition
SET_WEATHER_TYPE_OVERTIME_PERSIST("extrasunny", 10.000)
SPECIAL_ABILITY_LOCK(GET_PLAYER_PED_MODEL(CHAR_TREVOR))
SPECIAL_ABILITY_RESET(PLAYER_ID())
RESET_MISSION_VALUES()
DISABLE_CHEAT(CHEAT_TYPE_SPAWN_VEHICLE, TRUE)
DISABLE_CHEAT(CHEAT_TYPE_GIVE_WEAPONS, TRUE)
DISABLE_TAXI_HAILING(TRUE)
// replay malarky
IF IS_REPLAY_IN_PROGRESS()= TRUE // Set up the initial scene for replays
CPRINTLN(DEBUG_MISSION, "REPLAY IN PROGRESS", MISSION_VERSION)
g_bSceneAutoTrigger = TRUE
eInitialSceneStage = IS_REQUEST_SCENE
WHILE NOT SetupScene_BARRY_2(sRCLauncherDataLocal)
WAIT(0)
ENDWHILE
g_bSceneAutoTrigger = FALSE
ENABLE_AMBIENT_PEDS_AND_VEHICLES(FALSE, FALSE, TRUE, TRUE)
BLOCK_SCENARIOS_AND_AMBIENT(scenarioBlock)
// WAIT_FOR_WORLD_TO_LOAD(vMissionStart)
// SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), vMissionStart, fMissionStart, TRUE)
SET_AMBIENT_ZONE_STATE(sAmbientZone, TRUE)
WHILE NOT HAVE_ASSET_REQUESTS_LOADED(assetRequester)
WAIT(0)
ENDWHILE
stageEnum = SE_FIRSTCONTACT
stageProgress = SP_LOADING
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CPRINTLN(DEBUG_MISSION, "Please Stop T-Posing...")
SET_ENTITY_VISIBLE(PLAYER_PED_ID(), TRUE)
ENDIF
INT iReplayStage = GET_REPLAY_MID_MISSION_STAGE()
IF g_bShitskipAccepted = TRUE
iReplayStage++ // player is skipping this stage
ENDIF
SWITCH iReplayStage
CASE CP_MISSION_START
// @SBA - inital wave is now performance
START_REPLAY_SETUP(vMissionStart, fMissionStart, FALSE)
Do_Z_Skip(Z_SKIP_TO_PERFORMANCE) // skip to the inital clowns
IF NOT ANIMPOSTFX_IS_RUNNING(FX_DrugsSkip)
CPRINTLN(DEBUG_MISSION, "[BARRY2] - REPLAY START - CP_MISSION_START - PLAY FX:FX_DrugsSkip")
ANIMPOSTFX_PLAY(FX_DrugsSkip, 0, TRUE)
ENDIF
BREAK
CASE CP_MID_STAGE
START_REPLAY_SETUP((<<188.9320, -952.0983, 29.0923>>), 325.7944, FALSE)
SETUP_TREVOR_DIALOG()
Do_Z_Skip(Z_SKIP_TO_FOURTH_WAVE) // skip to the 2 wave of clowns
PRINT_NOW("B2_PRIME", DEFAULT_GOD_TEXT_TIME, 1) // Kill the Clowns
IF NOT ANIMPOSTFX_IS_RUNNING(FX_DrugsSkip)
CPRINTLN(DEBUG_MISSION, "[BARRY2] - REPLAY START - PLAY FX:FX_DrugsSkip")
ANIMPOSTFX_PLAY(FX_DrugsSkip, 0, TRUE)
ENDIF
BREAK
CASE CP_OUTRO
SAFE_FADE_SCREEN_OUT_TO_BLACK()
Do_Z_Skip(Z_SKIP_TO_OUTRO) // skip to the end
BREAK
DEFAULT
SCRIPT_ASSERT("Replay in progress: Unknown checkpoint selected")
BREAK
ENDSWITCH
ENDIF
ENABLE_CLOWN_BLOOD_VFX(TRUE)
RESET_MISSION_COMBAT_PARAMETERS(combatParams)
CPRINTLN(DEBUG_MISSION, "SETUP DONE")
ENDPROC
/// PURPOSE:
/// Cleans up the scripted cameras
PROC CLEANUP_CAMERAS()
IF DOES_CAM_EXIST(ciPerformCamera1)
SET_CAM_ACTIVE(ciPerformCamera1, FALSE)
DESTROY_CAM(ciPerformCamera1)
ENDIF
ENDPROC
// PURPOSE:
/// Cleans mission
PROC MISSION_CLEANUP()
IF IS_AUDIO_SCENE_ACTIVE(sndAlienAmbientScene)
STOP_AUDIO_SCENE(sndAlienAmbientScene)
ENDIF
SAFE_STOP_AND_RELEASE_SOUND_ID(iApplauseSound)
// @SBA - adding spectators to this
CLEANUP_ALL_SPECTATOR_PEDS()
FLEE_ALL_CLOWN_PEDS()
CLEANUP_ALL_CLOWN_PEDS()
CLEANUP_ALL_CLOWN_GENERATORS()
IF DOES_ENTITY_EXIST(sRCLauncherDataLocal.pedID[0])
DELETE_PED(sRCLauncherDataLocal.pedID[0])
ENDIF
SET_PLAYER_HEALTH_RECHARGE_MULTIPLIER(PLAYER_ID(), 1.0)
SET_PLAYER_WEAPON_DAMAGE_MODIFIER(GET_PLAYER_INDEX(), 1.0)
SET_PED_CAN_SWITCH_WEAPON(PLAYER_PED_ID(), TRUE)
SPECIAL_ABILITY_UNLOCK(GET_PLAYER_PED_MODEL(CHAR_TREVOR))
SET_PED_USING_ACTION_MODE(PLAYER_PED_ID(), FALSE)
SAFE_REMOVE_BLIP(locationBlip)
// @SBA - make sure cams are gone
CLEANUP_CAMERAS()
ENABLE_CLOWN_BLOOD_VFX(FALSE)
ENDPROC
/// PURPOSE:
/// Cleanups Script and terminates thread - this should be the last function called
PROC SCRIPT_CLEANUP()
// Ensure launcher is cleaned up
RC_CLEANUP_LAUNCHER()
// If the mission was triggered then additional mission cleanup will be required.
IF (Random_Character_Cleanup_If_Triggered())
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Random Character Script was triggered so additional cleanup required")
#ENDIF
ENDIF
SET_PLAYER_HEALTH_RECHARGE_MULTIPLIER(GET_PLAYER_INDEX(), 1.0)
SET_PLAYER_WEAPON_DAMAGE_MODIFIER(GET_PLAYER_INDEX(), 1.0)
IF HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), playerWeapon)
SET_PED_INFINITE_AMMO(PLAYER_PED_ID(), FALSE, playerWeapon)
ENDIF
CLEANUP_SCREEN_FX()
MISSION_CLEANUP()
UNLOAD_REQUESTED_ASSETS(assetRequester)
//UNLOAD_MISSION_ASSETS()
SET_ALL_SHOPS_TEMPORARILY_UNAVAILABLE(FALSE)
SET_CONTROL_SHAKE(PLAYER_CONTROL, 0, 0)
DISABLE_TAXI_HAILING(FALSE)
#IF IS_DEBUG_BUILD
CLEANUP_DEBUG_WIDGETS()
#ENDIF
// restore world based things
SHAKE_GAMEPLAY_CAM("DRUNK_SHAKE", 0)
// @SBA - adding spectators to this
DELETE_ALL_SPECTATOR_PEDS()
// @SBA - restore armor
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
CPRINTLN(DEBUG_MISSION, "MISSION_SETUP: Restoring player's previous armor level of: ", iPlayerStartingArmor)
SET_PED_ARMOUR(PLAYER_PED_ID(), iPlayerStartingArmor)
ENDIF
SAFE_REMOVE_BLIP(locationBlip)
CLEANUP_ALL_CLOWN_PEDS(TRUE)
CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
//CLEAR_AREA_OF_VEHICLES(vMainLocation, 30.0)
REMOVE_DECALS_IN_RANGE(vMissionStart, 500.0)
SET_TIME_SCALE(1.0)
DEACTIVATE_AUDIO_SLOWMO_MODE("BARRY_02_SLOWMO")
SET_AUDIO_FLAG("AllowScriptedSpeechInSlowMo", FALSE)
SET_AUDIO_FLAG("AllowAmbientSpeechInSlowMo", FALSE)
DISABLE_CHEAT(CHEAT_TYPE_SPAWN_VEHICLE, FALSE)
DISABLE_CHEAT(CHEAT_TYPE_GIVE_WEAPONS, FALSE)
ENABLE_ALL_DISPATCH_SERVICES(TRUE)
CLEAR_ALL_PICKUP_REWARD_TYPE_SUPPRESSION()
DISABLE_CELLPHONE(FALSE)
ENABLE_AMBIENT_PEDS_AND_VEHICLES(TRUE, TRUE)
UNBLOCK_SCENARIOS_AND_AMBIENT(scenarioBlock)
CLEAR_WEATHER_TYPE_PERSIST()
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
CLEAR_AMBIENT_ZONE_STATE(sAmbientZone, TRUE)
RC_CleanupSceneEntities(sRCLauncherDataLocal, FALSE)
TERMINATE_THIS_THREAD()
ENDPROC
/// PURPOSE:
/// Handles Mission Passed
PROC SCRIPT_PASSED()
#IF IS_DEBUG_BUILD
CPRINTLN(DEBUG_MISSION, "Mission Passed")
#ENDIF
//FLEE_ALL_ALIEN_PEDS()
IF HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), playerWeapon)
SET_PED_INFINITE_AMMO(PLAYER_PED_ID(), FALSE, playerWeapon)
ENDIF
REMOVE_ALL_PED_WEAPONS(PLAYER_PED_ID())
//SIMULATE_PLAYER_INPUT_GAIT(PLAYER_ID(), PEDMOVE_WALK, 1000)
// ADD_CONTACT_TO_PHONEBOOK(CHAR_BARRY, TREVOR_BOOK)
// This needs to be done before random character passed as the replay values are reset
Restore_Game_State_Snapshot_Weapons(g_startSnapshot)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
RESTORE_PLAYER_PED_WEAPONS(PLAYER_PED_ID())
ENDIF
CPRINTLN(DEBUG_MISSION, "Starting postRC_Barry1and2")
START_NEW_SCRIPT("postRC_Barry1and2", DEFAULT_STACK_SIZE)
SET_SCRIPT_AS_NO_LONGER_NEEDED("postRC_Barry1and2")
Random_Character_Passed(CP_RAND_C_BAR2)
SCRIPT_CLEANUP()
ENDPROC
//----------------------
// STATE FUNCTIONS
//----------------------
/// PURPOSE:
/// @SBA - creates the peds for the opening performance
PROC CREATE_INITIAL_PERFORMANCE_PEDS()
INT idx
// @SBA - keeping in case we get new lead out
// Init and make spectators, ensure they start clapping immediately
// INITIALIZE_PERFORMANCE_SPECTATOR_DATA()
// REPEAT COUNT_OF(ssSpectator) idx
// IF CREATE_SPECTATOR_PED(idx)
// SET_ENTITY_VISIBLE(ssSpectator[idx].piPed, TRUE)
// ssSpectator[idx].ssState = SS_WATCH_CLOWN
// ENDIF
// ENDREPEAT
// Create first clown (center), set "special" for custom treatment
IF GET_FREE_CLOWN_PED_INDEX(idx)
//IF CREATE_CLOWN_PED(clownPed[idx], (<<175.2541, -958.2550, 30.1>>), 262.4564, TRUE, TRUE)
IF CREATE_CLOWN_PED(clownPed[idx], (<<163.92494, -956.99603, 29.09192>>), 262.4564, TRUE)
i1stPerformanceClownID = idx
SET_CLOWN_TYPE(clownPed[i1stPerformanceClownID], SCT_SPECIAL)
ENDIF
ENDIF
// Clown on right
IF GET_FREE_CLOWN_PED_INDEX(idx)
CREATE_CLOWN_PED(clownPed[idx], (<<166.44772, -955.05847, 29.09192>>), 263.4564)
i2ndPerformanceClownID = idx
SET_CLOWN_TYPE(clownPed[i2ndPerformanceClownID], SCT_SPECIAL)
ENDIF
// clown on left
IF GET_FREE_CLOWN_PED_INDEX(idx)
CREATE_CLOWN_PED(clownPed[idx], (<<168.95203, -960.75641, 29.07847>>), 265.4564)
i3rdPerformanceClownID = idx
SET_CLOWN_TYPE(clownPed[i3rdPerformanceClownID], SCT_SPECIAL)
ENDIF
ENDPROC
/// PURPOSE:
/// @SBA - these are the last two clowns who pop in for the performance, straight to active state
PROC CREATE_FINAL_PERFORMANCE_CLOWNS()
INT idx
// Clown on right
IF GET_FREE_CLOWN_PED_INDEX(idx)
CREATE_CLOWN_PED(clownPed[idx], (<<174.05942, -960.29022, 30.09226>>), 262.4564, TRUE)
i2ndPerformanceClownID = idx
SET_CLOWN_TYPE(clownPed[i2ndPerformanceClownID], SCT_SPECIAL)
ENDIF
// clown on left
IF GET_FREE_CLOWN_PED_INDEX(idx)
CREATE_CLOWN_PED(clownPed[idx], (<<175.53503, -956.09955, 30.09226>>), 265.4564, TRUE)
i3rdPerformanceClownID = idx
SET_CLOWN_TYPE(clownPed[i3rdPerformanceClownID], SCT_SPECIAL)
ENDIF
ENDPROC
/// PURPOSE:
/// @SBA - creates a clown performer (if desired) and an random audience of spectators
/// PARAMS:
/// SpawnZone - the general area in which the spawn points are grouped (SZ_ZONE_1 = start, 2 = middle, 3 = end)
/// iMinNumSpectators - Minimum number of spectators to create.
/// iMaxNumSpectators - Max number to create. A random number bewteen min and max will be spawned, depedning on available slots.
/// bMakeClown - Set FALSE if you just want to make some spectators that will flee (and no clown)
PROC CREATE_GENERAL_CLOWN_PERFORMANCE(SPAWN_ZONES SpawnZone, INT iMinNumSpectators = 2, INT iMaxNumSpectators = kiNumberOfSpectators, BOOL bMakeClown = TRUE)
// Exit if too many or too few spectators specified
IF iMinNumSpectators < 1
OR iMaxNumSpectators > kiNumberOfSpectators
OR iMinNumSpectators > iMaxNumSpectators
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: *** Spectators out of range! iMinNumSpectators = ", iMinNumSpectators, "; iMaxNumSpectators = ", iMaxNumSpectators)
EXIT
ENDIF
// How many spectators could we create at maximum?
INT iAvailableSlots = kiNumberOfSpectators - GET_ALIVE_SPECTATOR_PED_COUNT()
// Are there enough slots at minimum?
IF iAvailableSlots < iMinNumSpectators
// Do we want to force this? Yes.
IF iAvailableSlots > 0
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: Need to increase min spectators: iMinNumSpectators = ", iMinNumSpectators, "; iAvailableSlots = ", iAvailableSlots)
iMinNumSpectators = iAvailableSlots
ELSE
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: NO AVAILABLE SLOTS! iMinNumSpectators = ", iMinNumSpectators, "; iAvailableSlots = ", iAvailableSlots)
EXIT
ENDIF
ENDIF
// Can we create the max number requested? If not, set max to what is available.
IF iAvailableSlots < iMaxNumSpectators
IF iAvailableSlots > 0
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: Need to reduce max spectators: iMaxNumSpectators = ", iMaxNumSpectators, "; iAvailableSlots = ", iAvailableSlots)
iMaxNumSpectators = iAvailableSlots
ELSE
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: NO AVAILABLE SLOTS! iMaxNumSpectators = ", iMaxNumSpectators, "; iAvailableSlots = ", iAvailableSlots)
EXIT
ENDIF
ENDIF
// Pick a random number of spectators based on what's avaialble
INT iRandomNum = GET_RANDOM_INT_IN_RANGE(iMinNumSpectators, iMaxNumSpectators)
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: Randomized number of spectators = ", iRandomNum)
INT ind, idx
IF GET_SPECIFIC_PERFORMANCE_SPAWN_DATA(SpawnZone, idx, NOT bMakeClown)
IF bMakeClown
IF GET_FREE_CLOWN_PED_INDEX(ind)
IF CREATE_CLOWN_PED(clownPed[ind], CPD_SpecificData[idx].vClownPos, CPD_SpecificData[idx].fClownHead, TRUE, TRUE)
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: Created performance clown")
SET_CLOWN_TYPE(clownPed[ind], SCT_PERFORM)
SPAWN_SPECTATORS_FOR_GENERAL_PERFORMANCE(CPD_SpecificData[idx], iRandomNum)
ELSE
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: *** Could not create performance clown! ***")
ENDIF
ENDIF
ELSE
CPRINTLN(DEBUG_MISSION, "CREATE_GENERAL_CLOWN_PERFORMANCE: No Clown Requested. Making just spectators.")
SPAWN_SPECTATORS_FOR_GENERAL_PERFORMANCE(CPD_SpecificData[idx], iRandomNum, NOT bMakeClown)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Puts all living/active clowns into the active state
PROC RETURN_CLOWNS_TO_STATE_MACHINE()
INT i
REPEAT (COUNT_OF(clownPed)) i
IF IS_CLOWN_PED_ALIVE(clownPed[i])
clownPed[i].aState = CS_ACTIVE
ENDIF
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Creates initial clowns
PROC CREATE_INITIAL_CLOWNS()
INT ind
IF bInitialClowns = TRUE
EXIT
ENDIF
IF GET_FREE_CLOWN_PED_INDEX(ind)
IF CREATE_CLOWN_PED(clownPed[ind], <<181.1, -951.9, 30.1>>)
// @SBA this clown goes to attack first
//clownPed[ind].iDanceTimer = 0
ENDIF
ENDIF
IF GET_FREE_CLOWN_PED_INDEX(ind)
IF CREATE_CLOWN_PED(clownPed[ind], <<173.0, -956.9, 30.1>>)
clownPed[ind].iDanceTimer = 0
ENDIF
ENDIF
IF GET_FREE_CLOWN_PED_INDEX(ind)
IF CREATE_CLOWN_PED(clownPed[ind], <<174.7, -948.1, 30.1>>)
clownPed[ind].iDanceTimer = 0
ENDIF
ENDIF
// @SBA - Create a performance with 5 spectators
CREATE_GENERAL_CLOWN_PERFORMANCE(SZ_ZONE_1, 5)
CPRINTLN(DEBUG_MISSION, "INITIAL CLOWNS CREATED")
bInitialClowns = TRUE
ENDPROC
// Get clown dancing for initial performance
FUNC BOOL MAKE_CLOWN_DANCE_FOR_PERFORMANCE(CLOWN_PED &clown, STRING sDanceAnim, FLOAT fStartPhase = 0.0)
IF clown.aState = CS_NULL
IF NOT IS_ENTITY_PLAYING_ANIM(clown.pedID, sMissionAnimDanceDictionary, sDanceAnim)
CPRINTLN(DEBUG_MISSION, "MAKE_CLOWN_DANCE_FOR_PERFORMANCE: PERFORM, CLOWN!!")
clown.danceAnim = sDanceAnim
TASK_PLAY_ANIM(clown.pedID, sMissionAnimDanceDictionary, clown.danceAnim, NORMAL_BLEND_IN, -1, -1, AF_DEFAULT, fStartPhase) //, kfMimeStartPhase)
ELSE
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
// when clown is done dancing, get him to aim at player (for initial performance)
FUNC BOOL HAVE_CLOWN_AIM_AT_PLAYER(CLOWN_PED &clown)
// If clown died, just assume true
IF NOT IS_ENTITY_OK(clown.pedID)
RETURN TRUE
ENDIF
IF (GET_SCRIPT_TASK_STATUS(clown.pedID, SCRIPT_TASK_AIM_GUN_AT_ENTITY) > PERFORMING_TASK)
IF NOT IS_ENTITY_PLAYING_ANIM(clown.pedID, sMissionAnimDanceDictionary, clown.danceAnim)
CPRINTLN(DEBUG_MISSION, "HAVE_CLOWN_AIM_AT_PLAYER: AIM, CLOWN!!")
// Reset the timer here to avoid premature dancing
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinClownDanceDelay, iMaxClownDanceDelay)
TASK_AIM_GUN_AT_ENTITY(clown.pedID, PLAYER_PED_ID(), -1, TRUE)
RETURN TRUE
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
// when clown is done dancing, get him to attack player (for initial performance)
FUNC BOOL HAVE_CLOWN_ATTACK_PLAYER(CLOWN_PED &clown)
// If clown died, just assume true
IF NOT IS_ENTITY_OK(clown.pedID)
RETURN TRUE
ENDIF
IF (GET_SCRIPT_TASK_STATUS(clown.pedID, SCRIPT_TASK_COMBAT) > PERFORMING_TASK)
IF NOT IS_ENTITY_PLAYING_ANIM(clown.pedID, sMissionAnimDanceDictionary, clown.danceAnim)
CPRINTLN(DEBUG_MISSION, "HAVE_CLOWN_ATTACK_PLAYER: ATTACK, CLOWN!!")
clown.iDanceTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinClownDanceDelay, iMaxClownDanceDelay)
clown.aState = CS_ACTIVE
TASK_COMBAT_PED(clown.pedID, PLAYER_PED_ID(), COMBAT_PED_DISABLE_AIM_INTRO)
RETURN TRUE
ENDIF
ELSE
RETURN TRUE
ENDIF
RETURN FALSE
ENDFUNC
// @SBA - special case stuff for the lead out performance
FUNC BOOL INTRO_PERFORMANCE_ATTACK_SPECTATORS(CLOWN_PED &clown, PED_INDEX pi1stTarget, PED_INDEX pi2ndTarget = NULL)
IF clownPed[i1stPerformanceClownID].aState != CS_NULL
RETURN FALSE
ENDIF
IF NOT IS_PED_INJURED(clown.pedID)
AND NOT IS_PED_INJURED(pi1stTarget)
IF GET_SCRIPT_TASK_STATUS(clown.pedID, SCRIPT_TASK_PERFORM_SEQUENCE) > PERFORMING_TASK
SEQUENCE_INDEX seq
OPEN_SEQUENCE_TASK(seq)
TASK_AIM_GUN_AT_ENTITY(NULL, pi1stTarget, GET_RANDOM_INT_IN_RANGE(750, 1000))
TASK_SHOOT_AT_ENTITY(NULL, pi1stTarget, GET_RANDOM_INT_IN_RANGE(500, 750), FIRING_TYPE_CONTINUOUS)
IF pi2ndTarget != NULL
TASK_AIM_GUN_AT_ENTITY(NULL, pi2ndTarget, GET_RANDOM_INT_IN_RANGE(500, 750))
TASK_SHOOT_AT_ENTITY(NULL, pi2ndTarget, GET_RANDOM_INT_IN_RANGE(500, 750), FIRING_TYPE_CONTINUOUS)
TASK_AIM_GUN_AT_ENTITY(NULL, PLAYER_PED_ID(), INFINITE_TASK_TIME)
// ELSE
// TASK_SHOOT_AT_ENTITY(NULL, pi1stTarget, 500, FIRING_TYPE_CONTINUOUS)
ENDIF
CLOSE_SEQUENCE_TASK(seq)
TASK_PERFORM_SEQUENCE(clown.pedID, seq)
CLEAR_SEQUENCE_TASK(seq)
RETURN TRUE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Handles the timing of the intro lead-out performance in which the clowns shoot the spectators
/// RETURNS:
/// TRUE when the performance is complete
FUNC BOOL HANDLE_INTRO_PERFORMANCE()
// for asserts
IS_ENTITY_OK(clownPed[i1stPerformanceClownID].pedID)
IS_ENTITY_OK(clownPed[i2ndPerformanceClownID].pedID)
IS_ENTITY_OK(clownPed[i3rdPerformanceClownID].pedID)
IS_ENTITY_OK(PLAYER_PED_ID())
// Trevor's first line
IF NOT bTrevFirstLine
IF psPerformanceState = PS_KILL_CLOWNS
AND (GET_GAME_TIMER() > iFirstDialogTime)
ADD_PED_FOR_DIALOGUE(convoPlayer, ENUM_TO_INT(CHAR_TREVOR), PLAYER_PED_ID(), "TREVOR")
IF CREATE_CONVERSATION(convoPlayer, "BARY2AU", "BARY2_FREAK", CONV_PRIORITY_HIGH, DO_NOT_DISPLAY_SUBTITLES)
CPRINTLN(DEBUG_MISSION, "Trevor's first rant")
bTrevFirstLine = TRUE
ENDIF
ENDIF
ENDIF
SWITCH psPerformanceState
CASE PS_MIME_CLOWN_MIME
// Ensure player control is off
IF IS_PLAYER_CONTROL_ON(PLAYER_ID())
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: PLAYER CONTROL was on, turning off.")
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
ENDIF
// trigger music if not triggered
IF (bTransitionStarted = FALSE)
bTransitionStarted = TRUE
TRIGGER_MUSIC_EVENT("RC18B_START")
ENDIF
// Put first clowns into dance anim once done teleporting
IF MAKE_CLOWN_DANCE_FOR_PERFORMANCE(clownPed[i1stPerformanceClownID], "clown_idle_0")
AND MAKE_CLOWN_DANCE_FOR_PERFORMANCE(clownPed[i2ndPerformanceClownID], "clown_idle_6", 0.1)
AND MAKE_CLOWN_DANCE_FOR_PERFORMANCE(clownPed[i3rdPerformanceClownID], "clown_idle_3", 0.1)
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: ALL CLOWNS SHOULD BE DANCING")
psPerformanceState = PS_MOVE_PLAYER
ENDIF
BREAK
CASE PS_MOVE_PLAYER
// have clown on left laugh (if not already speaking)
IF NOT IS_AMBIENT_SPEECH_PLAYING(clownPed[i3rdPerformanceClownID].pedID)
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: Laugh, Clown, Laugh!")
PLAY_PED_AMBIENT_SPEECH_WITH_VOICE(clownPed[i3rdPerformanceClownID].pedID, "CLOWN_LAUGH", "CLOWNS", SPEECH_PARAMS_FORCE_SHOUTED_CLEAR)
ENDIF
// Hold on second cam after interp, and move the player
IF DOES_CAM_EXIST(ciPerformCamera1)
IF IS_CAM_ACTIVE(ciPerformCamera1)
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: CAM PLAYING - MOVING PLAYER")
// @SBA - teleporting player
SAFE_TELEPORT_ENTITY(PLAYER_PED_ID(), (<<187.78902, -959.62036, 29.00801>>), 85.0)
// dummy ref
CANCEL_TIMER(tmrPerformance)
//psPerformanceState = PS_SPAWN_WEAPON
psPerformanceState = PS_KILLING_SPECTATORS
ENDIF
ENDIF
BREAK
// @SBA - saving this in case we get a new lead out
// CASE PS_SPAWN_WEAPON
// IF SPAWN_GUN_IN_CLOWNS_HAND(clownPed[i1stPerformanceClownID], sMimeAnimDict, kfMimeGunSpawnPhase, kfMimeEndPhase, bPlayedGunSmokeFX)
// // Get a target and aim at it while we wait for reinforcements
// IF NOT IS_PED_INJURED(ssSpectator[1].piPed)
// TASK_AIM_GUN_AT_ENTITY(clownPed[i1stPerformanceClownID].pedID, ssSpectator[1].piPed, -1)
// ENDIF
// // Start timer for attack and last clown spawns
// START_TIMER_NOW(tmrPerformance)
// psPerformanceState = PS_SPAWN_LAST_CLOWNS
// ENDIF
// BREAK
// CASE PS_SPAWN_LAST_CLOWNS
// // Check the timer to spawn in the rest of the killer clowns
// IF TIMER_DO_ONCE_WHEN_READY(tmrPerformance, 0.200)
// CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: Spawning last clowns")
// CREATE_FINAL_PERFORMANCE_CLOWNS()
// // Start timer for attack and last clown spawns
// START_TIMER_NOW(tmrPerformance)
// psPerformanceState = PS_CLOWNS_ATTACK_SPECTATORS
// ENDIF
// BREAK
// CASE PS_CLOWNS_ATTACK_SPECTATORS
// // Check timer, then set intial clown into attack state
// IF TIMER_DO_ONCE_WHEN_READY(tmrPerformance, 0.100)
// CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: 1st Clown should be attacking spectators.")
// MAKE_CLOWN_MORE_AGGRESSIVE(clownPed[i1stPerformanceClownID], TRUE)
// INTRO_PERFORMANCE_ATTACK_SPECTATORS(clownPed[i1stPerformanceClownID], ssSpectator[1].piPed)
// SET_CLOWN_TYPE(clownPed[i1stPerformanceClownID], SCT_NORMAL)
// psPerformanceState = PS_CLOWNS_ATTACK_SPECTATORS_2
// ENDIF
// BREAK
// CASE PS_CLOWNS_ATTACK_SPECTATORS_2
// IF INTRO_PERFORMANCE_ATTACK_SPECTATORS(clownPed[i2ndPerformanceClownID], ssSpectator[0].piPed, ssSpectator[2].piPed)
// AND INTRO_PERFORMANCE_ATTACK_SPECTATORS(clownPed[i3rdPerformanceClownID], ssSpectator[4].piPed, ssSpectator[3].piPed)
// CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: Last two clowns should be attacking spectators.")
// psPerformanceState = PS_KILLING_SPECTATORS
// ENDIF
// BREAK
CASE PS_KILLING_SPECTATORS
// Put first clown into his dance anim once he's done a'killin'
// IF clownPed[i1stPerformanceClownID].aState = CS_NULL
// IF GET_SCRIPT_TASK_STATUS(clownPed[i1stPerformanceClownID].pedID, SCRIPT_TASK_PERFORM_SEQUENCE) > PERFORMING_TASK
// CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: 1st clown is ready to do happy dance.")
// clownPed[i1stPerformanceClownID].aState = CS_DANCE_START
// ENDIF
// ENDIF
// Have spectators died
// IF GET_ALIVE_SPECTATOR_PED_COUNT() = 0
// 1st clown should be done dancing first, but monitor others
HAVE_CLOWN_AIM_AT_PLAYER(clownPed[i2ndPerformanceClownID])
HAVE_CLOWN_AIM_AT_PLAYER(clownPed[i3rdPerformanceClownID])
IF HAVE_CLOWN_AIM_AT_PLAYER(clownPed[i1stPerformanceClownID])
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: 1st clown should be aiming")
// give the player his weapon
FORCE_PLAYER_WEAPON()
// Reset to the game cam
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
RENDER_SCRIPT_CAMS(FALSE, FALSE, DEFAULT_INTERP_IN_TIME)
ELSE
RENDER_SCRIPT_CAMS(FALSE, TRUE, DEFAULT_INTERP_IN_TIME)
ENDIF
SET_CAM_ACTIVE(ciPerformCamera1, FALSE)
psPerformanceState = PS_RETURN_PLAYER_CONTROL
ENDIF
BREAK
CASE PS_RETURN_PLAYER_CONTROL
// update aims
HAVE_CLOWN_AIM_AT_PLAYER(clownPed[i2ndPerformanceClownID])
HAVE_CLOWN_AIM_AT_PLAYER(clownPed[i3rdPerformanceClownID])
// Return player control once the camera is done interpolating
IF IS_GAMEPLAY_CAM_RENDERING()
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: NOW BACK TO GAME CAMERA")
IF NOT IS_PLAYER_CONTROL_ON(PLAYER_ID())
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: RESTORING PLAYER CONTROL")
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ENDIF
// Print objective
PRINT_NOW("B2_PRIME", DEFAULT_GOD_TEXT_TIME, 1) // Kill the Clowns
RC_END_CUTSCENE_MODE(TRUE, FALSE)
psPerformanceState = PS_CLOWNS_ATTACK_PLAYER
ENDIF
BREAK
CASE PS_CLOWNS_ATTACK_PLAYER
// 1st clown should finish first, others can keep aiming
HAVE_CLOWN_AIM_AT_PLAYER(clownPed[i2ndPerformanceClownID])
HAVE_CLOWN_AIM_AT_PLAYER(clownPed[i3rdPerformanceClownID])
IF HAVE_CLOWN_ATTACK_PLAYER(clownPed[i1stPerformanceClownID])
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: 1st Clown is attacking!")
iFirstDialogTime = GET_GAME_TIMER() + 1500
psPerformanceState = PS_KILL_CLOWNS
ENDIF
BREAK
CASE PS_KILL_CLOWNS
HAVE_CLOWN_ATTACK_PLAYER(clownPed[i1stPerformanceClownID])
HAVE_CLOWN_ATTACK_PLAYER(clownPed[i2ndPerformanceClownID])
HAVE_CLOWN_ATTACK_PLAYER(clownPed[i3rdPerformanceClownID])
// check if clowns are dead
IF (iAliveClownCount = 0)
CPRINTLN(DEBUG_MISSION, "HANDLE_INTRO_PERFORMANCE: ALL CLOWNS ARE DEAD - DONE!")
psPerformanceState = PS_DONE
RETURN TRUE
ENDIF
BREAK
CASE PS_DONE
// Nothing
BREAK
ENDSWITCH
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Updates Leading Sequence
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_LEADIN(STAGE_PROGRESS &prog)
RC_PLAYER_TRIGGER_SCENE_LOCK_IN()
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_DETONATE)
SET_ALL_RANDOM_PEDS_FLEE_THIS_FRAME(PLAYER_ID())
HANDLE_LOCK_PLAYER_IN_FRONT_OF_TABLE()
SWITCH (prog)
CASE SP_LOADING
REQUEST_MISSION_ASSETS()
SECURE_REQUEST_AND_LOAD_ANIM_DICT(sMissionAnimDanceDictionary, FALSE)
prog = SP_SETUP
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
IF GET_CAM_VIEW_MODE_FOR_CONTEXT(CAM_VIEW_MODE_CONTEXT_ON_FOOT) = CAM_VIEW_MODE_FIRST_PERSON
SET_GAMEPLAY_ENTITY_HINT(sRCLauncherDataLocal.pedID[0], (<<0.0, 0, 0.3>>), TRUE, -1, 3000)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(0.0)
ELSE
SET_GAMEPLAY_ENTITY_HINT(sRCLauncherDataLocal.pedID[0], (<<0.6, 0, 0.3>>), TRUE, -1, 3000)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_SIDE_OFFSET(-0.04)
ENDIF
SET_GAMEPLAY_HINT_FOLLOW_DISTANCE_SCALAR(0.43)
//SET_GAMEPLAY_HINT_BASE_ORBIT_PITCH_OFFSET(1.0)
SET_GAMEPLAY_HINT_CAMERA_RELATIVE_VERTICAL_OFFSET(-0.02)
SET_GAMEPLAY_HINT_FOV(30.00)
SET_GAMEPLAY_HINT_CAMERA_BLEND_TO_FOLLOW_PED_MEDIUM_VIEW_MODE(TRUE)
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
TASK_LOOK_AT_ENTITY(PLAYER_PED_ID(), sRCLauncherDataLocal.pedID[0], -1)
ENDIF
ENDIF
BREAK
CASE SP_SETUP
IF HAS_ANIM_DICT_LOADED(sMissionAnimDanceDictionary)
AND NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED()
CPRINTLN(DEBUG_MISSION, "LEAD-IN ANIMS LOADED")
structPedsForConversation sConversation
ADD_PED_FOR_DIALOGUE(sConversation, 1, PLAYER_PED_ID(), "TREVOR")
ADD_PED_FOR_DIALOGUE(sConversation, 0, sRCLauncherDataLocal.pedID[0], "BARRY")
IF CREATE_CONVERSATION(sConversation ,"BARY2AU", "BAR_3_RCM_LI", CONV_PRIORITY_MEDIUM, DISPLAY_SUBTITLES)
TASK_PLAY_ANIM(sRCLauncherDataLocal.pedID[0], sMissionAnimDanceDictionary, "lead_in", NORMAL_BLEND_IN, SLOW_BLEND_OUT, -1, AF_HOLD_LAST_FRAME)
TASK_LOOK_AT_ENTITY(sRCLauncherDataLocal.pedID[0], PLAYER_PED_ID(), INFINITE_TASK_TIME, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_VERY_HIGH)
CPRINTLN(DEBUG_MISSION, "STARTED PLAYING LEAD-IN CONVERSATION")
prog = SP_RUNNING
iStateTimeOut = GET_GAME_TIMER() + 30000
ENDIF
ENDIF
BREAK
CASE SP_RUNNING
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
IF NOT IS_ANY_CONVERSATION_ONGOING_OR_QUEUED() OR (GET_GAME_TIMER() > iStateTimeOut )
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
TASK_CLEAR_LOOK_AT(PLAYER_PED_ID())
ENDIF
prog = SP_CLEANUP
ENDIF
ENDIF
BREAK
CASE SP_CSKIPPED
BREAK
CASE SP_CLEANUP
IF IS_GAMEPLAY_HINT_ACTIVE()
STOP_GAMEPLAY_HINT()
ENDIF
CPRINTLN(DEBUG_MISSION, "LEAD IN FINISHED")
stageEnum = SE_INTRO
prog = SP_LOADING
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates Intro Sequence
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_INTRO(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
//DELETE_ALL_ALIEN_PEDS()
CPRINTLN(DEBUG_MISSION, "REQUESTED CUTSCENE")
RC_REQUEST_CUTSCENE("BAR_3_RCM")
stageProgress = SP_SETUP
START_MISSION_DEBUG_TIMER()
//CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
BREAK
CASE SP_SETUP
bHasPlayerCameraExitState = FALSE
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Trevor", PLAYER_PED_ID(), GET_ENTITY_MODEL(PLAYER_PED_ID()))
ENDIF
SET_CUTSCENE_PED_PROP_VARIATION(sSceneHandleBarry, ANCHOR_EYES, 0)
CPRINTLN(DEBUG_MISSION, "PED CUTSCENE VARIATIONS SET")
ENDIF
CPRINTLN(DEBUG_MISSION, "CHECKING TO SEE IF CUTSCENE IS OK TO START")
IF RC_IS_CUTSCENE_OK_TO_START()
CPRINTLN(DEBUG_MISSION, "CUTSCENE IS OK TO START")
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.pedID[0], sSceneHandleBarry, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
CPRINTLN(DEBUG_MISSION, "REGISTERED BARRY")
ELSE
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.pedID[0], sSceneHandleBarry, CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, GET_NPC_PED_MODEL(CHAR_BARRY))
CPRINTLN(DEBUG_MISSION, "REGISTERED NEW BARRY")
ENDIF
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_TABLE])
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.objID[OBJ_TABLE], sSceneHandleTable, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
CPRINTLN(DEBUG_MISSION, "REGISTERED TABLE")
ELSE
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.objID[OBJ_TABLE], sSceneHandleTable, CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, PROP_PROTEST_TABLE_01)
CPRINTLN(DEBUG_MISSION, "REGISTERED NEW TABLE")
ENDIF
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_CHAIR])
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.objID[OBJ_CHAIR], sSceneHandleChair, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
CPRINTLN(DEBUG_MISSION, "REGISTERED CHAIR")
ELSE
REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.objID[OBJ_CHAIR], sSceneHandleChair, CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, PROP_CHAIR_08)
CPRINTLN(DEBUG_MISSION, "REGISTERED NEW CHAIR")
ENDIF
// @SBA - adding this prop. Uncomment the registrations once the cutscene handle is fixed (otherwise causes and assert)
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_PAPERS])
//REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.objID[OBJ_PAPERS], sSceneHandlePapers, CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
SET_OBJECT_AS_NO_LONGER_NEEDED(sRCLauncherDataLocal.objID[OBJ_PAPERS]) // REMOVE THIS!
DUMMY_REFERENCE_STRING(sSceneHandlePapers) // AND THIS!
CPRINTLN(DEBUG_MISSION, "REGISTERED PAPERS")
ELSE
//REGISTER_ENTITY_FOR_CUTSCENE(sRCLauncherDataLocal.objID[OBJ_PAPERS], sSceneHandlePapers, CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, P_A4_Sheets_S)
CPRINTLN(DEBUG_MISSION, "REGISTERED NEW PAPERS")
ENDIF
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Trevor", CU_ANIMATE_EXISTING_SCRIPT_ENTITY)
CPRINTLN(DEBUG_MISSION, "REGISTERED TREVOR")
ENDIF
// set up cut cam for post cutscene
ciPerformCamera1 = CREATE_CAM_WITH_PARAMS("DEFAULT_SCRIPTED_CAMERA", <<188.1366, -957.7827, 30.6514>>, <<-5.5067, -8.0000, 92.8053>>, 40.0)
// Cleanup launcher which will remove lead-in blip
RC_CLEANUP_LAUNCHER()
START_CUTSCENE()
REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW)
SET_CUTSCENE_CAN_BE_SKIPPED(FALSE)
WAIT(0)
ENABLE_AMBIENT_PEDS_AND_VEHICLES(FALSE, FALSE, TRUE, FALSE)
RESOLVE_MISSION_VEHICLES_FOR_CUTSCENE()
RC_START_CUTSCENE_MODE(vMissionStart, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE)
BLOCK_SCENARIOS_AND_AMBIENT(scenarioBlock)
CLEANUP_SCREEN_FX()
CREATE_STANDING_SIGN(sRCLauncherDataLocal.objID[OBJ_SIGN], mnProtestSign)
SAFE_FADE_SCREEN_IN_FROM_BLACK(500, FALSE)
REQUEST_MISSION_ASSETS()
stageProgress = SP_RUNNING
ENDIF
BREAK
CASE SP_RUNNING
IF NOT IS_CUTSCENE_PLAYING()
SET_TIME_SCALE(fTimeScale)
ACTIVATE_AUDIO_SLOWMO_MODE("BARRY_02_SLOWMO")
SET_AUDIO_FLAG("AllowScriptedSpeechInSlowMo", TRUE)
SET_AUDIO_FLAG("AllowAmbientSpeechInSlowMo", TRUE)
// @SBA - don't want player to have control yet or give weapon(?)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
//FORCE_PLAYER_WEAPON()
stageProgress = SP_LOADING
stageEnum = SE_PERFORMANCE// @SBA - adding performance stage OLD = SE_FIRSTCONTACT
ELSE
INT iCutTime
iCutTime = GET_CUTSCENE_TIME()
CDEBUG3LN(DEBUG_MISSION, "Cutscene Time = ", iCutTime)
IF (bShowDebugMissionTime)
SET_TEXT_SCALE(0.5, 0.5)
DISPLAY_TEXT_WITH_NUMBER(0.1, 0.1, "NUMBER", iCutTime)
ENDIF
IF HAVE_ASSET_REQUESTS_LOADED(assetRequester)
IF NOT bSkipAllowed
SET_CUTSCENE_CAN_BE_SKIPPED(TRUE)
bSkipAllowed = TRUE
ENDIF
// not sure this is really used - skipping seems built in
IF (iCutTime < 59000)
IF IS_CUTSCENE_SKIP_BUTTON_JUST_PRESSED_WITH_DELAY()
stageProgress = SP_CSKIPPED
CPRINTLN(DEBUG_MISSION, "Cutscene Skipped - Assets Loaded")
EXIT
ENDIF
ENDIF
ENDIF
IF (bTransitionStarted = FALSE)
IF (iCutTime >= CUTSCENE_TRANSITION_TIME)
CPRINTLN(DEBUG_MISSION, "Transition started!")
bTransitionStarted = TRUE
STRING FXname
FXname = FX_DrugsIn
IF WAS_CUTSCENE_SKIPPED()
CPRINTLN(DEBUG_MISSION, "Starting screen effect (cs skipped)")
FXname = FX_DrugsSkip
ENDIF
ANIMPOSTFX_PLAY(FXname, 0, TRUE)
TRIGGER_MUSIC_EVENT("RC18B_START")
ENDIF
ENDIF
// @SBA - adding first performace clown
IF (bPerformancePedsCreated = FALSE) AND (iCutTime >= CUTSCENE_CLOWN_TIME)
CREATE_INITIAL_PERFORMANCE_PEDS()
bPerformancePedsCreated = TRUE
ELIF bPerformancePedsCreated
HANDLE_INTRO_PERFORMANCE()
ENDIF
// is this happening too late in the cutscene?
IF CAN_SET_EXIT_STATE_FOR_CAMERA()
REPLAY_STOP_EVENT()
// @SBA - cut to performance cam
IF DOES_CAM_EXIST(ciPerformCamera1)
CPRINTLN(DEBUG_MISSION, "EXIT STATE FOR CAMERA SET: start cam")
SET_CAM_ACTIVE(ciPerformCamera1, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
SHAKE_CAM(ciPerformCamera1, "DRUNK_SHAKE")
ENDIF
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Trevor")
CPRINTLN(DEBUG_MISSION, "EXIT STATE FOR PLAYER SET")
ENDIF
ENDIF
BREAK
CASE SP_CSKIPPED
SET_CUTSCENE_FADE_VALUES(false, false, FALSE, false)
SAFE_FADE_SCREEN_OUT_TO_BLACK(250, TRUE)
IF IS_CUTSCENE_PLAYING()
WAIT_FOR_CUTSCENE_TO_STOP()
ENDIF
//RC_END_CUTSCENE_MODE(TRUE, FALSE)
// trigger music if not triggered
IF (bTransitionStarted = FALSE)
bTransitionStarted = TRUE
TRIGGER_MUSIC_EVENT("RC18B_START")
IF NOT ANIMPOSTFX_IS_RUNNING(FX_DrugsSkip)
ANIMPOSTFX_PLAY(FX_DrugsSkip, 0, TRUE)
ENDIF
ENDIF
// @SBA - don't want player to have control yet or give weapon(?)
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
//FORCE_PLAYER_WEAPON()
// @SBA - cut to performance cam
IF DOES_CAM_EXIST(ciPerformCamera1)
CPRINTLN(DEBUG_MISSION, "Cutscene skipped: start cam")
SET_CAM_ACTIVE(ciPerformCamera1, TRUE)
RENDER_SCRIPT_CAMS(TRUE, FALSE)
SHAKE_CAM(ciPerformCamera1, "DRUNK_SHAKE")
ENDIF
WAIT(500)
// update handler
IF bPerformancePedsCreated
HANDLE_INTRO_PERFORMANCE()
ENDIF
stageProgress = SP_LOADING
stageEnum = SE_PERFORMANCE// @SBA - adding performance stage OLD = SE_FIRSTCONTACT
BREAK
CASE SP_CLEANUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates The Pass Out Sequence
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_TEST(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
CASE SP_SETUP
SAFE_FADE_SCREEN_IN_FROM_BLACK(500, FALSE)
CPRINTLN(DEBUG_MISSION, "ENTERING UPDATE STAGE TEST")
CLEAR_PRINTS()
CLEAR_HELP()
// @SBA - adding spectators
DELETE_ALL_SPECTATOR_PEDS()
DELETE_ALL_CLOWN_PEDS()
DELETE_ALL_CLOWN_GENERATORS()
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
BREAK
CASE SP_CLEANUP
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// @SBA - adding this stage - Updates the opening Performance stage
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_PERFORMANCE(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
WHILE NOT HAVE_ASSET_REQUESTS_LOADED(assetRequester)
WAIT(0)
ENDWHILE
// @SBA - make performance peds if not made already
IF NOT bPerformancePedsCreated
CREATE_INITIAL_PERFORMANCE_PEDS()
bPerformancePedsCreated = TRUE
ENDIF
// update handler
HANDLE_INTRO_PERFORMANCE()
prog = SP_SETUP
iMaxActivePeds = 5
RC_SET_ENTITY_PROOFS_FOR_CUTSCENE(sRCLauncherDataLocal, FALSE)
RC_CleanupSceneEntities(sRCLauncherDataLocal, TRUE, TRUE, FALSE)
START_MISSION_DEBUG_TIMER()
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_MISSION_START, "Mission Start", FALSE)
BREAK
CASE SP_SETUP
CLEAR_PRINTS()
CPRINTLN(DEBUG_MISSION, "PERFORMANCE (you'll laugh 'til you die).")
INFORM_MISSION_STATS_OF_DAMAGE_WATCH_ENTITY(PLAYER_PED_ID())
IF NOT IS_AUDIO_SCENE_ACTIVE(sndAlienAmbientScene)
START_AUDIO_SCENE(sndAlienAmbientScene)
ENDIF
CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
SET_AMBIENT_ZONE_STATE(sAmbientZone, TRUE)
SETUP_TREVOR_DIALOG()
// update handler
HANDLE_INTRO_PERFORMANCE()
SAFE_FADE_SCREEN_IN_FROM_BLACK(500, FALSE)
//TRIGGER_MUSIC_EVENT("RC18B_START")
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
// Is performance done and are clowns dead?
IF HANDLE_INTRO_PERFORMANCE()
CPRINTLN(DEBUG_MISSION, "GOING TO PERFORMANCE CLEANUP")
prog = SP_CLEANUP
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_FIRSTCONTACT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates First Contact (wave of 3 clowns)
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_FIRSTCONTACT(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
//
prog = SP_SETUP
iMaxActivePeds = 5
BREAK
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "FIRST CONTACT")
bHasInitialOutburst = TRUE
CREATE_INITIAL_CLOWNS()
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
IF (iAliveClownCount = 0)
CPRINTLN(DEBUG_MISSION, "GOING TO FIRST CONTACT CLEANUP")
bLastClownAggressive = FALSE
prog = SP_CLEANUP
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_WAVE1
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates First Wave - 1 clown generator
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_WAVE_1(STAGE_PROGRESS &prog)
INT ind
SWITCH (prog)
CASE SP_LOADING
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "FIRST WAVE")
iMaxActivePeds = 5
IF GET_FREE_CLOWN_GENERATOR_INDEX(ind)
IF CREATE_CLOWN_GENERATOR(clownGenerator[ind], <<151.200, -962.300, 30.100>>, 213.200, 1, 0, 1250, 2500) //CREATE_CLOWN_GENERATOR(clownGenerator[ind], <<163.5672, -983.8129, 29.0923>>, 114.28)
prog = SP_RUNNING
ENDIF
ENDIF
BREAK
CASE SP_RUNNING
IF ARE_ALL_CLOWN_GENERATORS_DEAD()
// @SBA - have last clown come after player
MAKE_LAST_CLOWN_AGGRESSIVE(bLastClownAggressive)
IF (iAliveClownCount = 0)
bLastClownAggressive = FALSE
CPRINTLN(DEBUG_MISSION, "GOING TO FIRST WAVE CLEANUP")
prog = SP_CLEANUP
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_WAVE2
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates Wave 2 - three clowns
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_WAVE_2(STAGE_PROGRESS &prog)
INT ind
SWITCH (prog)
CASE SP_LOADING
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "2 WAVE")
iMaxActivePeds = 5
IF GET_FREE_CLOWN_PED_INDEX(ind)
CREATE_CLOWN_PED(clownPed[ind], <<202.1, -999.3, 30.6>>)
ENDIF
IF GET_FREE_CLOWN_PED_INDEX(ind)
CREATE_CLOWN_PED(clownPed[ind], <<200.6, -989.3, 30.6>>)
ENDIF
IF GET_FREE_CLOWN_PED_INDEX(ind)
CREATE_CLOWN_PED(clownPed[ind], <<192.3, -994.7, 30.6>>)
ENDIF
// @SBA - PERFORMANCE CLOWN SPAWN
CREATE_GENERAL_CLOWN_PERFORMANCE(SZ_ZONE_1)
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
IF ARE_ALL_CLOWN_GENERATORS_DEAD()
// @SBA - have last clown come after player
MAKE_LAST_CLOWN_AGGRESSIVE(bLastClownAggressive)
IF (iAliveClownCount = 0)
bLastClownAggressive = FALSE
CPRINTLN(DEBUG_MISSION, "GOING TO 2 WAVE CLEANUP")
prog = SP_CLEANUP
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_WAVE3
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates third wave
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_WAVE_3(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
iStageTimer = 0
iMaxActivePeds = 5
prog = SP_SETUP
BREAK
CASE SP_SETUP
IF (iStageTimer < STAGE_BREAK_TIME)
EXIT
ENDIF
CPRINTLN(DEBUG_MISSION, "3 WAVE")
bGenerateAutoClowns = TRUE
bUseClownSpawnPoint = TRUE
vClownSpawnPoint = <<188.085785,-952.725281,33.092264>>
fClownSpawnRadius = 16
iClownPedsSpawned = 0
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
IF (iClownPedsSpawned >= 3)
bGenerateAutoClowns = FALSE
ENDIF
IF ARE_ALL_CLOWN_GENERATORS_DEAD() AND (bGenerateAutoClowns = FALSE)
// @SBA - have last clown come after player
MAKE_LAST_CLOWN_AGGRESSIVE(bLastClownAggressive)
IF (iAliveClownCount = 0)
bLastClownAggressive = FALSE
CPRINTLN(DEBUG_MISSION, "GOING TO 3 WAVE CLEANUP")
prog = SP_CLEANUP
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_WAVE4
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates fourth wave
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_WAVE_4(STAGE_PROGRESS &prog)
INT ind
SWITCH (prog)
CASE SP_LOADING
iStageTimer = 0
bUseClownSpawnPoint = FALSE
bGenerateAutoClowns = FALSE
iMaxActivePeds = MAX_CLOWN_PEDS - 2
prog = SP_SETUP
BREAK
CASE SP_SETUP
IF (iStageTimer < STAGE_BREAK_TIME)
EXIT
ENDIF
CPRINTLN(DEBUG_MISSION, "4 WAVE")
bGenerateAutoClowns = FALSE
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_MID_STAGE, "Half Way", FALSE)
IF GET_FREE_CLOWN_GENERATOR_INDEX(ind)
CREATE_CLOWN_GENERATOR(clownGenerator[ind], <<173.700, -918.900, 32.200>>, 235.720, -1, 1250, 1150, 1750)
// @SBA - experimental - having van drive down the stairs
//CREATE_CLOWN_GENERATOR(clownGenerator[ind], <<196.6811, -929.6295, 32.200>>, 150.6685, -1, 1250, 1150, 1750)
ENDIF
IF GET_FREE_CLOWN_GENERATOR_INDEX(ind)
CREATE_CLOWN_GENERATOR(clownGenerator[ind], <<214.200, -947.300, 32.200>>, 53.640, -1, 8250, 850, 2000)
ENDIF
// @SBA - timer for fleeing peds
START_TIMER_NOW(tmrGeneral)
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
// @SBA - set up some runners after timer goes off and there are enough clowns
IF iAliveClownCount > 1
IF TIMER_DO_ONCE_WHEN_READY(tmrGeneral, GET_RANDOM_FLOAT_IN_RANGE(9.000, 12.000))
CREATE_GENERAL_CLOWN_PERFORMANCE(SZ_ZONE_2, 5, 5, FALSE)
ENDIF
ENDIF
IF ARE_ALL_CLOWN_GENERATORS_DEAD()
// @SBA - have last clown come after player
MAKE_LAST_CLOWN_AGGRESSIVE(bLastClownAggressive)
IF (iAliveClownCount = 0)
bLastClownAggressive = FALSE
CPRINTLN(DEBUG_MISSION, "GOING TO 4 WAVE CLEANUP")
prog = SP_CLEANUP
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_WAVE5
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates fifth wave
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_WAVE_5(STAGE_PROGRESS &prog)
INT ind
SWITCH (prog)
CASE SP_LOADING
iStageTimer = 0
iMaxActivePeds = MAX_CLOWN_PEDS
prog = SP_SETUP
BREAK
CASE SP_SETUP
IF (iStageTimer < STAGE_BREAK_TIME)
EXIT
ENDIF
CPRINTLN(DEBUG_MISSION, "5 WAVE")
bGenerateAutoClowns = TRUE
bUseClownSpawnPoint = TRUE
iClownPedsSpawned = 0
vClownSpawnPoint = <<210.035477,-902.093811,29.692423>>
fClownSpawnRadius = 20
IF GET_FREE_CLOWN_GENERATOR_INDEX(ind)
CREATE_CLOWN_GENERATOR(clownGenerator[ind], <<247.800, -880.300, 33.000>>, 129.460, 1, 6000, 600, 2000)
ENDIF
IF GET_FREE_CLOWN_GENERATOR_INDEX(ind)
CREATE_CLOWN_GENERATOR(clownGenerator[ind], <<218.400, -868.500, 33.000>>, 228.600, -1, 14000, 1100, 2000)
ENDIF
// @SBA - timer for fleeing peds
START_TIMER_NOW(tmrGeneral)
fGeneralTime = GET_RANDOM_FLOAT_IN_RANGE(5.000, 8.000)
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
// @SBA - set up some runners after timer goes off, if not on last clown
IF NOT bLastClownAggressive
IF TIMER_DO_ONCE_WHEN_READY(tmrGeneral, fGeneralTime)
CREATE_GENERAL_CLOWN_PERFORMANCE(SZ_ZONE_3, 5, 5, FALSE)
fGeneralTime = GET_RANDOM_FLOAT_IN_RANGE(20.000, 30.000)
START_TIMER_NOW(tmrGeneral)
ENDIF
ENDIF
IF (iClownPedsSpawned >= 5)
bGenerateAutoClowns = FALSE
ENDIF
IF ARE_ALL_CLOWN_GENERATORS_DEAD() AND (bGenerateAutoClowns = FALSE)
// @SBA - have last clown come after player
MAKE_LAST_CLOWN_AGGRESSIVE(bLastClownAggressive)
IF (iAliveClownCount = 0)
bLastClownAggressive = FALSE
CPRINTLN(DEBUG_MISSION, "GOING TO 5 WAVE CLEANUP")
prog = SP_CLEANUP
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_WAVE6
BREAK
ENDSWITCH
ENDPROC
PROC UPDATE_STAGE_WAVE_6(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
iStageTimer = 0
iMaxActivePeds = MAX_CLOWN_PEDS
RESET_ALL_CLOWN_DEATH_VECTORS()
prog = SP_SETUP
BREAK
CASE SP_SETUP
IF (iStageTimer < STAGE_BREAK_TIME)
EXIT
ENDIF
CPRINTLN(DEBUG_MISSION, "6 WAVE")
INT ind
iDuplicatesCount = 0
iClownPedsSpawned = 0
fClownSpawnRadius = 2.0
iNextSpawnTimer = 0
bUseClownSpawnPoint = TRUE
bGenerateAutoClowns = FALSE
// lower value for this stage
fNoSpawnPlayerDist = 2.0
CANCEL_TIMER(tmrGeneral)
// create 1st clown
IF GET_FREE_CLOWN_PED_INDEX(ind)
IF CREATE_CLOWN_PED(clownPed[ind], <<195.1091, -933.9568, 29.6918>>, 325.0, TRUE)
CPRINTLN(DEBUG_MISSION, "Created 1st Clown of 6th WAVE")
ENDIF
ENDIF
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
IF (iClownPedsSpawned >= 15)
bGenerateAutoClowns = FALSE
ELIF NOT bGenerateAutoClowns
CHECK_FOR_SPAWNING_DUPLICATES()
ENDIF
HANDLE_PLAY_TREVOR_CLOWN_DUPLICATION_RANT()
IF ARE_ALL_CLOWN_GENERATORS_DEAD() AND (bGenerateAutoClowns = FALSE) AND (iClownPedsSpawned >= 10) // @SBA - just need a largish number for this last condition
// @SBA - have last clown come after player
MAKE_LAST_CLOWN_AGGRESSIVE(bLastClownAggressive)
IF (iAliveClownCount = 0)
bLastClownAggressive = FALSE
CPRINTLN(DEBUG_MISSION, "GOING TO 6 WAVE CLEANUP")
prog = SP_CLEANUP
ENDIF
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_PASSOUT
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates The Pass Out Sequence
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_PASSOUT(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
CASE SP_SETUP
SAFE_FADE_SCREEN_IN_FROM_BLACK(500, FALSE)
CPRINTLN(DEBUG_MISSION, "ENTERING UPDATE STAGE PASSOUT")
CLEAR_PRINTS()
CLEAR_HELP()
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
IF PASS_OUT_SEQUENCE(TRUE)
prog = SP_CLEANUP
ENDIF
BREAK
CASE SP_CLEANUP
prog = SP_LOADING
stageEnum = SE_OUTRO
BREAK
ENDSWITCH
ENDPROC
//request the necessary dictionaries
FUNC BOOL REQUEST_DRUNK_ANIMS()
STRING m_movementClip = Get_Drunk_Level_Moveclip(DL_verydrunk)
REQUEST_CLIP_SET(m_movementClip)
IF NOT HAS_CLIP_SET_LOADED(m_movementClip)
RETURN FALSE
ELSE
RETURN TRUE
ENDIF
ENDFUNC
/// PURPOSE:
/// Updates Outro
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_OUTRO(STAGE_PROGRESS &prog)
IF CAN_REQUEST_ASSETS_FOR_CUTSCENE_ENTITY()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_CUTSCENE_PED_COMPONENT_VARIATION_FROM_PED("Trevor", PLAYER_PED_ID(), GET_ENTITY_MODEL(PLAYER_PED_ID()))
ENDIF
SET_CUTSCENE_PED_PROP_VARIATION(sSceneHandleBarry, ANCHOR_EYES, 0)
CPRINTLN(DEBUG_MISSION, "PED CUTSCENE VARIATIONS SET")
ENDIF
SWITCH (prog)
CASE SP_LOADING
CPRINTLN(DEBUG_MISSION, "REQUESTING CUTSCENE - bar_4_rcm")
RC_REQUEST_CUTSCENE("bar_4_rcm")
WAIT_FOR_WORLD_TO_LOAD(vMissionStart)
IF NOT HAS_SCRIPT_LOADED("postRC_Barry1and2")
REQUEST_SCRIPT("postRC_Barry1and2")
ENDIF
SET_REPLAY_MID_MISSION_STAGE_WITH_NAME(CP_OUTRO, "Outro", TRUE)
prog = SP_SETUP
BREAK
CASE SP_SETUP
IF NOT REQUEST_DRUNK_ANIMS()
CPRINTLN(DEBUG_MISSION, "Waiting on drunk anims...")
EXIT
ENDIF
CLEAR_AMBIENT_ZONE_STATE(sAmbientZone, TRUE)
IF RC_IS_CUTSCENE_OK_TO_START()
AND HAS_SCRIPT_LOADED("postRC_Barry1and2")
IF IS_ENTITY_OK(PLAYER_PED_ID())
RESET_PED_VISIBLE_DAMAGE(PLAYER_PED_ID())
CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
ENDIF
MISSION_CLEANUP()
bHasPlayerCameraExitState = FALSE
CLEAR_AREA_OF_VEHICLES(vMissionStart, 250.0)
CLEAR_AREA_OF_PEDS(vMissionStart, 50.0)
CLEAR_AREA_OF_OBJECTS(vMissionStart, 30.0)
REMOVE_DECALS_IN_RANGE(vMissionStart, 500.0)
REGISTER_ENTITY_FOR_CUTSCENE(NULL, sSceneHandleBarry, CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, GET_NPC_PED_MODEL(CHAR_BARRY))
REGISTER_ENTITY_FOR_CUTSCENE(NULL, sSceneHandleTable, CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, PROP_PROTEST_TABLE_01)
REGISTER_ENTITY_FOR_CUTSCENE(NULL, sSceneHandleChair, CU_CREATE_AND_ANIMATE_NEW_SCRIPT_ENTITY, PROP_CHAIR_08) //PROP_TABLE_03_CHR
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
REGISTER_ENTITY_FOR_CUTSCENE(PLAYER_PED_ID(), "Trevor", CU_ANIMATE_EXISTING_SCRIPT_ENTITY, PLAYER_TWO)
CPRINTLN(DEBUG_MISSION, "REGISTERED TREVOR")
ENDIF
REPLAY_START_EVENT(REPLAY_IMPORTANCE_LOW)
START_CUTSCENE()
WAIT(0)
//CLEANUP_SCREEN_FX()
//ANIMPOSTFX_PLAY(FX_DrugsIn, 0, FALSE)
SAFE_FADE_SCREEN_IN_FROM_BLACK(1000, FALSE)
//RESOLVE_MISSION_VEHICLES_FOR_CUTSCENE()
RC_START_CUTSCENE_MODE(<<0, 0, 0>>, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE)
SET_SRL_POST_CUTSCENE_CAMERA(<<183.4340, -949.1876, 30.8535>>, B2_CONVERT_ROT_TO_DIR_VECTOR(<<-3.0000, 0.0000, 72.9999>>))
//SET_CUTSCENE_CAN_BE_SKIPPED(FALSE)
prog = SP_RUNNING
ENDIF
BREAK
CASE SP_RUNNING
INT iCutTime
// Don't look back
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
ENDIF
IF NOT IS_CUTSCENE_PLAYING()
RC_END_CUTSCENE_MODE()
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), FALSE)
ENDIF
REPLAY_STOP_EVENT()
prog = SP_CLEANUP
ELSE
iCutTime = GET_CUTSCENE_TIME()
CDEBUG3LN(DEBUG_MISSION, "Cutscene Time = ", iCutTime)
IF iCutTime > 15000
IF MAKE_PED_DRUNK(PLAYER_PED_ID(), 10000)
CPRINTLN(DEBUG_MISSION, "TREVOR set to be drunk")
ENDIF
ENDIF
IF NOT bHasPlayerCameraExitState
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
ENDIF
IF CAN_SET_EXIT_STATE_FOR_REGISTERED_ENTITY("Trevor")
CPRINTLN(DEBUG_MISSION, "SET EXIT STATE FOR TREVOR")
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), <<180.1684, -948.6075, 29.0919>>)
SET_ENTITY_HEADING(PLAYER_PED_ID(), 73.0)
FORCE_PED_MOTION_STATE(PLAYER_PED_ID(), MS_ON_FOOT_RUN, FALSE, FAUS_CUTSCENE_EXIT)
SIMULATE_PLAYER_INPUT_GAIT(player_id(), PEDMOVE_RUN, 750)
bHasPlayerCameraExitState = TRUE
ENDIF
IF NOT IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_SIGN])
CREATE_STANDING_SIGN(sRCLauncherDataLocal.objID[OBJ_SIGN], mnProtestSign)
ENDIF
// register things as we exit
IF NOT IS_ENTITY_ALIVE(sRCLauncherDataLocal.pedID[0])
IF DOES_ENTITY_EXIST(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY(sSceneHandleBarry))
sRCLauncherDataLocal.pedID[0] = GET_PED_INDEX_FROM_ENTITY_INDEX(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY(sSceneHandleBarry))
SET_PED_PROP_INDEX(sRCLauncherDataLocal.pedID[0], ANCHOR_EYES, 0) //Glasses prop.
ENDIF
ENDIF
IF NOT IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_TABLE])
IF DOES_ENTITY_EXIST(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY(sSceneHandleTable))
sRCLauncherDataLocal.objID[OBJ_TABLE] = GET_OBJECT_INDEX_FROM_ENTITY_INDEX(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY(sSceneHandleTable))
ENDIF
ENDIF
IF NOT IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_CHAIR])
IF DOES_ENTITY_EXIST(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY(sSceneHandleChair))
sRCLauncherDataLocal.objID[OBJ_CHAIR] = GET_OBJECT_INDEX_FROM_ENTITY_INDEX(GET_ENTITY_INDEX_OF_REGISTERED_ENTITY(sSceneHandleChair))
ENDIF
ENDIF
IF CAN_SET_ENTER_STATE_FOR_REGISTERED_ENTITY(sSceneHandleTable)
IF IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_TABLE]) AND IS_ENTITY_ALIVE(sRCLauncherDataLocal.objID[OBJ_PAPERS])
ATTACH_ENTITY_TO_ENTITY(sRCLauncherDataLocal.objID[OBJ_PAPERS], sRCLauncherDataLocal.objID[OBJ_TABLE], 0, <<0, -0.25, 0>>, <<0, 0, 0>>)
CPRINTLN(DEBUG_MISSION, "PAPERS REATTACHED TO TABLE")
ENDIF
ENDIF
ENDIF
BREAK
CASE SP_CSKIPPED
SET_CUTSCENE_FADE_VALUES(false, false, FALSE, false)
SAFE_FADE_SCREEN_OUT_TO_BLACK(250, FALSE)
IF IS_CUTSCENE_PLAYING()
WAIT_FOR_CUTSCENE_TO_STOP()
ENDIF
RC_END_CUTSCENE_MODE()
SET_ENTITY_COORDS_GROUNDED(PLAYER_PED_ID(), vMissionStart)
SET_ENTITY_HEADING(PLAYER_PED_ID(), fMissionStart)
SET_GAMEPLAY_CAM_RELATIVE_PITCH()
SET_GAMEPLAY_CAM_RELATIVE_HEADING()
WAIT(250)
SAFE_FADE_SCREEN_IN_FROM_BLACK(250, FALSE)
SCRIPT_PASSED()
BREAK
CASE SP_CLEANUP
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
SET_PLAYER_CONTROL(PLAYER_ID(), TRUE)
ENDIF
DISABLE_CONTROL_ACTION(PLAYER_CONTROL, INPUT_LOOK_BEHIND)
SCRIPT_PASSED()
BREAK
ENDSWITCH
ENDPROC
/// PURPOSE:
/// Updates failed stage
/// PARAMS:
/// prog - stage progress enum, tells us what state we are in
PROC UPDATE_STAGE_FAILED(STAGE_PROGRESS &prog)
SWITCH (prog)
CASE SP_LOADING
CASE SP_SETUP
CPRINTLN(DEBUG_MISSION, "Mission Failed")
CLEAR_PRINTS()
CLEAR_HELP()
// @SBA - adding spectators
CLEANUP_ALL_SPECTATOR_PEDS()
// Remove all blips here
// Make all clowns flee
FLEE_ALL_CLOWN_PEDS()
CLEANUP_ALL_CLOWN_PEDS(TRUE)
// stop mission music
CPRINTLN(DEBUG_MISSION, "FAIL STRING = ", sFailString)
PREPARE_MUSIC_EVENT("RC18B_END")
// B*938802 - No more delay fades
IF IS_STRING_NULL_OR_EMPTY(sFailString)
Random_Character_Failed()
ELSE
Random_Character_Failed_With_Reason(sFailString, TRUE) ///, bDelayFade)
ENDIF
prog = SP_RUNNING
BREAK
CASE SP_RUNNING
IF GET_MISSION_FLOW_SAFE_TO_CLEANUP()
// @SBA - this is preventing the music from ending if you debug fail - is the death check needed?
//IF IS_ENTITY_DEAD(PLAYER_PED_ID())
TRIGGER_MUSIC_EVENT("RC18B_END")
//ENDIF
// Set warp locations
MISSION_FLOW_SET_FAIL_WARP_LOCATION(<<165.4821, -990.5140, 29.0923>>, 166.7554)
SET_REPLAY_DECLINED_VEHICLE_WARP_LOCATION(vPlayerCarRespot, fPlayerCarRespot)
// @SBA - adding spectators
CLEANUP_ALL_SPECTATOR_PEDS()
// delete everything here!
//DeleteEverything()?
CLEANUP_ALL_CLOWN_PEDS(TRUE)
// script_cleanup should terminate the thread
RC_END_CUTSCENE_MODE(TRUE, FALSE)
Script_Cleanup()
ELSE
// not finished fading out
// you may want to handle dialogue etc here.
IF ARE_STRINGS_EQUAL(sFailString, "B2_FAIL2") // Fled the battle
IF PASS_OUT_SEQUENCE() AND IS_REPEAT_PLAY_ACTIVE()
CPRINTLN(DEBUG_MISSION, "Repeat Play - Emergency Exit")
Script_Cleanup()
ENDIF
ENDIF
ENDIF
BREAK
ENDSWITCH
ENDPROC
//----------------------
// DEBUG FUNCTIONS
//----------------------
#IF IS_DEBUG_BUILD
/// PURPOSE:
/// Operates S, F, J and Z keys
PROC UPDATE_DEBUG_KEYS()
UPDATE_MISSION_DEBUG_TIMER()
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_S)
IF IS_CUTSCENE_PLAYING()
WAIT_FOR_CUTSCENE_TO_STOP(TRUE, FALSE)
ENDIF
WHILE NOT HAS_SCRIPT_LOADED("postRC_Barry1and2")
REQUEST_SCRIPT("postRC_Barry1and2")
WAIT(0)
ENDWHILE
IF IS_GAMEPLAY_HINT_ACTIVE()
STOP_GAMEPLAY_HINT()
ENDIF
CLEANUP_SCREEN_FX()
TRIGGER_MUSIC_EVENT("RC18B_END")
// @SBA - adding spectators
DELETE_ALL_SPECTATOR_PEDS()
CLEANUP_ALL_SPECTATOR_PEDS()
DELETE_ALL_CLOWN_PEDS()
DELETE_ALL_CLOWN_GENERATORS()
FLEE_ALL_CLOWN_PEDS()
CLEANUP_ALL_CLOWN_PEDS()
SCRIPT_PASSED()
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_F)
IF IS_CUTSCENE_PLAYING()
WAIT_FOR_CUTSCENE_TO_STOP(TRUE, FALSE)
ENDIF
SET_MISSION_FAILED("")
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_P)
IF IS_CUTSCENE_PLAYING()
WAIT_FOR_CUTSCENE_TO_STOP(TRUE, FALSE)
ENDIF
IF (stageEnum = SE_INTRO) OR (stageEnum = SE_PERFORMANCE) OR (stageEnum = SE_FIRSTCONTACT)
DO_Z_SKIP(Z_SKIP_TO_INTRO)
ELSE
DO_Z_SKIP(ENUM_TO_INT(stageEnum) - 1)
ENDIF
ENDIF
IF IS_KEYBOARD_KEY_JUST_PRESSED(KEY_J)
IF IS_CUTSCENE_PLAYING()
WAIT_FOR_CUTSCENE_TO_STOP(TRUE, FALSE)
ENDIF
IF (stageEnum = SE_INTRO)
// @SBA - Performance is now first
//DO_Z_SKIP(Z_SKIP_TO_FIRST_CONTACT)
DO_Z_SKIP(Z_SKIP_TO_PERFORMANCE)
ELIF (stageEnum = SE_OUTRO)
CLEANUP_SCREEN_FX()
TRIGGER_MUSIC_EVENT("RC18B_END")
SCRIPT_PASSED()
ELSE
DO_Z_SKIP(ENUM_TO_INT(stageEnum) + 1)
ENDIF
ENDIF
IF LAUNCH_MISSION_STAGE_MENU(sSkipMenu, iDbgStageJump)
DO_Z_SKIP(iDbgStageJump)
ENDIF
ENDPROC
/// PURPOSE:
/// Updates Debug Widgets and draw debug stuff
PROC UPDATE_DEBUG_WIDGETS()
INT ind
VECTOR v
IF (bDebugTTYSpew)
DRAW_DEBUG_CIRCLE(vBattleCenter, fBattleRadius)
DRAW_DEBUG_CIRCLE(vBattleCenter, fClownSpawnRadius)
DEBUG_DRAW_ANGLED_AREA_EX(battleAreaInner, 0, 255, 0)
DEBUG_DRAW_ANGLED_AREA_EX(battleArea, 255, 255, 255)
DEBUG_DRAW_ANGLED_AREA_EX(battleAreaOuter, 255, 0, 0)
DRAW_DEBUG_CIRCLE(vTestGenPoint, 1.0)
DRAW_DEBUG_SPHERE(vTestGenPoint, 0.125)
v = GET_OFFSET_FROM_COORD_AND_HEADING_IN_WORLD_COORDS(vTestGenPoint, fTestHeading, <<0, 5, 0>>)
DRAW_DEBUG_LINE(vTestGenPoint, v)
ENDIF
IF (bGenerateTestGenerator)
DELETE_ALL_CLOWN_PEDS()
DELETE_ALL_CLOWN_GENERATORS()
IF CREATE_CLOWN_GENERATOR(clownGenerator[0], vTestGenPoint, fTestHeading, iTestSwerve, 0, iTestFwdTime, iTestBrakeTime)
bGenerateTestGenerator = FALSE
ENDIF
ENDIF
IF (bGenerateTestClown)
IF (iAliveClownCount >= iMaxActivePeds)
EXIT
ENDIF
IF (GET_GAME_TIMER() < iNextSpawnTimer)
EXIT
ENDIF
IF NOT GET_FREE_CLOWN_PED_INDEX(ind)
EXIT
ENDIF
v = GET_RANDOM_POINT_IN_DISC(vBattleCenter, fClownSpawnRadius, 6.0)
IF NOT CHECK_SPAWN_POINT_IS_OK(v)
EXIT
ENDIF
IF CREATE_CLOWN_PED(clownPed[ind], v)
iNextSpawnTimer = GET_GAME_TIMER() + GET_RANDOM_INT_IN_RANGE(iMinPedSpawnTime, iMaxPedSpawnTime)
ENDIF
ENDIF
ENDPROC
#ENDIF
/// PURPOSE:
/// Check to see if player has left battle area if so handle failure
PROC UPDATE_PLAYER_AREA_CHECK()
/*
IF (bIsPlayerInBattleArea)
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), battleAreaOuter.vPosition[0], battleAreaOuter.vPosition[1], battleAreaOuter.fWidth)
PRINT_NOW("B2_WARN", DEFAULT_GOD_TEXT_TIME, 1) // Return to the ~y~battleground.~s~
SAFE_REMOVE_BLIP(locationBlip)
locationBlip = CREATE_COORD_BLIP(vBattleCenter)
iMissionAbandonedTimer = GET_GAME_TIMER() + FAIL_WARNING_TIME
bIsPlayerInBattleArea = FALSE
ENDIF
ELSE
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), battleAreaInner.vPosition[0], battleAreaInner.vPosition[1], battleAreaInner.fWidth)
IF (GET_GAME_TIMER() > iMissionAbandonedTimer)
SET_MISSION_FAILED("B2_FAIL2") // You fled the battle.
ENDIF
ELSE
PRINT_NOW("B2_PRIME", DEFAULT_GOD_TEXT_TIME, 1) // Kill the ~r~clowns.~s~
SAFE_REMOVE_BLIP(locationBlip)
bIsPlayerInBattleArea = TRUE
ENDIF
ENDIF
*/
IF (bIsPlayerInBattleArea)
IF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), battleArea.vPosition[0], battleArea.vPosition[1], battleArea.fWidth)
PRINT_NOW("B2_WARN", DEFAULT_GOD_TEXT_TIME, 1) // Return to the ~y~battleground.~s~
SAFE_REMOVE_BLIP(locationBlip)
locationBlip = CREATE_COORD_BLIP(vBattleCenter)
iMissionAbandonedTimer = GET_GAME_TIMER() + FAIL_WARNING_TIME
bIsPlayerInBattleArea = FALSE
ENDIF
ELSE
IF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), battleAreaInner.vPosition[0], battleAreaInner.vPosition[1], battleAreaInner.fWidth)
PRINT_NOW("B2_PRIME", DEFAULT_GOD_TEXT_TIME, 1) // Kill the ~r~clowns.~s~
SAFE_REMOVE_BLIP(locationBlip)
bIsPlayerInBattleArea = TRUE
ELIF NOT IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), battleAreaOuter.vPosition[0], battleAreaOuter.vPosition[1], battleAreaOuter.fWidth)
IF (GET_GAME_TIMER() > iMissionAbandonedTimer)
ENDIF
SET_MISSION_FAILED("B2_FAIL2") // You fled the battle.
ENDIF
ENDIF
ENDPROC
//----------------------
// MAIN SCRIPT
//----------------------
SCRIPT(g_structRCScriptArgs sRCLauncherDataIn)
VECTOR amin, amax
sRCLauncherDataLocal = sRCLauncherDataIn
RC_TakeEntityOwnership(sRCLauncherDataLocal)
SET_MISSION_FLAG(TRUE)
sFailString = ""
// clean up any live projectiles near Barry
CLEAR_AREA_OF_PROJECTILES((<<190.2424, -956.3790, 28.63>>), 6.0)
// Setup callback when player is killed, arrested or goes to multiplayer
IF (HAS_FORCE_CLEANUP_OCCURRED(DEFAULT_FORCE_CLEANUP_FLAGS|FORCE_CLEANUP_FLAG_DEBUG_MENU))
PRINT_LAUNCHER_DEBUG("Force cleanup [TERMINATING]")
TRIGGER_MUSIC_EVENT("RC18B_END")
Random_Character_Failed()
SCRIPT_CLEANUP()
ENDIF
// setup areas
MISSION_SETUP()
SET_DEBUG_LINES_AND_SPHERES_DRAWING_ACTIVE(TRUE)
CALCULATE_MIN_MAX_FROM_POSITION_AND_RADIUS(vBattleCenter, 200.0, amin, amax)
DUMMY_REFERENCE_INT(iClownGeneratorsDestroyed)
DUMMY_REFERENCE_INT(iAliveClownGeneratorCount)
DUMMY_REFERENCE_INT(iClownPedsKilled)
IF IS_REPEAT_PLAY_ACTIVE()
if not is_screen_faded_in()
if not is_screen_fading_in()
do_screen_fade_in(default_fade_time)
endif
endif
ENDIF
// main loop
WHILE (TRUE)
REPLAY_CHECK_FOR_EVENT_THIS_FRAME("SF_GRT")
UPDATE_MISSION_NAME_DISPLAYING(sRCLauncherDataLocal.sIntroCutscene)
// globals
iAlphaCounter = 0 // this regulates alpha
iSpecAlphaCounter = 0
iStageTimer += GET_FRAME_TIME()
// stop nonsense
NO_AMBIENT_MALARKY_THIS_FRAME()
SET_PED_NON_CREATION_AREA(amin, amax)
SET_PLAYER_MAY_NOT_ENTER_ANY_VEHICLE(GET_PLAYER_INDEX())
// update spectators
DISABLE_CELLPHONE_THIS_FRAME_ONLY()
UPDATE_SPECTATOR_PEDS()
// update enemies
UPDATE_CLOWN_PEDS()
UPDATE_CLOWN_GENERATORS()
UPDATE_CLOWN_SPAWNER()
// main switch
SWITCH (stageEnum)
CASE SE_LEAD_IN
UPDATE_STAGE_LEADIN(stageProgress)
BREAK
CASE SE_INTRO
UPDATE_STAGE_INTRO(stageProgress)
BREAK
CASE SE_TEST
UPDATE_STAGE_TEST(stageProgress)
BREAK
CASE SE_PERFORMANCE
UPDATE_STAGE_PERFORMANCE(stageProgress)
BREAK
CASE SE_FIRSTCONTACT
UPDATE_STAGE_FIRSTCONTACT(stageProgress)
BREAK
CASE SE_WAVE1
UPDATE_STAGE_WAVE_1(stageProgress)
BREAK
CASE SE_WAVE2
UPDATE_STAGE_WAVE_2(stageProgress)
BREAK
CASE SE_WAVE3
UPDATE_STAGE_WAVE_3(stageProgress)
BREAK
CASE SE_WAVE4
UPDATE_STAGE_WAVE_4(stageProgress)
BREAK
CASE SE_WAVE5
UPDATE_STAGE_WAVE_5(stageProgress)
BREAK
CASE SE_WAVE6
UPDATE_STAGE_WAVE_6(stageProgress)
BREAK
CASE SE_PASSOUT
UPDATE_STAGE_PASSOUT(stageProgress)
BREAK
CASE SE_OUTRO
UPDATE_STAGE_OUTRO(stageProgress)
BREAK
CASE SE_FAILED
UPDATE_STAGE_FAILED(stageProgress)
BREAK
ENDSWITCH
// handle things which are updated in combat
IF IS_MISSION_IN_COMBAT_STAGE()
// drugs effect and other thing
IF IS_AUDIO_SCENE_ACTIVE(sndAlienAmbientScene)
SET_AUDIO_SCENE_VARIABLE(sndAlienAmbientScene, "DrugsEffect", (SIN(((TO_FLOAT(GET_GAME_TIMER())/1000)*45)%360))*0.25+0.25)
ENDIF
UPDATE_PLAYER_AREA_CHECK()
PLAY_TREVOR_FREAK_DIALOG_LINES()
ENDIF
WAIT(0)
// debug
#IF IS_DEBUG_BUILD
IF (stageEnum <> SE_FAILED)
UPDATE_DEBUG_KEYS()
ENDIF
IF (bUpdateWidgets)
UPDATE_DEBUG_WIDGETS()
ENDIF
#ENDIF
ENDWHILE
// Script should never reach here. Always terminate with cleanup function.
ENDSCRIPT