3330 lines
160 KiB
Scheme
Executable File
3330 lines
160 KiB
Scheme
Executable File
USING "rage_builtins.sch"
|
|
USING "globals.sch"
|
|
USING "vehicle_public.sch"
|
|
USING "commands_clock.sch"
|
|
USING "player_ped_public.sch"
|
|
USING "selector_public.sch"
|
|
USING "battlebuddy_private.sch"
|
|
USING "vehicle_gen_public.sch"
|
|
USING "comms_control_private.sch"
|
|
USING "commands_water.sch"
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
USING "debug_channels_structs.sch"
|
|
#ENDIF
|
|
|
|
#IF USE_CLF_DLC
|
|
USING "spy_vehicle_system.sch"
|
|
#ENDIF
|
|
|
|
|
|
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
//
|
|
// SCRIPT NAME : snapshot_private.sch
|
|
// AUTHOR : Andrew Minghella
|
|
// DESCRIPTION : Handles gameplay state snapshots used in replay controller and repeat play
|
|
//
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
// *****************************************************************************************
|
|
|
|
// ===========================================================================================================
|
|
// Metrics tracking functions
|
|
// ===========================================================================================================
|
|
#IF IS_DEBUG_BUILD
|
|
|
|
/// PURPOSE:
|
|
/// Starts new metrics / smoketest stage
|
|
/// PARAMS:
|
|
/// iStage - the replay checkpoint stage (this is only used to check if we're doing a new mission)
|
|
/// eMissionID - the mission that is starting the metrics stage
|
|
/// sStageName - the debug name for this stage
|
|
PROC StartNewMetricsStage(INT iStage, STRING sScriptName, STRING sStageName)
|
|
|
|
// check if this is a stroy or RC mission
|
|
SP_MISSIONS eMissionID = GET_SP_MISSION_ID_FOR_SCRIPT_NAME(sScriptName, TRUE)
|
|
|
|
// increment the metrics tracking stage (used for metrics and smoketests)
|
|
// also let the autoplay system know which mission is running
|
|
IF iStage = 0
|
|
g_iMetricsTrackingStage = 0
|
|
TEXT_LABEL_31 tMissionName
|
|
IF eMissionID = SP_MISSION_NONE
|
|
// RC mission
|
|
tMissionName = "M_"
|
|
tMissionName += sScriptName
|
|
ELSE
|
|
tMissionName = GET_SP_MISSION_NAME_LABEL(eMissionID)
|
|
ENDIF
|
|
g_txtFlowAutoplayRunningMission = tMissionName
|
|
CPRINTLN(DEBUG_AUTOPLAY, "New autoplay mission, name: ", g_txtFlowAutoplayRunningMission)
|
|
ELSE
|
|
g_iMetricsTrackingStage++
|
|
ENDIF
|
|
|
|
// --------------metrics---------------------
|
|
IF g_bFlowMetricZonesEnabled
|
|
IF iStage = 0
|
|
// start new metrics zone
|
|
METRICS_ZONES_HIDE()
|
|
METRICS_ZONES_CLEAR()
|
|
g_bFlowMetricZoneInProgress = TRUE
|
|
CPRINTLN(DEBUG_METRICS, "Mission started. Resetting metrics zone system.")
|
|
ELSE
|
|
// stage
|
|
METRICS_ZONE_STOP()
|
|
CPRINTLN(DEBUG_METRICS, "Stopped running metrics zone.")
|
|
ENDIF
|
|
|
|
IF g_bFlowMetricZoneInProgress
|
|
TEXT_LABEL_63 tMetricsZoneName = "["
|
|
IF eMissionID = SP_MISSION_NONE
|
|
// RC mission
|
|
tMetricsZoneName += sScriptName
|
|
ELSE
|
|
tMetricsZoneName += g_sMissionStaticData[eMissionID].statID
|
|
ENDIF
|
|
tMetricsZoneName += ":"
|
|
tMetricsZoneName += g_iMetricsTrackingStage
|
|
tMetricsZoneName += "] "
|
|
tMetricsZoneName += sStageName
|
|
METRICS_ZONE_START(tMetricsZoneName)
|
|
CPRINTLN(DEBUG_METRICS, "Started new metrics zone ", tMetricsZoneName,".")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// --------------smoketests-------------------------------------------
|
|
IF g_bFlowSmoketestEnabled
|
|
IF g_bFlowSmoketestSectionActive
|
|
//End current smoketest section.
|
|
CPRINTLN(DEBUG_AUTOPLAY, "Mission checkpoint. Ending tracking for smoketest section.")
|
|
SMOKETEST_STOP_CAPTURE_SECTION()
|
|
g_bFlowSmoketestSectionActive = FALSE
|
|
ENDIF
|
|
|
|
//Start new smoketest section.
|
|
TEXT_LABEL_63 tSmoketestSection = "["
|
|
IF eMissionID <> SP_MISSION_NONE
|
|
tSmoketestSection += g_sMissionStaticData[eMissionID].statID
|
|
ENDIF
|
|
tSmoketestSection += ":"
|
|
tSmoketestSection += g_iMetricsTrackingStage
|
|
tSmoketestSection += "] "
|
|
tSmoketestSection += sStageName
|
|
SMOKETEST_START_CAPTURE_SECTION(tSmoketestSection)
|
|
CPRINTLN(DEBUG_AUTOPLAY, "Started new smoketest section ", tSmoketestSection,".")
|
|
g_bFlowSmoketestSectionActive = TRUE
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
PROC Stop_Metrics_For_Mission_Over(STRING sScriptName)
|
|
IF g_bFlowMetricZonesEnabled
|
|
IF g_bFlowMetricZoneInProgress
|
|
|
|
// check if this is a story or RC mission
|
|
SP_MISSIONS eMissionID = GET_SP_MISSION_ID_FOR_SCRIPT_NAME(sScriptName, TRUE)
|
|
|
|
//Stop tracking current metrics zone.
|
|
CPRINTLN(DEBUG_METRICS, "Mission over. Ending metrics zone tracking for mission.")
|
|
METRICS_ZONE_STOP()
|
|
g_bFlowMetricZoneInProgress = FALSE
|
|
|
|
//Write metrics for this mission to file.
|
|
TEXT_LABEL_63 tMetricsFileName = "METRICS_"
|
|
|
|
IF eMissionID = SP_MISSION_NONE
|
|
// rc mission
|
|
tMetricsFileName += sScriptName
|
|
ELSE
|
|
// story mission
|
|
tMetricsFileName += g_sMissionStaticData[eMissionID].statID
|
|
ENDIF
|
|
|
|
tMetricsFileName += "_"
|
|
tMetricsFileName += g_iMetricsIteration
|
|
tMetricsFileName += ".xml"
|
|
METRICS_ZONE_SAVE_TO_FILE(tMetricsFileName)
|
|
CPRINTLN(DEBUG_METRICS, "Metrics data written to file \"", tMetricsFileName, "\".")
|
|
|
|
//Display metrics data to screen for a time.
|
|
METRICS_ZONES_SHOW()
|
|
g_bDisplayingMetricsZoneResults = TRUE
|
|
g_iTimeDisplayedMetricsReport = GET_GAME_TIMER()
|
|
CPRINTLN(DEBUG_METRICS, "Started displaying in-game metrics report.")
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF g_bFlowSmoketestEnabled
|
|
IF g_bFlowSmoketestSectionActive
|
|
//End current smoketest section.
|
|
CPRINTLN(DEBUG_AUTOPLAY, "Mission over. Ending tracking for current smoketest section.")
|
|
SMOKETEST_STOP_CAPTURE_SECTION()
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
// other debug functions
|
|
|
|
/// PURPOSE:
|
|
/// Prints the model dimensions of the vehicle passed in
|
|
/// PARAMS:
|
|
/// mVehicle - the vehicle we are printing info for
|
|
PROC PRINT_MODEL_DIMENSIONS(VEHICLE_INDEX mVehicle)
|
|
// print model dimension info
|
|
VECTOR vMin, vMax
|
|
GET_MODEL_DIMENSIONS(GET_ENTITY_MODEL(mVehicle), vMin, vMax)
|
|
//CPRINTLN(DEBUG_REPLAY, "model dimensions are: vMin =", vMin, "vMax= ", vMax)
|
|
CPRINTLN(DEBUG_REPLAY, "x =", vMax.x - vMin.x)
|
|
CPRINTLN(DEBUG_REPLAY, "y =", vMax.y - vMin.y)
|
|
CPRINTLN(DEBUG_REPLAY, "z =", vMax.z - vMin.z)
|
|
ENDPROC
|
|
|
|
#ENDIF
|
|
|
|
// ===========================================================================================================
|
|
// SNAPSHOT HELPER FUNCTIONS
|
|
// ===========================================================================================================
|
|
|
|
/// PURPOSE:
|
|
/// check if vPosToCheck is inside the specified interior
|
|
/// uses IS_COLLISION_MARKED_OUTSIDE & GET_INTERIOR_AT_COORDS_WITH_TYPE
|
|
/// PARAMS:
|
|
/// vPosToCheck - the position to test
|
|
/// sInteriorName - the name of the specific interior you want to test for
|
|
/// vInteriorCoords - a position from inside the specific interior
|
|
/// RETURNS:
|
|
/// TRUE if vPosToCheck is inside the specific interior
|
|
FUNC BOOL IS_POSITION_INSIDE_SPECIFC_INTERIOR(VECTOR vPosToCheck, STRING sInteriorName, VECTOR vInteriorCoords)
|
|
|
|
IF NOT IS_COLLISION_MARKED_OUTSIDE(vPosToCheck)
|
|
|
|
INTERIOR_INSTANCE_INDEX interiorIndexToCheck = GET_INTERIOR_AT_COORDS_WITH_TYPE(vInteriorCoords, sInteriorName)
|
|
|
|
// make sure the handle to the specific interior to check is valid first
|
|
IF NOT IS_VALID_INTERIOR(interiorIndexToCheck)
|
|
//CPRINTLN(DEBUG_REPLAY, " IS_POSITION_INSIDE_SPECIFC_INTERIOR() : return FALSE unable to test interiorIndexToCheck ins't valid interior ")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
INTERIOR_INSTANCE_INDEX interiorIndexAtPosition = GET_INTERIOR_FROM_COLLISION(vPosToCheck)
|
|
IF interiorIndexAtPosition = interiorIndexToCheck
|
|
//CPRINTLN(DEBUG_REPLAY, "IS_POSITION_INSIDE_SPECIFC_INTERIOR() : return TRUE - for vPosToCheck : ", vPosToCheck)
|
|
RETURN TRUE
|
|
ELSE
|
|
//CPRINTLN(DEBUG_REPLAY, "IS_POSITION_INSIDE_SPECIFC_INTERIOR() : [pos inside interior but not the specific interior! return FALSE - for vPosToCheck : ", vPosToCheck)
|
|
ENDIF
|
|
ELSE
|
|
//CPRINTLN(DEBUG_REPLAY, "IS_POSITION_INSIDE_SPECIFC_INTERIOR() - collision marked outside return FALSE - for vPosToCheck : ", vPosToCheck)
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
// ===========================================================================================================
|
|
// CLEAN UP FUNCTIONS
|
|
// ===========================================================================================================
|
|
|
|
/// PURPOSE:
|
|
/// Resets the data in a player snapshot struct
|
|
/// PARAMS:
|
|
/// mSnapshot - the player snapshot struct
|
|
PROC Reset_Player_Snapshot(PLAYER_SNAPSHOT &mSnapshot)
|
|
mSnapshot.vPos = <<0,0,0>>
|
|
mSnapshot.fHeading = 0.0
|
|
mSnapshot.iWantedLevel = 0
|
|
mSnapshot.eParachuteState = PPS_INVALID
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets the data in a vehicle snapshot struct
|
|
/// PARAMS:
|
|
/// mSnapshot - the vehicle snapshot struct
|
|
PROC Reset_Vehicle_Snapshot(VEHICLE_SNAPSHOT &mSnapshot)
|
|
RESET_VEHICLE_SETUP_STRUCT(mSnapshot.mVehicle)
|
|
mSnapshot.vVehiclePos = <<0.0,0.0,0.0>>
|
|
mSnapshot.vVehicleVelocity = <<0.0,0.0,0.0>>
|
|
mSnapshot.fVehicleHeading = 0.0
|
|
mSnapshot.bInVehicle = FALSE
|
|
mSnapshot.bTrackedForImpound = FALSE
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets the data in a vehicle snapshot struct
|
|
/// PARAMS:
|
|
/// mSnapshot - the vehicle snapshot struct
|
|
PROC Reset_BattleBuddy_Snapshot(structBattleBuddySnapshot &mSnapshot)
|
|
mSnapshot.eMission = SP_MISSION_NONE
|
|
mSnapshot.iAllowedChars = 0
|
|
mSnapshot.iReplayChars = 0
|
|
mSnapshot.iFailedChars = 0
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Resets the player and vehicle snapshots in the repeat play snapshot
|
|
PROC Reset_RepeatPlay_SnapshotCLF()
|
|
Reset_Player_Snapshot(g_savedGlobalsClifford.sRepeatPlayData.mPlayerStruct)
|
|
Reset_Vehicle_Snapshot(g_savedGlobalsClifford.sRepeatPlayData.mVehicleStruct)
|
|
g_savedGlobalsClifford.sRepeatPlayData.eMission = SP_MISSION_NONE
|
|
g_savedGlobalsClifford.sRepeatPlayData.eRCMissionToBlock = NO_RC_MISSION
|
|
ENDPROC
|
|
|
|
PROC Reset_RepeatPlay_SnapshotNRM()
|
|
Reset_Player_Snapshot(g_savedGlobalsnorman.sRepeatPlayData.mPlayerStruct)
|
|
Reset_Vehicle_Snapshot(g_savedGlobalsnorman.sRepeatPlayData.mVehicleStruct)
|
|
g_savedGlobalsnorman.sRepeatPlayData.eMission = SP_MISSION_NONE
|
|
g_savedGlobalsnorman.sRepeatPlayData.eRCMissionToBlock = NO_RC_MISSION
|
|
ENDPROC
|
|
|
|
PROC Reset_RepeatPlay_Snapshot()
|
|
#if USE_CLF_DLC
|
|
Reset_RepeatPlay_SnapshotCLF()
|
|
exit
|
|
#endif
|
|
#if USE_NRM_DLC
|
|
Reset_RepeatPlay_SnapshotNRM()
|
|
exit
|
|
#endif
|
|
Reset_Player_Snapshot(g_savedGlobals.sRepeatPlayData.mPlayerStruct)
|
|
Reset_Vehicle_Snapshot(g_savedGlobals.sRepeatPlayData.mVehicleStruct)
|
|
g_savedGlobals.sRepeatPlayData.eMission = SP_MISSION_NONE
|
|
g_savedGlobals.sRepeatPlayData.eRCMissionToBlock = NO_RC_MISSION
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Clear out the data in a snapshot struct.
|
|
/// NOTE: If this gets updated you'll need to update CopyStartSnapshotToStageSnapshot (below)
|
|
/// PARAMS:
|
|
/// paramSnapshot - the start or checkpoint snapshot
|
|
PROC Reset_Snapshot(SNAPSHOT_STRUCT &mSnapshot)
|
|
|
|
INT iTempIndex
|
|
INT iCharIndex
|
|
|
|
// character, position and time of day etc
|
|
mSnapshot.eCharacter = NO_CHARACTER
|
|
Clear_TimeOfDay(mSnapshot.tTime)
|
|
mSnapshot.iPreviousWeather = -1
|
|
mSnapshot.iNextWeather = -1
|
|
mSnapshot.fWeatherInterp = 0
|
|
mSnapshot.mCurrentWeapon = WEAPONTYPE_INVALID
|
|
mSnapshot.bRestrictedVehicle = FALSE
|
|
mSnapshot.mVehicleIndex = NULL
|
|
mSnapshot.eVehicleOwner = NO_CHARACTER
|
|
|
|
// all player characters
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
// bank accounts
|
|
mSnapshot.iBankLogIndex[iCharIndex] = -1
|
|
mSnapshot.iCash[iCharIndex] = 0
|
|
|
|
// armour
|
|
mSnapshot.iArmour[iCharIndex] = 0
|
|
|
|
// fail weapons
|
|
mSnapshot.mFailWeapon[iCharIndex] = WEAPONTYPE_INVALID
|
|
|
|
// Player's default vehicles
|
|
RESET_PED_VEH_DATA_STRUCT(mSnapshot.mPlayerVehicle[0][iCharIndex])
|
|
RESET_PED_VEH_DATA_STRUCT(mSnapshot.mPlayerVehicle[1][iCharIndex])
|
|
|
|
// ped varaitions
|
|
REPEAT NUM_PED_COMPONENTS iTempIndex
|
|
mSnapshot.mVariations[iCharIndex].iTextureVariation[iTempIndex] = -1
|
|
mSnapshot.mVariations[iCharIndex].iDrawableVariation[iTempIndex] = -1
|
|
mSnapshot.mVariations[iCharIndex].iPaletteVariation[iTempIndex] = -1
|
|
ENDREPEAT
|
|
|
|
// Hair / beard / mask stuff
|
|
mSnapshot.mVariations[iCharIndex].eStoredHairstyle = INT_TO_ENUM(PED_COMP_NAME_ENUM, 0) // all SP chars use hair 0 as default
|
|
mSnapshot.mVariations[iCharIndex].eItemThatForcedHairChange = DUMMY_PED_COMP
|
|
mSnapshot.mVariations[iCharIndex].eTypeThatForcedHairChange = COMP_TYPE_HAIR
|
|
mSnapshot.mVariations[iCharIndex].eStoredBeard = INT_TO_ENUM(PED_COMP_NAME_ENUM, 0) // all SP chars use beard 0 as default
|
|
mSnapshot.mVariations[iCharIndex].eItemThatForcedBeardChange = DUMMY_PED_COMP
|
|
mSnapshot.mVariations[iCharIndex].eTypeThatForcedBeardChange = COMP_TYPE_BERD
|
|
|
|
REPEAT NUM_PLAYER_PED_PROPS iTempIndex
|
|
mSnapshot.mVariations[iCharIndex].iPropIndex[iTempIndex] = -1
|
|
mSnapshot.mVariations[iCharIndex].iPropTexture[iTempIndex] = -1
|
|
ENDREPEAT
|
|
|
|
// weapons
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
mSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iAmmoCount = 0
|
|
mSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iModsAsBitfield = 0
|
|
mSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iTint = 0
|
|
mSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iCamo = 0
|
|
mSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].eWeaponType = WEAPONTYPE_INVALID
|
|
ENDREPEAT
|
|
REPEAT NUMBER_OF_DLC_WEAPONS iTempIndex
|
|
mSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].iAmmoCount = 0
|
|
mSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].iModsAsBitfield = 0
|
|
mSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].iTint = 0
|
|
mSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].iCamo = 0
|
|
mSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].eWeaponType = WEAPONTYPE_INVALID
|
|
ENDREPEAT
|
|
|
|
//Purchased weapon states.
|
|
REPEAT 4 iTempIndex
|
|
mSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[iTempIndex] = 0
|
|
ENDREPEAT
|
|
REPEAT 10 iTempIndex
|
|
mSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[iTempIndex] = 0
|
|
ENDREPEAT
|
|
REPEAT 15 iTempIndex
|
|
mSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[iTempIndex] = 0
|
|
ENDREPEAT
|
|
|
|
// special ability
|
|
mSnapshot.iSpecialAbility[iCharIndex] = 0
|
|
|
|
// tattoos
|
|
FOR iTempIndex = 0 TO MAX_NUMBER_OF_TATTOO_BITSETS -1
|
|
mSnapshot.sTattoos[iCharIndex].iUnlockedTattoos[iTempIndex] = 0
|
|
mSnapshot.sTattoos[iCharIndex].iViewedTattoos[iTempIndex] = 0
|
|
mSnapshot.sTattoos[iCharIndex].iCurrentTattoos[iTempIndex] = 0
|
|
ENDFOR
|
|
|
|
// clothes
|
|
FOR iTempIndex = 0 TO PED_COMPONENT_USED_SLOT
|
|
mSnapshot.sComponents[iCharIndex].iHeadBitset0[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iBeardBitset0[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iHairBitset0[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset1[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset2[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset3[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset4[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset5[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset6[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset7[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset8[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iTorsoBitset9[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iLegsBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iLegsBitset1[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iLegsBitset2[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iLegsBitset3[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iHandBitset0[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iFeetBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iFeetBitset1[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iFeetBitset2[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iFeetBitset3[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iFeetBitset4[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iTeethBitset0[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iSpecialBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iSpecialBitset1[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iSpecialBitset2[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iSpecial2Bitset0[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iDeclBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iDeclBitset1[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iJbibBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iJbibBitset1[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iOutfitBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iOutfitBitset1[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iPropGroupBitset0[iTempIndex] = 0
|
|
|
|
mSnapshot.sComponents[iCharIndex].iPropsBitset0[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iPropsBitset1[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iPropsBitset2[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iPropsBitset3[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iPropsBitset4[iTempIndex] = 0
|
|
mSnapshot.sComponents[iCharIndex].iPropsBitset5[iTempIndex] = 0
|
|
ENDFOR
|
|
ENDREPEAT
|
|
|
|
// other structs
|
|
Reset_Player_Snapshot(mSnapshot.mPlayerStruct)
|
|
Reset_Vehicle_Snapshot(mSnapshot.mVehicleStruct)
|
|
Reset_BattleBuddy_Snapshot(mSnapshot.mBattleBuddyStruct)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Copies the star snapshot over the stage snapshot
|
|
/// NOTE: If this gets updated you'll need to update Reset_Snapshot (above)
|
|
PROC CopyStartSnapshotToStageSnapshot()
|
|
|
|
// --------------------Copy this start snapshot to the stage snapshot-----------------------
|
|
INT iTempIndex
|
|
INT iCharIndex
|
|
|
|
// character, position and time of day etc
|
|
g_stageSnapshot.eCharacter = g_startSnapshot.eCharacter
|
|
g_stageSnapshot.tTime = g_startSnapshot.tTime
|
|
g_stageSnapshot.iPreviousWeather = g_startSnapshot.iPreviousWeather
|
|
g_stageSnapshot.iNextWeather = g_startSnapshot.iNextWeather
|
|
g_stageSnapshot.fWeatherInterp = g_startSnapshot.fWeatherInterp
|
|
g_stageSnapshot.mCurrentWeapon = g_startSnapshot.mCurrentWeapon
|
|
g_stageSnapshot.bRestrictedVehicle = g_startSnapshot.bRestrictedVehicle
|
|
g_stageSnapshot.mVehicleIndex = g_startSnapshot.mVehicleIndex
|
|
g_stageSnapshot.eVehicleOwner = g_startSnapshot.eVehicleOwner
|
|
|
|
// all player characters
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
|
|
// bank accounts
|
|
g_stageSnapshot.iBankLogIndex[iCharIndex] = g_startSnapshot.iBankLogIndex[iCharIndex]
|
|
g_stageSnapshot.iCash[iCharIndex] = g_startSnapshot.iCash[iCharIndex]
|
|
|
|
//Armor.
|
|
g_stageSnapshot.iArmour[iCharIndex] = g_startSnapshot.iArmour[iCharIndex]
|
|
|
|
// Fail Weapons
|
|
g_stageSnapshot.mFailWeapon[iCharIndex] = g_startSnapshot.mFailWeapon[iCharIndex]
|
|
|
|
// Player's default vehicles
|
|
g_stageSnapshot.mPlayerVehicle[0][iCharIndex] = g_startSnapshot.mPlayerVehicle[0][iCharIndex]
|
|
g_stageSnapshot.mPlayerVehicle[1][iCharIndex] = g_startSnapshot.mPlayerVehicle[1][iCharIndex]
|
|
|
|
//Ped variations.
|
|
REPEAT NUM_PED_COMPONENTS iTempIndex
|
|
g_stageSnapshot.mVariations[iCharIndex].iTextureVariation[iTempIndex] = g_startSnapshot.mVariations[iCharIndex].iTextureVariation[iTempIndex]
|
|
g_stageSnapshot.mVariations[iCharIndex].iDrawableVariation[iTempIndex] = g_startSnapshot.mVariations[iCharIndex].iDrawableVariation[iTempIndex]
|
|
g_stageSnapshot.mVariations[iCharIndex].iPaletteVariation[iTempIndex] = g_startSnapshot.mVariations[iCharIndex].iPaletteVariation[iTempIndex]
|
|
ENDREPEAT
|
|
|
|
// hair / beard / mask stuff
|
|
g_stageSnapshot.mVariations[iCharIndex].eStoredHairstyle = g_startSnapshot.mVariations[iCharIndex].eStoredHairstyle
|
|
g_stageSnapshot.mVariations[iCharIndex].eItemThatForcedHairChange = g_startSnapshot.mVariations[iCharIndex].eItemThatForcedHairChange
|
|
g_stageSnapshot.mVariations[iCharIndex].eTypeThatForcedHairChange = g_startSnapshot.mVariations[iCharIndex].eTypeThatForcedHairChange
|
|
g_stageSnapshot.mVariations[iCharIndex].eStoredBeard = g_startSnapshot.mVariations[iCharIndex].eStoredBeard
|
|
g_stageSnapshot.mVariations[iCharIndex].eItemThatForcedBeardChange = g_startSnapshot.mVariations[iCharIndex].eItemThatForcedBeardChange
|
|
g_stageSnapshot.mVariations[iCharIndex].eTypeThatForcedBeardChange = g_startSnapshot.mVariations[iCharIndex].eTypeThatForcedBeardChange
|
|
|
|
REPEAT NUM_PLAYER_PED_PROPS iTempIndex
|
|
g_stageSnapshot.mVariations[iCharIndex].iPropIndex[iTempIndex] = g_startSnapshot.mVariations[iCharIndex].iPropIndex[iTempIndex]
|
|
g_stageSnapshot.mVariations[iCharIndex].iPropTexture[iTempIndex] = g_startSnapshot.mVariations[iCharIndex].iPropTexture[iTempIndex]
|
|
ENDREPEAT
|
|
|
|
//Weapons.
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
g_stageSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex] = g_startSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex]
|
|
ENDREPEAT
|
|
REPEAT NUMBER_OF_DLC_WEAPONS iTempIndex
|
|
g_stageSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex] = g_startSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex]
|
|
ENDREPEAT
|
|
|
|
//Purchased weapon states.
|
|
REPEAT 4 iTempIndex
|
|
g_stageSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[iTempIndex] = g_startSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[iTempIndex]
|
|
ENDREPEAT
|
|
REPEAT 10 iTempIndex
|
|
g_stageSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[iTempIndex] = g_startSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[iTempIndex]
|
|
ENDREPEAT
|
|
REPEAT 15 iTempIndex
|
|
g_stageSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[iTempIndex] = g_startSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[iTempIndex]
|
|
ENDREPEAT
|
|
|
|
// special ability
|
|
g_stageSnapshot.iSpecialAbility[iCharIndex] = g_startSnapshot.iSpecialAbility[iCharIndex]
|
|
|
|
// tattoos
|
|
FOR iTempIndex = 0 TO MAX_NUMBER_OF_TATTOO_BITSETS -1
|
|
g_stageSnapshot.sTattoos[iCharIndex].iUnlockedTattoos[iTempIndex] = g_startSnapshot.sTattoos[iCharIndex].iUnlockedTattoos[iTempIndex]
|
|
g_stageSnapshot.sTattoos[iCharIndex].iViewedTattoos[iTempIndex] = g_startSnapshot.sTattoos[iCharIndex].iViewedTattoos[iTempIndex]
|
|
g_stageSnapshot.sTattoos[iCharIndex].iCurrentTattoos[iTempIndex] = g_startSnapshot.sTattoos[iCharIndex].iCurrentTattoos[iTempIndex]
|
|
ENDFOR
|
|
|
|
// clothes
|
|
FOR iTempIndex = 0 TO PED_COMPONENT_USED_SLOT
|
|
g_stageSnapshot.sComponents[iCharIndex].iHeadBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iHeadBitset0[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iBeardBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iBeardBitset0[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iHairBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iHairBitset0[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset1[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset2[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset2[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset3[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset3[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset4[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset4[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset5[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset5[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset6[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset6[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset7[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset7[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset8[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset8[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iTorsoBitset9[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTorsoBitset9[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iLegsBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iLegsBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iLegsBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iLegsBitset1[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iLegsBitset2[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iLegsBitset2[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iLegsBitset3[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iLegsBitset3[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iHandBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iHandBitset0[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iFeetBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iFeetBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iFeetBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iFeetBitset1[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iFeetBitset2[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iFeetBitset2[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iFeetBitset3[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iFeetBitset3[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iFeetBitset4[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iFeetBitset4[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iTeethBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iTeethBitset0[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iSpecialBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iSpecialBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iSpecialBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iSpecialBitset1[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iSpecialBitset2[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iSpecialBitset2[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iSpecial2Bitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iSpecial2Bitset0[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iDeclBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iDeclBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iDeclBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iDeclBitset1[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iJbibBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iJbibBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iJbibBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iJbibBitset1[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iOutfitBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iOutfitBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iOutfitBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iOutfitBitset1[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iPropGroupBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iPropGroupBitset0[iTempIndex]
|
|
|
|
g_stageSnapshot.sComponents[iCharIndex].iPropsBitset0[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iPropsBitset0[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iPropsBitset1[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iPropsBitset1[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iPropsBitset2[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iPropsBitset2[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iPropsBitset3[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iPropsBitset3[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iPropsBitset4[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iPropsBitset4[iTempIndex]
|
|
g_stageSnapshot.sComponents[iCharIndex].iPropsBitset5[iTempIndex] = g_startSnapshot.sComponents[iCharIndex].iPropsBitset5[iTempIndex]
|
|
ENDFOR
|
|
ENDREPEAT
|
|
|
|
// other structs
|
|
g_stageSnapshot.mPlayerStruct.vPos = g_startSnapshot.mPlayerStruct.vPos
|
|
g_stageSnapshot.mPlayerStruct.fHeading = g_startSnapshot.mPlayerStruct.fHeading
|
|
|
|
g_stageSnapshot.mVehicleStruct.vVehiclePos = g_startSnapshot.mVehicleStruct.vVehiclePos
|
|
g_stageSnapshot.mVehicleStruct.vVehicleVelocity = g_startSnapshot.mVehicleStruct.vVehicleVelocity
|
|
g_stageSnapshot.mVehicleStruct.fVehicleHeading = g_startSnapshot.mVehicleStruct.fVehicleHeading
|
|
g_stageSnapshot.mVehicleStruct.bInVehicle = g_stageSnapshot.mVehicleStruct.bInVehicle
|
|
g_stageSnapshot.mVehicleStruct.bPersonalVehicle = g_startSnapshot.mVehicleStruct.bPersonalVehicle
|
|
g_stageSnapshot.mVehicleStruct.bTrackedForImpound = g_startSnapshot.mVehicleStruct.bTrackedForImpound
|
|
g_stageSnapshot.mVehicleStruct.ePlayerCharacter = g_startSnapshot.mVehicleStruct.ePlayerCharacter
|
|
g_stageSnapshot.mVehicleStruct.bVehGen = g_startSnapshot.mVehicleStruct.bVehGen
|
|
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iPlateIndex = g_startSnapshot.mVehicleStruct.mVehicle.iPlateIndex
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.tlPlateText = g_startSnapshot.mVehicleStruct.mVehicle.tlPlateText
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iColour1 = g_startSnapshot.mVehicleStruct.mVehicle.iColour1
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iColour2 = g_startSnapshot.mVehicleStruct.mVehicle.iColour2
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iColourExtra1 = g_startSnapshot.mVehicleStruct.mVehicle.iColourExtra1
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iColourExtra2 = g_startSnapshot.mVehicleStruct.mVehicle.iColourExtra2
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iModIndex = g_startSnapshot.mVehicleStruct.mVehicle.iModIndex
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iModVariation = g_startSnapshot.mVehicleStruct.mVehicle.iModVariation
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iTyreR = g_startSnapshot.mVehicleStruct.mVehicle.iTyreR
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iTyreG = g_startSnapshot.mVehicleStruct.mVehicle.iTyreG
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iTyreB = g_startSnapshot.mVehicleStruct.mVehicle.iTyreB
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iWindowTintColour = g_startSnapshot.mVehicleStruct.mVehicle.iWindowTintColour
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iFlags = g_startSnapshot.mVehicleStruct.mVehicle.iFlags
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.eModel = g_startSnapshot.mVehicleStruct.mVehicle.eModel
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iLivery = g_startSnapshot.mVehicleStruct.mVehicle.iLivery
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.eRoofState = g_startSnapshot.mVehicleStruct.mVehicle.eRoofState
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iWheelType = g_startSnapshot.mVehicleStruct.mVehicle.iWheelType
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iCustomR = g_startSnapshot.mVehicleStruct.mVehicle.iCustomR
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iCustomG = g_startSnapshot.mVehicleStruct.mVehicle.iCustomG
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iCustomB = g_startSnapshot.mVehicleStruct.mVehicle.iCustomB
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iNeonR = g_startSnapshot.mVehicleStruct.mVehicle.iNeonR
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iNeonG = g_startSnapshot.mVehicleStruct.mVehicle.iNeonG
|
|
g_stageSnapshot.mVehicleStruct.mVehicle.iNeonB = g_startSnapshot.mVehicleStruct.mVehicle.iNeonB
|
|
|
|
|
|
g_stageSnapshot.mBattleBuddyStruct.eMission = g_startSnapshot.mBattleBuddyStruct.eMission
|
|
g_stageSnapshot.mBattleBuddyStruct.iAllowedChars = g_startSnapshot.mBattleBuddyStruct.iAllowedChars
|
|
g_stageSnapshot.mBattleBuddyStruct.iReplayChars = g_startSnapshot.mBattleBuddyStruct.iReplayChars
|
|
g_stageSnapshot.mBattleBuddyStruct.iFailedChars = g_startSnapshot.mBattleBuddyStruct.iFailedChars
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Clears out snapshot data being held for the start of the mission.
|
|
PROC Reset_Start_Snapshot()
|
|
CPRINTLN(DEBUG_REPLAY, "Resetting mission start snapshot data.")
|
|
g_snapshotScriptName = ""
|
|
Reset_Snapshot(g_startSnapshot)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Clears out snapshot data being held for the last mission stage.
|
|
PROC Reset_Stage_Snapshot()
|
|
CPRINTLN(DEBUG_REPLAY, "Resetting last stage snapshot data.")
|
|
Reset_Snapshot(g_stageSnapshot)
|
|
ENDPROC
|
|
|
|
// ===========================================================================================================
|
|
// SNAPSHOT VEHICLE RESTORING FUNCTIONS
|
|
// ===========================================================================================================
|
|
|
|
/// PURPOSE:
|
|
/// Returns whether the specified snapshot has a start vehicle saved in it.
|
|
/// PARAMS:
|
|
/// mSnapshot - the start or checkpoint snapshot
|
|
/// RETURNS:
|
|
/// True if the snapshot has a vehicle saved in it
|
|
FUNC BOOL IsSnapshotVehicleAvailable(VEHICLE_SNAPSHOT &mSnapshot)
|
|
IF mSnapshot.mVehicle.eModel = DUMMY_MODEL_FOR_SCRIPT
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
IF NOT IS_VEHICLE_AVAILABLE_FOR_GAME(mSnapshot.mVehicle.eModel)
|
|
CPRINTLN(DEBUG_REPLAY, "IsSnapshotVehicleAvailable vehicle model ",GET_MODEL_NAME_FOR_DEBUG(mSnapshot.mVehicle.eModel)," not available for game.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
//Stunt plane check - B* 2552130
|
|
IF mSnapshot.mVehicle.eModel = STUNT AND ARE_VECTORS_ALMOST_EQUAL(mSnapshot.vVehiclePos, <<1694.62, 3276.27, 41.31>>)
|
|
CPRINTLN(DEBUG_REPLAY, "IsSnapshotVehicleAvailable Stunt Trials plane not available for game - should be handled by the minigame.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Start loading the model for a snapshot vehicle.
|
|
/// PARAMS:
|
|
/// mSnapshot - the start or checkpoint snapshot
|
|
PROC RequestSnapshotVehicleModel(VEHICLE_SNAPSHOT &mSnapshot)
|
|
IF IsSnapshotVehicleAvailable(mSnapshot)
|
|
REQUEST_MODEL(mSnapshot.mVehicle.eModel)
|
|
ELSE
|
|
SCRIPT_ASSERT("RequestSnapshotVehicleModel: Tried to request a stored vehicle model for a snapshot that had no vehicle saved. Check IsSnapshotVehicleAvailable() before requesting.")
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Check if a the model for a snapshot vehicle is loaded.
|
|
/// PARAMS:
|
|
/// mSnapshot - the start or checkpoint snapshot
|
|
/// RETURNS:
|
|
/// True if the model has loaded.
|
|
FUNC BOOL HasSnapshotVehicleLoaded(VEHICLE_SNAPSHOT &mSnapshot)
|
|
IF IsSnapshotVehicleAvailable(mSnapshot)
|
|
IF HAS_MODEL_LOADED(mSnapshot.mVehicle.eModel)
|
|
RETURN TRUE
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ELSE
|
|
SCRIPT_ASSERT("HasSnapshotVehicleLoaded: Tried to check if a vehicle model had loaded for a snapshot that had no vehicle saved. Check IsSnapshotVehicleAvailable() before querying.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the stored snapshot vehicle is a specific model.
|
|
/// PARAMS:
|
|
/// mSnapshot - the start or checkpoint snapshot
|
|
/// paramVehicleModel - the model name we are checking against
|
|
/// RETURNS:
|
|
/// TRUE if the stored snapshot vehicle is the model specified
|
|
FUNC BOOL IsSnapshotVehicleThisModel(VEHICLE_SNAPSHOT &mSnapshot, MODEL_NAMES paramVehicleModel)
|
|
IF IsSnapshotVehicleAvailable(mSnapshot)
|
|
IF mSnapshot.mVehicle.eModel = paramVehicleModel
|
|
RETURN TRUE
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
SCRIPT_ASSERT("IsSnapshotVehicleThisModel: Tried to query a stored vehicle model for a snapshot that had no vehicle saved. Check IsSnapshotVehicleAvailable() before querying.")
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if the special case vehicle index matches the vehgen
|
|
/// PARAMS:
|
|
/// mVehicle - the vehicle we are checking
|
|
/// vehGen - the VEHGEN we are checking against
|
|
/// RETURNS:
|
|
/// BOOL If vehicle matches vehgen
|
|
FUNC BOOL DOES_SPECIAL_CASE_VEHICLE_MATCH(VEHICLE_INDEX snapshotVehicle,VEHICLE_INDEX compareVehicle, BOOL checkColour = TRUE)
|
|
IF DOES_ENTITY_EXIST(compareVehicle) AND NOT IS_ENTITY_DEAD(compareVehicle) AND IS_VEHICLE_DRIVEABLE(compareVehicle)
|
|
IF checkColour
|
|
INT c1,c2,c3,c4
|
|
GET_VEHICLE_COLOURS(snapshotVehicle,c1,c2)
|
|
GET_VEHICLE_COLOURS(compareVehicle,c3,c4)
|
|
IF c1 = c3 AND c2 = c4
|
|
RETURN TRUE
|
|
ENDIF
|
|
ELSE
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if the vehicle index is a special case, hardcoded list designed to stop duplicates
|
|
/// Method was first created for bug 1912018
|
|
/// PARAMS:
|
|
/// mVehicle - the vehicle we are checking
|
|
/// RETURNS:
|
|
/// BOOL If vehicle matches special case
|
|
FUNC BOOL IS_VEHICLE_SNAPSHOT_SPECIAL_CASE(VEHICLE_INDEX mVehicle, VECTOR vVelocity, BOOL bInVehicle)
|
|
|
|
MODEL_NAMES tempModel = GET_ENTITY_MODEL(mVehicle)
|
|
VEHICLE_INDEX tempVehArray[3]
|
|
INT i,x
|
|
|
|
SWITCH tempModel
|
|
CASE CARGOBOB
|
|
//B* 1912018
|
|
IF DOES_SPECIAL_CASE_VEHICLE_MATCH(mVehicle, g_sVehicleGenNSData.vehicleID[VEHGEN_DOCKSP2B_CHINOOK],FALSE)
|
|
//duplicate CARGOBOB, remove vehicle gen
|
|
DELETE_VEHICLE_GEN_VEHICLE(VEHGEN_DOCKSP2B_CHINOOK)
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: specialCase, removing vehgen = VEHGEN_DOCKSP2B_CHINOOK")
|
|
RETURN TRUE
|
|
ENDIF
|
|
BREAK
|
|
CASE FIRETRUK
|
|
//B* 1932490
|
|
IF DOES_SPECIAL_CASE_VEHICLE_MATCH(mVehicle, g_sVehicleGenNSData.vehicleID[VEHGEN_AGENCY_PREP_FIRETRUCK])
|
|
//duplicate FIRETRUK, remove vehicle gen
|
|
DELETE_VEHICLE_GEN_VEHICLE(VEHGEN_AGENCY_PREP_FIRETRUCK)
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: specialCase, removing vehgen = VEHGEN_AGENCY_PREP_FIRETRUCK")
|
|
RETURN TRUE
|
|
ENDIF
|
|
BREAK
|
|
CASE CUBAN800
|
|
//B* 2009073
|
|
i = GET_PED_NEARBY_VEHICLES(PLAYER_PED_ID(),tempVehArray)
|
|
FOR x = 0 TO i-1
|
|
IF DOES_SPECIAL_CASE_VEHICLE_MATCH(mVehicle, tempVehArray[x])
|
|
AND ARE_VECTORS_ALMOST_EQUAL(GET_ENTITY_COORDS(tempVehArray[x]),<<2136.1331, 4780.5635, 39.9702>>,5.0)
|
|
IF NOT bInVehicle OR ARE_VECTORS_EQUAL(vVelocity,<<0,0,0>>) OR GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(mVehicle),GET_ENTITY_COORDS(tempVehArray[x])) < 10
|
|
DELETE_VEHICLE(mVehicle)
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: specialCase, trafficking air cuban800. Removing snapshot vehicle") //replay change
|
|
RETURN TRUE
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDFOR
|
|
BREAK
|
|
CASE LUXOR2
|
|
//B*-2334160
|
|
IF DOES_ENTITY_EXIST(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HANGAR_TREVOR])
|
|
AND IS_VEHICLE_DRIVEABLE(mVehicle) AND IS_VEHICLE_DRIVEABLE(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HANGAR_TREVOR])
|
|
IF GET_ENTITY_MODEL(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HANGAR_TREVOR]) = LUXOR2
|
|
AND GET_VEHICLE_LIVERY(mVehicle) = GET_VEHICLE_LIVERY(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HANGAR_TREVOR])
|
|
DELETE_VEHICLE_GEN_VEHICLE(VEHGEN_WEB_HANGAR_TREVOR)
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: specialCase LUXOR2, removing vehgen = VEHGEN_WEB_HANGAR_TREVOR")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
CASE SWIFT2
|
|
//B*-2346022
|
|
IF DOES_ENTITY_EXIST(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HELIPAD_TREVOR_COUNTRY])
|
|
AND IS_VEHICLE_DRIVEABLE(mVehicle) AND IS_VEHICLE_DRIVEABLE(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HELIPAD_TREVOR_COUNTRY])
|
|
IF GET_ENTITY_MODEL(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HELIPAD_TREVOR_COUNTRY]) = SWIFT2
|
|
AND GET_VEHICLE_LIVERY(mVehicle) = GET_VEHICLE_LIVERY(g_sVehicleGenNSData.vehicleSelectID[VEHGEN_WEB_HELIPAD_TREVOR_COUNTRY])
|
|
DELETE_VEHICLE_GEN_VEHICLE(VEHGEN_WEB_HELIPAD_TREVOR_COUNTRY)
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: specialCase SWIFT2, removing vehgen = VEHGEN_WEB_HELIPAD_TREVOR_COUNTRY")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
BREAK
|
|
ENDSWITCH
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if the vehicle index matches one stored in the dynamic vehgen vehicles array
|
|
/// PARAMS:
|
|
/// mVehicle - the vehicle we are checking
|
|
/// RETURNS:
|
|
/// VEHICLE_GEN_NAME_ENUM if the vehicle matches a vehgen and the vehgen vehicle exists, VEHGEN_NONE otherwise
|
|
FUNC VEHICLE_GEN_NAME_ENUM DOES_VEHICLE_MATCH_A_VEHGEN_VEHICLE(VEHICLE_INDEX mVehicle)
|
|
INT iVehGen
|
|
INT c1,c2,c3,c4
|
|
REPEAT NUMBER_OF_VEHICLES_TO_GEN iVehGen
|
|
IF DOES_ENTITY_EXIST(g_sVehicleGenNSData.vehicleSelectID[iVehGen])
|
|
AND (NOT IS_ENTITY_DEAD(g_sVehicleGenNSData.vehicleSelectID[iVehGen]))
|
|
AND IS_VEHICLE_DRIVEABLE(g_sVehicleGenNSData.vehicleSelectID[iVehGen])
|
|
GET_VEHICLE_COLOURS(mVehicle,c1,c2)
|
|
GET_VEHICLE_COLOURS(g_sVehicleGenNSData.vehicleSelectID[iVehGen],c3,c4)
|
|
IF GET_ENTITY_MODEL(mVehicle) = GET_ENTITY_MODEL(g_sVehicleGenNSData.vehicleSelectID[iVehGen])
|
|
AND GET_VEHICLE_LIVERY(mVehicle) = GET_VEHICLE_LIVERY(g_sVehicleGenNSData.vehicleSelectID[iVehGen])
|
|
AND c1 = c2 AND c3 = c4
|
|
RETURN INT_TO_ENUM(VEHICLE_GEN_NAME_ENUM, iVehGen)
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN VEHGEN_NONE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if the vehicle index equals one stored in the dynamic vehgen vehicles array
|
|
/// PARAMS:
|
|
/// mVehicle - the vehicle we are checking
|
|
/// RETURNS:
|
|
/// TRUE if the vehicle index equals a vehgen and the vehgen vehicle exists, FALSE otherwise
|
|
FUNC BOOL IS_VEHICLE_A_VEHGEN_VEHICLE(VEHICLE_INDEX mVehicle)
|
|
INT iVehGen
|
|
REPEAT NUMBER_OF_VEHICLES_TO_GEN iVehGen
|
|
IF DOES_ENTITY_EXIST(g_sVehicleGenNSData.vehicleSelectID[iVehGen])
|
|
IF mVehicle = g_sVehicleGenNSData.vehicleSelectID[iVehGen]
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Creates the vehicle saved for the specified snapshot.
|
|
/// PARAMS:
|
|
/// mSnapshot - - the start or checkpoint snapshot
|
|
/// vPos - where to create the snapshot vehicle (if <<0.0,0.0,0.0>> it is created at the co-ords from the snapshot)
|
|
/// fHeading - the snapshot vehicle's heading
|
|
/// RETURNS:
|
|
/// The vehicle index of the snapshot vehicle
|
|
FUNC VEHICLE_INDEX CreateSnapshotVehicle(VEHICLE_SNAPSHOT &mSnapshot, VECTOR vPos, FLOAT fHeading = 0.0, BOOL bDeleteSamePlayerVehicles = FALSE)
|
|
VEHICLE_INDEX vehSnapshot
|
|
VECTOR vTemp
|
|
|
|
IF IsSnapshotVehicleAvailable(mSnapshot)
|
|
IF ARE_VECTORS_EQUAL(vPos, <<0.0,0.0,0.0>>) // If no vector specified, use the vector in the snapshot
|
|
vPos = mSnapshot.vVehiclePos
|
|
fHeading = mSnapshot.fVehicleHeading
|
|
ENDIF
|
|
|
|
//B* 1902545: Monster vehicle check
|
|
IF (mSnapshot.mVehicle.eModel = MONSTER OR mSnapshot.mVehicle.eModel = MARSHALL)
|
|
IF IS_POINT_IN_ANGLED_AREA(vPos, <<-816.871643,185.623840,71.402748>>, <<-807.489441,189.376205,75.273232>>, 6.500000)
|
|
//Move monster truck to in front of M's house
|
|
vPos = <<-850.93,158.82,65.7>>
|
|
fHeading = 89.5
|
|
CPRINTLN(debug_replay,"Monster truck vehicle saved inside Michael's garage but unable to be created there, positioning at ",vPos)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
IF HasSnapshotVehicleLoaded(mSnapshot)
|
|
|
|
CLEAR_AREA(vPos, 5.0, TRUE) // Clear area so we can create the car
|
|
DELETE_VEHICLE_GEN_VEHICLES_IN_AREA(vPos, 5.0)
|
|
|
|
|
|
#IF USE_CLF_DLC
|
|
if mSnapshot.mVehicle.eModel = spy_vehicle_get_spy_vehicle_model()
|
|
|
|
spy_vehicle_system_struct spy_vehicle_system
|
|
|
|
spy_vehicle_remove_all_system_assets(spy_vehicle_system) //stops 2 instances of the spy vehicle being in the world and cleans up all the assets
|
|
|
|
spy_vehicle_create_spy_vehicle(spy_vehicle_system, vPos, fHeading)
|
|
|
|
vehSnapshot = spy_vehicle_get_vehicle_index()
|
|
|
|
#if is_debug_build
|
|
printstring("spy_vehicle - created via snapshot_private.sch")
|
|
printnl()
|
|
#endif
|
|
|
|
else
|
|
|
|
vehSnapshot = CREATE_VEHICLE(mSnapshot.mVehicle.eModel, vPos, fHeading)
|
|
|
|
endif
|
|
#endif
|
|
|
|
#IF not USE_CLF_DLC
|
|
|
|
vehSnapshot = CREATE_VEHICLE(mSnapshot.mVehicle.eModel, vPos, fHeading)
|
|
|
|
#endif
|
|
|
|
IF DOES_ENTITY_EXIST(vehSnapshot)
|
|
//B* - 2297443, set coords without offset. Bug, loading vehicle under Floyds apartment.
|
|
vTemp = GET_ENTITY_COORDS(vehSnapshot)
|
|
IF VDIST2(vTemp, <<-1151.15,-1530.32,7.48925>>) <= 3.0
|
|
SET_ENTITY_COORDS_NO_OFFSET(vehSnapshot, vPos)
|
|
ENDIF
|
|
|
|
SET_VEHICLE_SETUP(vehSnapshot, mSnapshot.mVehicle)
|
|
//B* 2059523: If it's a boat, only place on ground if it's not on land
|
|
BOOL bSetOnGround = TRUE
|
|
IF IS_THIS_MODEL_A_BOAT(mSnapshot.mVehicle.eModel)
|
|
OR IS_THIS_MODEL_A_JETSKI(mSnapshot.mVehicle.eModel)
|
|
VECTOR vIntersect
|
|
IF NOT TEST_PROBE_AGAINST_WATER(<<vPos.x,vpos.y,vpos.z + 30>>,<<vPos.x,vpos.y,vpos.z - 30>>,vIntersect)
|
|
CPRINTLN(debug_replay,"Player vehicle is a boat or jetski on land, NOT setting on ground properly")
|
|
bSetOnGround = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
IF bSetOnGround
|
|
SET_VEHICLE_ON_GROUND_PROPERLY(vehSnapshot)
|
|
ENDIF
|
|
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: bPersonalVehicle = ", mSnapshot.bPersonalVehicle)
|
|
|
|
// Flag this as a personal vehicle if needed
|
|
IF mSnapshot.bPersonalVehicle = TRUE
|
|
IF bDeleteSamePlayerVehicles
|
|
IF IS_THIS_MODEL_A_CAR(GET_ENTITY_MODEL(vehSnapshot))
|
|
DELETE_ALL_SCRIPT_CREATED_PLAYER_VEHICLES(mSnapshot.ePlayerCharacter, VEHICLE_TYPE_CAR)
|
|
ELIF IS_THIS_MODEL_A_BIKE(GET_ENTITY_MODEL(vehSnapshot))
|
|
DELETE_ALL_SCRIPT_CREATED_PLAYER_VEHICLES(mSnapshot.ePlayerCharacter, VEHICLE_TYPE_BIKE)
|
|
ENDIF
|
|
ENDIF
|
|
SET_VEHICLE_NOT_STEALABLE_AMBIENTLY(vehSnapshot, FALSE)
|
|
SET_VEHICLE_CAN_SAVE_IN_GARAGE(vehSnapshot, FALSE)
|
|
SET_VEHICLE_HAS_STRONG_AXLES(vehSnapshot, TRUE)
|
|
STORE_TEMP_PLAYER_VEHICLE_ID(vehSnapshot, mSnapshot.ePlayerCharacter)
|
|
// non-personal vehicle, but was created by vehgen
|
|
ELIF NOT IS_VEHICLE_SNAPSHOT_SPECIAL_CASE(vehSnapshot,mSnapshot.vVehicleVelocity,mSnapshot.bInVehicle) AND mSnapshot.bVehGen AND ARE_STRINGS_EQUAL(GET_THIS_SCRIPT_NAME(),"startup_positioning")
|
|
//We have the loaded the vehicle from the snapshot, remove the duplicate vehgen B*1821085
|
|
VEHICLE_GEN_NAME_ENUM vehGen = DOES_VEHICLE_MATCH_A_VEHGEN_VEHICLE(vehSnapshot)
|
|
IF vehGen = VEHGEN_NONE
|
|
mSnapshot.bVehGen = FALSE
|
|
ELSE
|
|
DELETE_VEHICLE_GEN_VEHICLE(vehGen)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Is the replay controller restoring this vehicle snapshot?
|
|
IF g_replay.replayStageID != RS_NOT_REQUIRED
|
|
AND g_replay.replayStageID != RS_ACTIVE
|
|
AND g_replay.replayStageID != RS_REJECTED
|
|
AND g_replay.replayStageID != RS_NOT_RUNNING
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: Replaying being processed.")
|
|
|
|
// Does the replay owner match the last mission vehgen owner?
|
|
IF GET_HASH_KEY(g_replay.replayScriptName) = g_iLastMissionVehgenOwnerHash
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: Replay script matches the last mission vehgen owner.")
|
|
|
|
// Does the snapshot vehicle's model match the mission vehgen model?
|
|
IF mSnapshot.mVehicle.eModel = g_savedGlobals.sVehicleGenData.sDynamicData[21].eModel
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: Mission vehgen model matches the replay snapshot model.")
|
|
|
|
SET_VEHICLE_GEN_AVAILABLE(VEHGEN_MISSION_VEH, FALSE)
|
|
DELETE_VEHICLE_GEN_VEHICLE(VEHGEN_MISSION_VEH)
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: Cleaned up conflicting mission vehgen.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// Restore whether this vehicle was being tracked for impound
|
|
IF mSnapshot.bTrackedForImpound = TRUE
|
|
TRACK_VEHICLE_FOR_IMPOUND(vehSnapshot, mSnapshot.ePlayerCharacter)
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "CreateSnapshotVehicle: bTrackedForImpound = ", mSnapshot.bTrackedForImpound)
|
|
|
|
// Unload the model
|
|
SET_MODEL_AS_NO_LONGER_NEEDED(mSnapshot.mVehicle.eModel)
|
|
|
|
vTemp = GET_ENTITY_COORDS(vehSnapshot)
|
|
CPRINTLN(DEBUG_REPLAY, "Snapshot vehicle restored at ", vPos, " actual vehicle location is ",vTemp)
|
|
ENDIF
|
|
RETURN vehSnapshot
|
|
ELSE
|
|
SCRIPT_ASSERT("CreateSnapshotVehicle: Vehicle model not loaded. Use HasSnapshotVehicleLoaded() before calling this command.")
|
|
ENDIF
|
|
ENDIF
|
|
SCRIPT_ASSERT("CreateSnapshotVehicle: Tried to create a vehicle for a snapshot that had no vehicle saved. Check IsSnapshotVehicleAvailable() before creating.")
|
|
|
|
RETURN vehSnapshot
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Runs shape test for players vehicle at road node.
|
|
/// PARAMS:
|
|
/// postion - road node VECTOR postion
|
|
/// heading = road node FLOAT heading
|
|
/// playerVehicleSnapshot - saved vehicle snapshot
|
|
/// vPlayersVeh - the index of the player vehicle (shape test will ignore collisions with this entity)
|
|
/// RETURNS:
|
|
/// TRUE if shape test passes, FALSE otherwise
|
|
FUNC BOOL CAN_LOAD_VEHICLE_AT_ROAD_NODE(VECTOR postion, FLOAT heading, VEHICLE_SNAPSHOT playerVehicleSnapshot, ENTITY_INDEX vPlayersVeh)
|
|
|
|
//First check to see if the vehicle is about to be placed on an
|
|
//active mission trigger.
|
|
INT iTriggerIndex
|
|
VECTOR vTriggerPosition
|
|
STATIC_BLIP_NAME_ENUM eMaxBlip
|
|
|
|
#IF USE_SP_DLC
|
|
REPEAT MAX_MISSION_TRIGGERS_TU iTriggerIndex
|
|
IF g_TriggerableMissionsTU[iTriggerIndex].bUsed
|
|
STATIC_BLIP_NAME_ENUM eTriggerBlip = g_TriggerableMissionsTU[iTriggerIndex].eBlip
|
|
#ENDIF
|
|
|
|
#IF NOT USE_SP_DLC
|
|
REPEAT MAX_MISSION_TRIGGERS iTriggerIndex
|
|
IF g_TriggerableMissions[iTriggerIndex].bUsed
|
|
STATIC_BLIP_NAME_ENUM eTriggerBlip = g_TriggerableMissions[iTriggerIndex].eBlip
|
|
#ENDIF
|
|
eMaxBlip = STATIC_BLIP_NAME_DUMMY_FINAL
|
|
|
|
//B* 2083300: Make sure the blip is in the acceptable range (under name_dummy_final)
|
|
IF eTriggerBlip >= eMaxBlip
|
|
CPRINTLN(debug_replay,"Blip value out of range, does this mission have a blip?")
|
|
RETURN FALSE
|
|
ENDIF
|
|
IF IS_BIT_SET(g_GameBlips[eTriggerBlip].iSetting, STATIC_BLIP_SETTING_MULTI_COORD_AND_SPRITE)
|
|
vTriggerPosition = GET_STATIC_BLIP_POSITION(eTriggerBlip, GET_CURRENT_PLAYER_PED_INT())
|
|
ELSE
|
|
vTriggerPosition = GET_STATIC_BLIP_POSITION(eTriggerBlip)
|
|
ENDIF
|
|
|
|
//Vehicle is within 3m of a mission trigger. Don't let it spawn here.
|
|
IF VDIST2(postion, vTriggerPosition) < 9 //3^2
|
|
CPRINTLN(DEBUG_REPLAY,"ROAD_NODE_TEST: FAIL - ON TRIGGER")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
#IF USE_SP_DLC
|
|
ENDIF
|
|
ENDREPEAT
|
|
#ENDIF
|
|
|
|
#IF NOT USE_SP_DLC
|
|
ENDIF
|
|
ENDREPEAT
|
|
#ENDIF
|
|
|
|
SHAPETEST_INDEX shapeTestIndex
|
|
ENTITY_INDEX entityHit
|
|
VECTOR vTempMin
|
|
VECTOR vTempMax
|
|
VECTOR vHitPos
|
|
VECTOR vHitNorm
|
|
INT iReturnValue = -1
|
|
|
|
GET_MODEL_DIMENSIONS(playerVehicleSnapshot.mVehicle.eModel, vTempMin, vTempMax)
|
|
|
|
shapeTestIndex = START_SHAPE_TEST_BOX(postion,vTempMax-vTempMin,<<0.0,0.0,heading>>,DEFAULT,SCRIPT_INCLUDE_VEHICLE|SCRIPT_INCLUDE_OBJECT|SCRIPT_INCLUDE_RAGDOLL|SCRIPT_INCLUDE_GLASS, vPlayersVeh)
|
|
|
|
WHILE GET_SHAPE_TEST_RESULT(shapeTestIndex,iReturnValue,vHitPos,vHitNorm,entityHit) = SHAPETEST_STATUS_RESULTS_NOTREADY
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
IF iReturnValue = 0
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_REPLAY,"ROAD_NODE_TEST: PASS")
|
|
#ENDIF
|
|
//load vehicle
|
|
RETURN TRUE
|
|
ELIF iReturnValue = 1
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_REPLAY,"ROAD_NODE_TEST: FAIL")
|
|
#ENDIF
|
|
//Don't load vehicle
|
|
RETURN FALSE
|
|
ELSE
|
|
#IF IS_DEBUG_BUILD
|
|
CPRINTLN(DEBUG_REPLAY,"ROAD_NODE_TEST: NON EXISTENT!!??!!??")
|
|
#ENDIF
|
|
//Something went wrong, Don't load vehicle
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Finds closest road node to player vehicle. If a suitable node is found, the player vehicle snapshot is updated.
|
|
/// PARAMS:
|
|
/// playerVehicleSnapshot - passed by reference.
|
|
/// vPlayersVeh - the index of the player vehicle (shape test will ignore collisions with this entity)
|
|
/// RETURNS:
|
|
/// TRUE if suitable node is found and snapshot updated, FALSE otherwise
|
|
FUNC BOOL CAN_LOAD_VEHICLE_FROM_SNAPSHOT_AT_NEARBY_ROAD_NODE(VEHICLE_SNAPSHOT &playerVehicleSnapshot, ENTITY_INDEX vPlayersVeh)
|
|
|
|
INT iNodeIterator = 1
|
|
INT iNumOfLanes
|
|
FLOAT fRotTemp
|
|
VECTOR vPosTemp
|
|
|
|
REQUEST_PATH_NODES_IN_AREA_THIS_FRAME(playerVehicleSnapshot.vVehiclePos.x-DEFAULT_ROAD_NODE_LOAD_DIST, playerVehicleSnapshot.vVehiclePos.y-DEFAULT_ROAD_NODE_LOAD_DIST, playerVehicleSnapshot.vVehiclePos.x+DEFAULT_ROAD_NODE_LOAD_DIST, playerVehicleSnapshot.vVehiclePos.y+DEFAULT_ROAD_NODE_LOAD_DIST)
|
|
|
|
WHILE NOT ARE_NODES_LOADED_FOR_AREA(playerVehicleSnapshot.vVehiclePos.x-DEFAULT_ROAD_NODE_LOAD_DIST, playerVehicleSnapshot.vVehiclePos.y-DEFAULT_ROAD_NODE_LOAD_DIST, playerVehicleSnapshot.vVehiclePos.x+DEFAULT_ROAD_NODE_LOAD_DIST, playerVehicleSnapshot.vVehiclePos.y+DEFAULT_ROAD_NODE_LOAD_DIST)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
WHILE GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING(playerVehicleSnapshot.vVehiclePos,iNodeIterator,vPosTemp,fRotTemp,iNumOfLanes)
|
|
IF GET_DISTANCE_BETWEEN_COORDS(playerVehicleSnapshot.vVehiclePos, vPosTemp, FALSE) <= DEFAULT_ROAD_NODE_LOAD_DIST
|
|
IF CAN_LOAD_VEHICLE_AT_ROAD_NODE(vPosTemp, fRotTemp, playerVehicleSnapshot, vPlayersVeh)
|
|
//set new vehicle postion
|
|
playerVehicleSnapshot.vVehiclePos = vPosTemp
|
|
playerVehicleSnapshot.fVehicleHeading = fRotTemp
|
|
playerVehicleSnapshot.vVehicleVelocity = <<0.0,0.0,0.0>>
|
|
RETURN TRUE
|
|
ELSE
|
|
iNodeIterator++
|
|
ENDIF
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Runs shape test for the players vehicle
|
|
/// PARAMS:
|
|
/// playerVehicleSnapshot - saved vehicle snapshot
|
|
/// vPlayersVeh - the index of the player vehicle (shape test will ignore collisions with this entity)
|
|
/// RETURNS:
|
|
/// TRUE if shape test passes, FALSE otherwise
|
|
FUNC BOOL CAN_LOAD_VEHICLE_AT_SNAPSHOT_POSITION(VEHICLE_SNAPSHOT playerVehicleSnapshot, ENTITY_INDEX vPlayersVeh = NULL)
|
|
|
|
//First check to see if the vehicle is about to be placed on an
|
|
//active mission trigger.
|
|
INT iTriggerIndex
|
|
VECTOR vTriggerPosition
|
|
STATIC_BLIP_NAME_ENUM eMaxBlip
|
|
|
|
#IF USE_SP_DLC
|
|
REPEAT MAX_MISSION_TRIGGERS_TU iTriggerIndex
|
|
IF g_TriggerableMissionsTU[iTriggerIndex].bUsed
|
|
STATIC_BLIP_NAME_ENUM eTriggerBlip = g_TriggerableMissionsTU[iTriggerIndex].eBlip
|
|
|
|
#ENDIF
|
|
|
|
#IF NOT USE_SP_DLC
|
|
REPEAT MAX_MISSION_TRIGGERS iTriggerIndex
|
|
IF g_TriggerableMissions[iTriggerIndex].bUsed
|
|
STATIC_BLIP_NAME_ENUM eTriggerBlip = g_TriggerableMissions[iTriggerIndex].eBlip
|
|
#ENDIF
|
|
|
|
eMaxBlip = STATIC_BLIP_NAME_DUMMY_FINAL
|
|
|
|
//B* 2083300: Make sure the blip is in the acceptable range (under name_dummy_final)
|
|
IF eTriggerBlip >= eMaxBlip
|
|
CPRINTLN(debug_replay,"Blip value out of range, does this mission have a blip?")
|
|
RETURN FALSE
|
|
ENDIF
|
|
IF IS_BIT_SET(g_GameBlips[eTriggerBlip].iSetting, STATIC_BLIP_SETTING_MULTI_COORD_AND_SPRITE)
|
|
vTriggerPosition = GET_STATIC_BLIP_POSITION(eTriggerBlip, GET_CURRENT_PLAYER_PED_INT())
|
|
ELSE
|
|
vTriggerPosition = GET_STATIC_BLIP_POSITION(eTriggerBlip)
|
|
ENDIF
|
|
|
|
//Vehicle is within 3m of a mission trigger. Don't let it spawn here.
|
|
IF VDIST2(playerVehicleSnapshot.vVehiclePos, vTriggerPosition) < 3 //3^2
|
|
CPRINTLN(DEBUG_REPLAY,"LOAD_VEHICLE_SNAPSHOT_SHAPETEST_RESULT: FAIL - ON TRIGGER")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
#IF USE_SP_DLC
|
|
ENDIF
|
|
ENDREPEAT
|
|
#ENDIF
|
|
|
|
#IF NOT USE_SP_DLC
|
|
ENDIF
|
|
ENDREPEAT
|
|
#ENDIF
|
|
|
|
|
|
SHAPETEST_INDEX shapeTestIndex
|
|
ENTITY_INDEX hitEntity
|
|
VECTOR vTempMin
|
|
VECTOR vTempMax
|
|
VECTOR vHitPos
|
|
VECTOR vHitNorm
|
|
INT iReturnValue = -1
|
|
|
|
//Now run a shapetest to check if the vehicle will collide with any game objects.
|
|
GET_MODEL_DIMENSIONS(playerVehicleSnapshot.mVehicle.eModel, vTempMin, vTempMax)
|
|
|
|
IF NOT IS_ENTITY_DEAD(vPlayersVeh)
|
|
shapeTestIndex = START_SHAPE_TEST_BOX(playerVehicleSnapshot.vVehiclePos,vTempMax-vTempMin,<<0.0, 0.0,playerVehicleSnapshot.fVehicleHeading>>,DEFAULT,SCRIPT_INCLUDE_VEHICLE|SCRIPT_INCLUDE_OBJECT|SCRIPT_INCLUDE_RAGDOLL|SCRIPT_INCLUDE_GLASS,vPlayersVeh)
|
|
ENDIF
|
|
|
|
WHILE GET_SHAPE_TEST_RESULT(shapeTestIndex,iReturnValue,vHitPos,vHitNorm,hitEntity) = SHAPETEST_STATUS_RESULTS_NOTREADY
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
IF iReturnValue = 0
|
|
CPRINTLN(DEBUG_REPLAY,"LOAD_VEHICLE_SNAPSHOT_SHAPETEST_RESULT: PASS")
|
|
|
|
//load vehicle
|
|
RETURN TRUE
|
|
ELIF iReturnValue = 1
|
|
CPRINTLN(DEBUG_REPLAY,"LOAD_VEHICLE_SNAPSHOT_SHAPETEST_RESULT: FAIL")
|
|
|
|
//Don't load vehicle
|
|
RETURN FALSE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY,"LOAD_VEHICLE_SNAPSHOT_SHAPETEST_RESULT: NON EXISTENT!!??!!??")
|
|
|
|
//Something went wrong, Don't load vehicle
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Restores the vehicle stored in the specified snapshot
|
|
/// Clears the nearby area, waits for model to load, creates vehicle
|
|
/// Puts player in if he is very near, sets vehicle as no longer needed
|
|
/// PARAMS:
|
|
/// mVehicleSnapshot - the start or stage snapshot
|
|
/// mPlayerVehicle - the index of the vehicle created
|
|
/// bAllowBoats - is this vehicle allowed to be a boat?
|
|
/// bWarpInCheck - if this is set to true we warp the player into the vehicle if he was in it when the vehicle was snapshotted
|
|
/// bAllowPlanes - is this vehicle allowed to be a plane?
|
|
/// bAllowCopCars - is this vehicle allowed to be a cop car?
|
|
/// RETURNS:
|
|
/// TRUE if vehicle was created, FALSE otherwise
|
|
FUNC BOOL RestoreSnapshotVehicle(VEHICLE_SNAPSHOT &mVehicleSnapshot, VEHICLE_INDEX &mPlayerVehicle, BOOL bAllowBoats = FALSE, BOOL bWarpInCheck = FALSE, BOOL bAllowPlanes = TRUE, BOOL bAllowCopCars = TRUE, BOOL bDeleteSamePlayerVehicles = FALSE #IF USE_TU_CHANGES , BOOL bIgnoreCollisionCheck = FALSE #ENDIF )
|
|
|
|
BOOL bPutPlayerInVehicle = FALSE
|
|
VECTOR vMin
|
|
VECTOR vMax
|
|
VECTOR vVehicleMin
|
|
VECTOR vVehicleMax
|
|
FLOAT fVehicleX
|
|
FLOAT fVehicleY
|
|
FLOAT fVehicleZ
|
|
FLOAT fVehicleLargestDimension
|
|
|
|
IF IsSnapshotVehicleAvailable(mVehicleSnapshot)
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: mVehicleSnapshot.mVehicle.eModel =", GET_MODEL_NAME_FOR_DEBUG(mVehicleSnapshot.mVehicle.eModel))
|
|
|
|
IF bAllowBoats = FALSE
|
|
IF IS_THIS_MODEL_A_BOAT(mVehicleSnapshot.mVehicle.eModel)
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: Not restoring snapshot vehicle as it is a boat")
|
|
// pass info to impound if needed
|
|
IF mVehicleSnapshot.bTrackedForImpound = TRUE
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: creation aborted: update impound info")
|
|
SEND_VEHICLE_DATA_TO_IMPOUND_USING_SETUP(mVehicleSnapshot.mVehicle, mVehicleSnapshot.ePlayerCharacter)
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bAllowPlanes = FALSE
|
|
IF IS_THIS_MODEL_A_PLANE(mVehicleSnapshot.mVehicle.eModel)
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: Not restoring snapshot vehicle as it is a plane")
|
|
// pass info to impound if needed
|
|
IF mVehicleSnapshot.bTrackedForImpound = TRUE
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: creation aborted: update impound info")
|
|
SEND_VEHICLE_DATA_TO_IMPOUND_USING_SETUP(mVehicleSnapshot.mVehicle, mVehicleSnapshot.ePlayerCharacter)
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
IF bAllowCopCars = FALSE
|
|
IF IS_MODEL_POLICE_VEHICLE(mVehicleSnapshot.mVehicle.eModel)
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: Not restoring snapshot vehicle as it is a cop car")
|
|
// pass info to impound if needed
|
|
IF mVehicleSnapshot.bTrackedForImpound = TRUE
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: creation aborted: update impound info")
|
|
SEND_VEHICLE_DATA_TO_IMPOUND_USING_SETUP(mVehicleSnapshot.mVehicle, mVehicleSnapshot.ePlayerCharacter)
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: Restoring snapshot vehicle")
|
|
|
|
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
|
|
IF NOT IS_ENTITY_DEAD(PLAYER_PED_ID()) // need the player to be alive to check his co-ords
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: Trying to clear the area now")
|
|
|
|
GET_MODEL_DIMENSIONS(mVehicleSnapshot.mVehicle.eModel, vVehicleMin, vVehicleMax)
|
|
fVehicleX = vVehicleMax.x - vVehicleMin.x
|
|
fVehicleY = vVehicleMax.y - vVehicleMin.y
|
|
fVehicleZ = vVehicleMax.z - vVehicleMin.z
|
|
|
|
// see which dimension of the vehicle is the largest
|
|
fVehicleLargestDimension = fVehicleX
|
|
IF fVehicleY > fVehicleLargestDimension
|
|
fVehicleLargestDimension = fVehicleY
|
|
ENDIF
|
|
IF fVehicleZ > fVehicleLargestDimension
|
|
fVehicleLargestDimension = fVehicleZ
|
|
ENDIF
|
|
|
|
// work out area we need to check is clear to create vehicle
|
|
vMin = mVehicleSnapshot.vVehiclePos
|
|
vMin = vMin -vVehicleMin
|
|
vMax = mVehicleSnapshot.vVehiclePos
|
|
vMax = vMax +vVehicleMax
|
|
|
|
//CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: vehicle pos =", mVehicleSnapshot.vVehiclePos)
|
|
//CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: vehicle area min pos =", vMin)
|
|
//CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: vehicle area max pos =", vMax)
|
|
//CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: vVehicleMin =", vVehicleMin)
|
|
//CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: vVehicleMax =", vVehicleMax)
|
|
|
|
//#1676539
|
|
#IF USE_TU_CHANGES
|
|
ENTITY_INDEX vPlayersVeh
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
vPlayersVeh = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
|
|
ELSE
|
|
vPlayersVeh = PLAYER_PED_ID()
|
|
ENDIF
|
|
|
|
//#1990795
|
|
BOOL bCheckIfAreaOccupied = TRUE
|
|
IF bIgnoreCollisionCheck
|
|
IF IS_THIS_MODEL_A_PLANE(mVehicleSnapshot.mVehicle.eModel)
|
|
OR IS_THIS_MODEL_A_HELI(mVehicleSnapshot.mVehicle.eModel)
|
|
bCheckIfAreaOccupied = FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bCheckIfAreaOccupied
|
|
// AND IF IS_AREA_OCCUPIED(vMin, vMax, FALSE, TRUE, FALSE, TRUE, FALSE, vPlayersVeh)
|
|
// and not IS_THIS_MODEL_A_HELI(mVehicleSnapshot.mVehicle.eModel)
|
|
//B* 1819425
|
|
IF NOT CAN_LOAD_VEHICLE_AT_SNAPSHOT_POSITION(mVehicleSnapshot, vPlayersVeh)
|
|
IF NOT CAN_LOAD_VEHICLE_FROM_SNAPSHOT_AT_NEARBY_ROAD_NODE(mVehicleSnapshot, vPlayersVeh)
|
|
// position is blocked, abort creation
|
|
CPRINTLN(DEBUG_REPLAY, "TU RestoreSnapshotVehicle: Vehicle pos occupied, so aborting creation")
|
|
// pass info to impound if needed
|
|
IF mVehicleSnapshot.bTrackedForImpound = TRUE
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: creation aborted: update impound info")
|
|
SEND_VEHICLE_DATA_TO_IMPOUND_USING_SETUP(mVehicleSnapshot.mVehicle, mVehicleSnapshot.ePlayerCharacter)
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// clear room for car //Moved clear tasks to run after shape tests
|
|
CLEAR_AREA(mVehicleSnapshot.vVehiclePos, fVehicleLargestDimension, TRUE)
|
|
CLEAR_AREA_OF_OBJECTS(mVehicleSnapshot.vVehiclePos, fVehicleLargestDimension, CLEAROBJ_FLAG_FORCE)
|
|
|
|
#IF NOT USE_TU_CHANGES
|
|
IF IS_AREA_OCCUPIED(vMin, vMax, FALSE, TRUE, FALSE, TRUE, FALSE)
|
|
// position is blocked, abort creation
|
|
CPRINTLN(DEBUG_REPLAY, "non TU RestoreSnapshotVehicle: Vehicle pos occupied, so aborting creation")
|
|
// pass info to impound if needed
|
|
IF mVehicleSnapshot.bTrackedForImpound = TRUE
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: creation aborted: update impound info")
|
|
SEND_VEHICLE_DATA_TO_IMPOUND_USING_SETUP(mVehicleSnapshot.mVehicle, mVehicleSnapshot.ePlayerCharacter)
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
// area is ok for creating vehicle, load assets
|
|
RequestSnapshotVehicleModel(mVehicleSnapshot)
|
|
WHILE NOT HasSnapshotVehicleLoaded(mVehicleSnapshot)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
// create vehicle
|
|
mPlayerVehicle = CreateSnapshotVehicle(mVehicleSnapshot, <<0.0,0.0,0.0>>, 0.0, bDeleteSamePlayerVehicles) // create vehicle at the position it was in the start snapshot
|
|
IF DOES_ENTITY_EXIST(mPlayerVehicle)
|
|
IF IS_VEHICLE_DRIVEABLE(mPlayerVehicle)
|
|
IF DOES_ENTITY_EXIST(PLAYER_PED_ID())
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
IF bWarpInCheck = TRUE
|
|
AND mVehicleSnapshot.bInVehicle = TRUE
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: player was in vehicle when snapshotted, put in")
|
|
bPutPlayerInVehicle= TRUE
|
|
ELSE
|
|
// see if player is very close to the vehicle
|
|
IF GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(mPlayerVehicle), GET_ENTITY_COORDS(PLAYER_PED_ID())) < 3.0
|
|
OR IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), mPlayerVehicle)
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: player is very close to vehicle, put in")
|
|
bPutPlayerInVehicle= TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
|
|
#IF USE_TU_CHANGES
|
|
// If we are re-creating the vehicle for the startup script, do not spawn the player inside if
|
|
// it is in a restricted area.
|
|
#IF USE_CLF_DLC
|
|
IF (GET_HASH_KEY(GET_THIS_SCRIPT_NAME()) = HASH("startup_pos_CLF"))
|
|
#endif
|
|
|
|
#if USE_NRM_DLC
|
|
IF (GET_HASH_KEY(GET_THIS_SCRIPT_NAME()) = HASH("startup_pos_NRM"))
|
|
#endif
|
|
|
|
#if NOT USE_SP_DLC
|
|
IF (GET_HASH_KEY(GET_THIS_SCRIPT_NAME()) = HASH("startup_positioning"))
|
|
#endif
|
|
|
|
// in a Vehicle Garage
|
|
IF IS_ENTITY_IN_ANGLED_AREA(mPlayerVehicle, <<207.433578,-1019.795410,-100.472763>>, <<189.933777,-1019.623474,-95.568832>>, 17.187500)
|
|
bPutPlayerInVehicle = FALSE
|
|
|
|
// Hayes' Chopshop
|
|
ELIF IS_ENTITY_IN_ANGLED_AREA(mPlayerVehicle, <<483.717468,-1326.629883,28.213499>>, <<474.964355,-1307.998291,34.494976>>, 12.000000)
|
|
bPutPlayerInVehicle = FALSE
|
|
|
|
// Impound Garage
|
|
ELIF IS_ENTITY_IN_ANGLED_AREA(mPlayerVehicle, <<439.543152,-996.976868,24.883070>>, <<428.293549,-997.019226,28.574581>>, 8.500000)
|
|
bPutPlayerInVehicle = FALSE
|
|
ENDIF
|
|
|
|
#IF USE_CLF_DLC
|
|
ENDIF
|
|
#endif
|
|
|
|
#if USE_NRM_DLC
|
|
ENDIF
|
|
#endif
|
|
|
|
#if NOT USE_SP_DLC
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#ENDIF
|
|
|
|
|
|
IF bPutPlayerInVehicle = TRUE
|
|
IF IS_ENTITY_ATTACHED(PLAYER_PED_ID())
|
|
FREEZE_ENTITY_POSITION(GET_ENTITY_ATTACHED_TO(PLAYER_PED_ID()), FALSE)
|
|
ELSE
|
|
FREEZE_ENTITY_POSITION(PLAYER_PED_ID(), FALSE)
|
|
ENDIF
|
|
SET_ENTITY_COLLISION(PLAYER_PED_ID(), TRUE)
|
|
CPRINTLN(DEBUG_REPLAY, "Turning player's collision back on as we're putting him in a vehicle.")
|
|
SET_PED_INTO_VEHICLE(PLAYER_PED_ID(), mPlayerVehicle)
|
|
|
|
// if we're putting the player in a helicopter, start the blades
|
|
IF IS_THIS_MODEL_A_HELI(mVehicleSnapshot.mVehicle.eModel)
|
|
SET_HELI_BLADES_FULL_SPEED(mPlayerVehicle)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: Snapshot vehicle restored")
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: No snapshot vehicle available to restore")
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreSnapshotVehicle: Snapshot vehicle not restored")
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the snapshot vehicle is restricted or was snapshotted for another character
|
|
/// PARAMS:
|
|
/// mSnapshot - start or stage snapshot
|
|
/// RETURNS:
|
|
/// TRUE if it is safe to restore this snapshot vehicle. FALSE otherwise
|
|
FUNC BOOL CanRestoreSnapshotVehicleForCharacter(SNAPSHOT_STRUCT &mSnapshot, enumCharacterList eCharacter)
|
|
|
|
enumCharacterList eVehicleOwner
|
|
|
|
IF IsSnapshotVehicleAvailable(mSnapshot.mVehicleStruct)
|
|
IF mSnapshot.bRestrictedVehicle = FALSE
|
|
|
|
// check if this vehicle is owned by another character
|
|
eVehicleOwner = mSnapshot.mVehicleStruct.ePlayerCharacter
|
|
|
|
IF eVehicleOwner = NO_CHARACTER
|
|
OR eVehicleOwner = eCharacter
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "CanRestoreSnapshotVehicleForCharacter. Vehicle belongs to a different character.")
|
|
CPRINTLN(DEBUG_REPLAY, "eVehicleOwner: ", eVehicleOwner , " eCharacter: ", eCharacter)
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "CanRestoreSnapshotVehicleForCharacter. Vehicle restricted.")
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "CanRestoreSnapshotVehicleForCharacter. no vehicle available.")
|
|
ENDIF
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Attempts to restore the stage snapshot vehicle, if this fails it attempts to restore the start snapshot vehicle
|
|
/// PARAMS:
|
|
/// eCharacter - the character we are trying to restore a vehicle for
|
|
/// RETURNS:
|
|
/// TRUE if vehicle restored. FALSE otherwise
|
|
FUNC BOOL RestoreAnySnapshotVehicle(enumCharacterList eCharacter, BOOL bAllowCopCars = TRUE)
|
|
|
|
VEHICLE_INDEX mPlayerVehicle
|
|
|
|
// try to create stage snapshot vehicle
|
|
IF CanRestoreSnapshotVehicleForCharacter(g_stageSnapshot, eCharacter)
|
|
IF RestoreSnapshotVehicle(g_stageSnapshot.mVehicleStruct, mPlayerVehicle, FALSE, FALSE, FALSE, bAllowCopCars, TRUE)
|
|
IF DOES_ENTITY_EXIST(mPlayerVehicle)
|
|
// clear velocity here as this is only used if the player has warped
|
|
SET_ENTITY_VELOCITY(mPlayerVehicle, <<0.0,0.0,0.0>>)
|
|
CPRINTLN(DEBUG_REPLAY, "Clear player vehicle velocity as we've warped him.")
|
|
SET_VEHICLE_AS_NO_LONGER_NEEDED(mPlayerVehicle)
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// try to create start snapshot vehicle
|
|
IF CanRestoreSnapshotVehicleForCharacter(g_startSnapshot, eCharacter)
|
|
|
|
// the stage snapshot has the correct position info in it, so copy it over...
|
|
g_startSnapshot.mVehicleStruct.vVehiclePos = g_stageSnapshot.mVehicleStruct.vVehiclePos
|
|
g_startSnapshot.mVehicleStruct.fVehicleHeading = g_stageSnapshot.mVehicleStruct.fVehicleHeading
|
|
|
|
IF RestoreSnapshotVehicle(g_startSnapshot.mVehicleStruct, mPlayerVehicle, FALSE, FALSE, FALSE, bAllowCopCars, TRUE)
|
|
IF DOES_ENTITY_EXIST(mPlayerVehicle)
|
|
// clear velocity here as this is only used if the player has warped
|
|
SET_ENTITY_VELOCITY(mPlayerVehicle, <<0.0,0.0,0.0>>)
|
|
CPRINTLN(DEBUG_REPLAY, "Clear player vehicle velocity as we've warped him.")
|
|
SET_VEHICLE_AS_NO_LONGER_NEEDED(mPlayerVehicle)
|
|
ENDIF
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "RestoreAnySnapshotVehicle. No valid snapshot vehicle to restore.")
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
// ===========================================================================================================
|
|
// FAIL WEAPON FUNCTIONS
|
|
// ===========================================================================================================
|
|
|
|
/// PURPOSE:
|
|
/// Checks if the player character specified had the weapon specified at their last checkpoint
|
|
/// PARAMS:
|
|
/// iCharIndex - 0,1,2 Michael, Franklin, Trevor
|
|
/// mWeapon - the weapon type we are checking
|
|
/// RETURNS:
|
|
/// BOOL, true if this player character had this weapon at their last checkpoint. false otherwise
|
|
FUNC BOOL Had_Weapon_At_Last_Checkpoint(INT iCharIndex, WEAPON_TYPE mWeapon)
|
|
|
|
INT iTempIndex = 0
|
|
|
|
#IF NOT USE_TU_CHANGES
|
|
SNAPSHOT_STRUCT paramSnapshot
|
|
|
|
IF g_replayMissionStage > 0
|
|
paramSnapshot = g_stageSnapshot
|
|
ELSE
|
|
paramSnapshot = g_startSnapshot
|
|
ENDIF
|
|
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
IF paramSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].eWeaponType = mWeapon
|
|
IF paramSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iAmmoCount > 0
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Had fail weapon at last checkpoint, but no ammo: don't store.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
REPEAT NUMBER_OF_DLC_WEAPONS iTempIndex
|
|
IF paramSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].eWeaponType = mWeapon
|
|
IF paramSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].iAmmoCount > 0
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Had fail weapon at last checkpoint, but no ammo: don't store.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
#ENDIF
|
|
|
|
#IF USE_TU_CHANGES
|
|
IF g_replayMissionStage > 0
|
|
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
IF g_stageSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].eWeaponType = mWeapon
|
|
IF g_stageSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iAmmoCount > 0
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Had fail weapon at last checkpoint, but no ammo: don't store.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
REPEAT NUMBER_OF_DLC_WEAPONS iTempIndex
|
|
IF g_stageSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].eWeaponType = mWeapon
|
|
IF g_stageSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].iAmmoCount > 0
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Had fail weapon at last checkpoint, but no ammo: don't store.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ELSE
|
|
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
IF g_startSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].eWeaponType = mWeapon
|
|
IF g_startSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iAmmoCount > 0
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Had fail weapon at last checkpoint, but no ammo: don't store.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
REPEAT NUMBER_OF_DLC_WEAPONS iTempIndex
|
|
IF g_startSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].eWeaponType = mWeapon
|
|
IF g_startSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex].iAmmoCount > 0
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Had fail weapon at last checkpoint, but no ammo: don't store.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDREPEAT
|
|
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
// ===========================================================================================================
|
|
// SNAPSHOT STORING FUNCTIONS
|
|
// ===========================================================================================================
|
|
|
|
/// PURPOSE:
|
|
/// Returns string value of weather type passed in
|
|
/// PARAMS:
|
|
/// iWeather - hash of weather type
|
|
/// RETURNS:
|
|
/// STRING of weather type to restore. or empty string if invalid (asserts)
|
|
FUNC STRING GET_WEATHER_STRING_FROM_HASH(INT iWeather)
|
|
|
|
IF iWeather = HASH("EXTRASUNNY")
|
|
RETURN "EXTRASUNNY"
|
|
|
|
ELIF iWeather = HASH("CLEAR")
|
|
RETURN "CLEAR"
|
|
|
|
ELIF iWeather = HASH("CLOUDS")
|
|
RETURN "CLOUDS"
|
|
|
|
ELIF iWeather = HASH("SMOG")
|
|
RETURN "SMOG"
|
|
|
|
ELIF iWeather = HASH("FOGGY")
|
|
RETURN "FOGGY"
|
|
|
|
ELIF iWeather = HASH("OVERCAST")
|
|
RETURN "OVERCAST"
|
|
|
|
ELIF iWeather = HASH("RAIN")
|
|
RETURN "RAIN"
|
|
|
|
ELIF iWeather = HASH("THUNDER")
|
|
RETURN "THUNDER"
|
|
|
|
ELIF iWeather = HASH("CLEARING")
|
|
RETURN "CLEARING"
|
|
|
|
ELIF iWeather = HASH("NEUTRAL")
|
|
RETURN "NEUTRAL"
|
|
|
|
ELIF iWeather = HASH("SNOW")
|
|
RETURN "SNOW"
|
|
|
|
ELIF iWeather = HASH("BLIZZARD")
|
|
RETURN "BLIZZARD"
|
|
|
|
ELIF iWeather = HASH("SNOWLIGHT")
|
|
RETURN "SNOWLIGHT"
|
|
ENDIF
|
|
|
|
// not found stored weather, assert and exit
|
|
CPRINTLN(DEBUG_REPLAY, "GET_WEATHER_STRING_FROM_HASH: Stored weather invalid: ", iWeather)
|
|
SCRIPT_ASSERT("GET_WEATHER_STRING_FROM_HASH: Stored weather invalid.")
|
|
RETURN ""
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Sets the position of the vehicle in the specified snapshot
|
|
/// This is used to alter where the vehicle will be restored if a replay is rejected.
|
|
/// e.g. If the player is getting warped out of a restricted area etc.
|
|
/// PARAMS:
|
|
/// paramSnapshot - the vehicle snapshot we are editing.
|
|
/// vVehiclePos - where we will want to respawn vehicle.
|
|
/// fVehicleHeading - the heading to use when respawning vehicle.
|
|
PROC Set_Vehicle_Snapshot_Pos(VEHICLE_SNAPSHOT ¶mSnapshot, VECTOR vVehiclePos, FLOAT fVehicleHeading)
|
|
paramSnapshot.vVehiclePos = vVehiclePos
|
|
paramSnapshot.fVehicleHeading = fVehicleHeading
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stores all the info used in a player snapshot struct
|
|
/// bQuickSave - true for quick save and repeat play saves. Use to reposition the player away from unsuitable spawn areas.
|
|
PROC Store_Player_Snapshot(PLAYER_SNAPSHOT &mSnapshot, BOOL bQuickSave = FALSE)
|
|
|
|
// get player's position, heading + wanted level
|
|
mSnapshot.vPos = GET_ENTITY_COORDS(PLAYER_PED_ID()) // store player's position
|
|
mSnapshot.fHeading = GET_ENTITY_HEADING(PLAYER_PED_ID())
|
|
mSnapshot.eParachuteState = GET_PED_PARACHUTE_STATE(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_REPLAY, "Storing eParachuteState as ", mSnapshot.eParachuteState)
|
|
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
mSnapshot.iWantedLevel = GET_PLAYER_WANTED_LEVEL(PLAYER_ID())
|
|
CPRINTLN(DEBUG_REPLAY, "Storing player's wanted level as ", mSnapshot.iWantedLevel)
|
|
ENDIF
|
|
|
|
// -----Check to see if we need to overwrite these for any reason--------
|
|
|
|
// Vinewood cinema
|
|
IF VDIST(mSnapshot.vPos, <<320.9934, 265.2515, 82.1221>>) < 10
|
|
mSnapshot.vPos = <<301.2162, 202.1357, 103.3797>>
|
|
mSnapshot.fHeading = 156.5144
|
|
CPRINTLN(DEBUG_REPLAY, "Player in Vinewood cinema, overwrite stored co-ords")
|
|
|
|
// Downtown cinema
|
|
ELIF VDIST(mSnapshot.vPos, << 377.1530, -717.5670, 10.0536 >>) < 10
|
|
mSnapshot.vPos = << 394.2567, -713.5439, 28.2853 >>
|
|
mSnapshot.fHeading = 276.6273
|
|
CPRINTLN(DEBUG_REPLAY, "Player in Downtown cinema, overwrite stored co-ords")
|
|
|
|
// Morningwood cinema
|
|
ELIF VDIST(mSnapshot.vPos, << -1425.5645, -244.3000, 15.8053 >>) < 10
|
|
mSnapshot.vPos = <<-1423.4724, -214.2539, 45.5004>>
|
|
mSnapshot.fHeading = 353.8757
|
|
CPRINTLN(DEBUG_REPLAY, "Player in Morningwood cinema, overwrite stored co-ords")
|
|
|
|
// Finale Choice in progress
|
|
ELIF GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(HASH("Finale_Choice")) > 0
|
|
mSnapshot.vPos = <<4.2587, 525.0214, 173.6281>>
|
|
mSnapshot.fHeading = 203.6746
|
|
CPRINTLN(DEBUG_REPLAY, "Finale choice in progress, overwrite stored co-ords")
|
|
|
|
// Cable Car up
|
|
ELIF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_ON_CABLE_CAR_UP))
|
|
mSnapshot.vPos = <<452.0255, 5571.8501, 780.1859>>
|
|
mSnapshot.fHeading = 78.9858
|
|
CPRINTLN(DEBUG_REPLAY, "Player on cable car going up, overwrite stored co-ords")
|
|
|
|
// Cable Car down
|
|
ELIF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_ON_CABLE_CAR_DOWN))
|
|
mSnapshot.vPos = <<-745.4462, 5595.1465, 40.6594>>
|
|
mSnapshot.fHeading = 261.7470
|
|
CPRINTLN(DEBUG_REPLAY, "Player on cable car going down, overwrite stored co-ords")
|
|
|
|
// Ferris Wheel
|
|
ELIF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_ON_FERRIS_WHEEL))
|
|
mSnapshot.vPos = <<-1675.5215, -1125.5901, 12.0910>>
|
|
mSnapshot.fHeading = 271.8208
|
|
CPRINTLN(DEBUG_REPLAY, "Player on ferris wheel, overwrite stored co-ords")
|
|
|
|
// Rollercoaster
|
|
ELIF IS_BIT_SET(g_iRepeatPlayBits, ENUM_TO_INT(RPB_FROZEN_ON_ROLLERCOASTER))
|
|
mSnapshot.vPos = <<-1631.2192, -1112.8052, 12.0212>>
|
|
mSnapshot.fHeading = 316.8879
|
|
CPRINTLN(DEBUG_REPLAY, "Player on rollercoaster, overwrite stored co-ords")
|
|
// Lester's house
|
|
ELIF GET_INTERIOR_FROM_ENTITY(PLAYER_PED_ID()) = GET_INTERIOR_AT_COORDS_WITH_TYPE(<<1272.6588, -1715.4669, 53.7715>>, "v_lesters")
|
|
mSnapshot.vPos = <<1276.9564, -1725.1892, 53.6551>>
|
|
mSnapshot.fHeading = 204.1703
|
|
CPRINTLN(DEBUG_REPLAY, "Player in Lester's house, overwrite stored co-ords")
|
|
|
|
// Murder Mystery - Mine
|
|
ELIF IS_ENTITY_IN_ANGLED_AREA( PLAYER_PED_ID(), <<-415.436462, 2068.288574, 113.300171>>,
|
|
<<-564.951599, 1884.702515, 134.040344>>, 258.750000 )
|
|
OR IS_ENTITY_IN_ANGLED_AREA( PLAYER_PED_ID(), <<-596.470581, 2089.920898, 125.412750>>,
|
|
<<-581.213440, 2036.256104, 136.283630>>, 9.500000 )
|
|
mSnapshot.vPos = <<-601.5900, 2099.1973, 128.8928>>
|
|
mSnapshot.fHeading = 204.7498
|
|
CPRINTLN(DEBUG_REPLAY, "Player in mine, overwrite stored co-ords")
|
|
|
|
// Murder Mystery - Solomon's Office
|
|
ELIF VDIST(mSnapshot.vPos, <<-1007.392639, -477.958435, 52.535702>>) < 8
|
|
mSnapshot.vPos = <<-1018.3756, -483.9436, 36.0964>>
|
|
mSnapshot.fHeading = 114.7664
|
|
CPRINTLN(DEBUG_REPLAY, "Player in Solomon's office, overwrite stored co-ords")
|
|
|
|
// Car Steal - Garage
|
|
ELIF VDIST(mSnapshot.vPos, <<480.66620, -1317.80847, 28.20303>>) < 15
|
|
mSnapshot.vPos = <<497.7238, -1310.9323, 28.2372>>
|
|
mSnapshot.fHeading = 289.3663
|
|
CPRINTLN(DEBUG_REPLAY, "Player in Car Steal - Garage, overwrite stored co-ords")
|
|
|
|
//RC - Omega shed
|
|
ELIF VDIST(mSnapshot.vPos, <<2329.5266, 2571.3113, 45.6779>>) < 5
|
|
mSnapshot.vPos = <<2316.9304, 2594.1528, 45.7199>>
|
|
mSnapshot.fHeading = 348.1325
|
|
CPRINTLN(DEBUG_REPLAY, "Player in Omega - Shed, overwrite stored co-ords")
|
|
ENDIF
|
|
|
|
// quick save only checks
|
|
IF bQuickSave = TRUE
|
|
SHOP_NAME_ENUM eShop
|
|
VECTOR vPos
|
|
FLOAT fHeading
|
|
|
|
// closed shop (to avoid issues of getting stuck behind respawned shopkeeper - like 1482459)
|
|
IF IS_PLAYER_IN_CLOSED_SHOP(eShop)
|
|
IF GET_SHOP_PARKING_SPACE(eShop, vPos, fHeading)
|
|
vPos.z = vPos.z + 1 // up the z so we're not in the ground
|
|
mSnapshot.vPos = vPos
|
|
mSnapshot.fHeading = fHeading
|
|
CPRINTLN(DEBUG_REPLAY, "Player in closed shop, overwrite stored co-ords")
|
|
ENDIF
|
|
|
|
// in a Vehicle Garage
|
|
ELIF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<207.433578,-1019.795410,-100.472763>>, <<189.933777,-1019.623474,-95.568832>>, 17.187500)
|
|
enumCharacterList eChar = GET_CURRENT_PLAYER_PED_ENUM()
|
|
|
|
IF eChar = CHAR_MICHAEL
|
|
mSnapshot.vPos = <<-65.1234, 81.2517, 70.5644>>
|
|
mSnapshot.fHeading = 71.6237
|
|
|
|
ELIF eChar = CHAR_FRANKLIN
|
|
mSnapshot.vPos = <<-68.5531, -1824.3774, 25.9424>>
|
|
mSnapshot.fHeading = 215.8295
|
|
|
|
ELIF eChar = CHAR_TREVOR
|
|
mSnapshot.vPos = <<-220.8189, -1162.3016, 22.0242>>
|
|
mSnapshot.fHeading = 70.2711
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "Player in garage, overwrite stored co-ords")
|
|
|
|
// Hayes' Chopshop
|
|
ELIF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<483.717468,-1326.629883,28.213499>>, <<474.964355,-1307.998291,34.494976>>, 12.000000)
|
|
mSnapshot.vPos = <<495.4108, -1306.0801, 29.2883>>
|
|
mSnapshot.fHeading = 213.6273
|
|
CPRINTLN(DEBUG_REPLAY, "Player in hayes garage, overwrite stored co-ords")
|
|
|
|
// Under Floyd's apartment. B*1747233, 2214618
|
|
ELIF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<-1146.77, -1534.22, 3.37>>, <<-1158.452515,-1517.749634,6.374244>>, 13.000000)
|
|
mSnapshot.vPos = <<-1160.0951, -1515.4070, 3.1496>>
|
|
mSnapshot.fHeading = 305.6424
|
|
CPRINTLN(DEBUG_REPLAY, "Player under Floyd's apartment, overwrite stored co-ords")
|
|
|
|
#IF USE_TU_CHANGES
|
|
// Impound Garage
|
|
ELIF IS_ENTITY_IN_ANGLED_AREA(PLAYER_PED_ID(), <<439.543152,-996.976868,24.883070>>, <<428.293549,-997.019226,28.574581>>, 8.500000)
|
|
mSnapshot.vPos = <<431.8853, -1013.1330, 28.7907>>
|
|
mSnapshot.fHeading = 186.6814
|
|
CPRINTLN(DEBUG_REPLAY, "Player in impound garage, overwrite stored co-ords")
|
|
#ENDIF
|
|
|
|
// B*1721440 - RC - Nigel 2 hospital interior (still accessible straight after the mission ends)
|
|
ELIF IS_POSITION_INSIDE_SPECIFC_INTERIOR(mSnapshot.vPos, "v_hospital", << 307.3065, -589.9595, 43.3020 >>)
|
|
mSnapshot.vPos = <<279.4137, -585.8815, 43.2502>>
|
|
mSnapshot.fHeading = 48.8028
|
|
CPRINTLN(DEBUG_REPLAY, "Player in hospital interior, overwrite stored co-ords : ", mSnapshot.vPos)
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Checks to see if the vehicle index matches one stored in the restricted vehicles array
|
|
/// PARAMS:
|
|
/// mVehicle - teh vehicle we are checking
|
|
/// RETURNS:
|
|
/// TRUE if the vehicle is set as restricted, FALSE otherwise
|
|
FUNC BOOL IS_VEHICLE_RESTRICTED(VEHICLE_INDEX mVehicle)
|
|
INT iVehicleNumber
|
|
FOR iVehicleNumber = 0 TO MAX_RESTRICTED_VEHICLES -1
|
|
IF g_replay.mRestrictedVehicles[iVehicleNumber] = mVehicle
|
|
RETURN TRUE // the vehicle is in the restricted array
|
|
ENDIF
|
|
ENDFOR
|
|
RETURN FALSE //the vehicle is not in the restricted array
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Stores the vehicle snapshot, does not use the massive replay snapshot struct
|
|
PROC Store_Vehicle_Snapshot_Only(VEHICLE_SNAPSHOT &mVehicleSnapshot, VEHICLE_INDEX mVehicle, BOOL bStorePosition = TRUE)
|
|
|
|
GET_VEHICLE_SETUP(mVehicle, mVehicleSnapshot.mVehicle)
|
|
|
|
// store whether this is a personal vehicle so we can flag it as such when re-creating it
|
|
mVehicleSnapshot.bPersonalVehicle = IS_VEHICLE_A_PLAYER_PERSONAL_VEHICLE(mVehicle)
|
|
CPRINTLN(DEBUG_REPLAY, "bPersonalVehicle = ", mVehicleSnapshot.bPersonalVehicle)
|
|
|
|
mVehicleSnapshot.ePlayerCharacter = GET_PLAYER_PED_PERSONAL_VEHICLE_BELONGS_TO(mVehicle)
|
|
CPRINTLN(DEBUG_REPLAY, "ePlayerCharacter = ", GET_PLAYER_PED_STRING(mVehicleSnapshot.ePlayerCharacter))
|
|
|
|
//If not a personal vehicle check if it was generated by a vehgen - B* 1821085
|
|
IF NOT mVehicleSnapshot.bPersonalVehicle
|
|
//If VehGen true, remain true
|
|
IF NOT mVehicleSnapshot.bVehGen
|
|
mVehicleSnapshot.bVehGen = IS_VEHICLE_A_VEHGEN_VEHICLE(mVehicle)
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF bStorePosition = TRUE
|
|
|
|
// store the vehicle's position and heading + velocity
|
|
mVehicleSnapshot.vVehiclePos = GET_ENTITY_COORDS(mVehicle)
|
|
mVehicleSnapshot.fVehicleHeading = GET_ENTITY_HEADING(mVehicle)
|
|
mVehicleSnapshot.vVehicleVelocity = GET_ENTITY_VELOCITY(mVehicle)
|
|
|
|
// -----Check to see if we need to overwrite these for any reason--------
|
|
// Under Floyd's apartment. B*1747233
|
|
IF IS_ENTITY_IN_ANGLED_AREA(mVehicle, <<-1154.325562,-1523.871338,3.262189>>, <<-1158.452515,-1517.749634,6.374244>>, 13.000000)
|
|
mVehicleSnapshot.vVehiclePos = <<-1160.0951, -1515.4070, 3.1496>>
|
|
mVehicleSnapshot.fVehicleHeading = 305.6424
|
|
CPRINTLN(DEBUG_REPLAY, "Player vehicle under Floyd's apartment, overwrite stored co-ords")
|
|
ENDIF
|
|
|
|
CPRINTLN(DEBUG_REPEAT, "vVehicleVelocity x= ", mVehicleSnapshot.vVehicleVelocity.x, " y= ", mVehicleSnapshot.vVehicleVelocity.y, " z= ", mVehicleSnapshot.vVehicleVelocity.z)
|
|
|
|
IF g_vCarToTrackForImpound = mVehicle
|
|
mVehicleSnapshot.bTrackedForImpound = TRUE
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "bTrackedForImpound = ", mVehicleSnapshot.bTrackedForImpound)
|
|
ENDIF
|
|
|
|
// store whether the player is in a vehicle
|
|
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
|
|
mVehicleSnapshot.bInVehicle = TRUE
|
|
ELSE
|
|
mVehicleSnapshot.bInVehicle = FALSE
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "mVehicleSnapshot.bInVehicle = ", mVehicleSnapshot.bInVehicle)
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stores information on a specific vehicle that exists in the world.
|
|
/// PARAMS:
|
|
/// mVehicleSnapshot - the vehicle snapshot we are updating
|
|
/// mSnapshot - the start or stage snapshot
|
|
/// mVehicle - The vehicle to store.
|
|
/// bStorePosition - can set this to FALSE so we don't overwrite the replay rejected warp position
|
|
FUNC BOOL Store_Vehicle_Snapshot_For_Vehicle(VEHICLE_SNAPSHOT &mVehicleSnapshot, SNAPSHOT_STRUCT &mSnapshot, VEHICLE_INDEX mVehicle, BOOL bStorePosition = TRUE)
|
|
|
|
IF IS_VEHICLE_DRIVEABLE(mVehicle)
|
|
CPRINTLN(DEBUG_REPLAY, "Storing player's vehicle snapshot now for script: ", GET_THIS_SCRIPT_NAME())
|
|
|
|
//-------- store the small vehicle snapshot info---------------
|
|
Store_Vehicle_Snapshot_Only(mVehicleSnapshot, mVehicle, bStorePosition )
|
|
|
|
//------- store the other info that is needed in the large replay snapshot-------
|
|
|
|
// store the vehicle index
|
|
mSnapshot.mVehicleIndex = mVehicle
|
|
|
|
// store whether this vehicle is restricted
|
|
IF IS_VEHICLE_RESTRICTED(mVehicle)
|
|
mSnapshot.bRestrictedVehicle = TRUE
|
|
CPRINTLN(DEBUG_REPLAY, "Snapshot vehicle set as restricted.")
|
|
ELSE
|
|
mSnapshot.bRestrictedVehicle = FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE // vehicle succesfully snapshotted
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Not storing vehicle for snapshot as it is not driveable.")
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Checks if there is a suitable vehicle to snapshot for this character
|
|
/// PARAMS:
|
|
/// mPlayerPed - which player are we checking this vehicle for?
|
|
/// mVehicle - index to the vehicle that is getting snapshotted
|
|
/// bDoDistanceCheck - only snapshot this vehicle if nearby?
|
|
/// RETURNS:
|
|
/// TRUE if there is a suitable vehicle, FALSE otherwise
|
|
/// bQuickSave - true for quick save and repeat play saves. Use to ignore vehicles with "IgnoredByQuickSave" decor
|
|
FUNC BOOL Is_Vehicle_Available_To_Snapshot(PED_INDEX mPlayerPed, VEHICLE_INDEX &mVehicle, BOOL bDoDistanceCheck = TRUE, BOOL bQuickSave = FALSE)
|
|
|
|
|
|
// works if the player is in a vehicle, or is near his last vehicle
|
|
IF DOES_ENTITY_EXIST(mPlayerPed)
|
|
IF NOT IS_PED_INJURED(mPlayerPed)
|
|
|
|
IF mPlayerPed = PLAYER_PED_ID()
|
|
mVehicle = GET_PLAYERS_LAST_VEHICLE()
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot checking for non player vehicle.")
|
|
mVehicle = GET_VEHICLE_PED_IS_IN(mPlayerPed, TRUE)
|
|
ENDIF
|
|
|
|
IF DOES_ENTITY_EXIST(mVehicle)
|
|
IF IS_VEHICLE_DRIVEABLE(mVehicle)
|
|
IF bDoDistanceCheck = FALSE
|
|
OR GET_DISTANCE_BETWEEN_COORDS(GET_ENTITY_COORDS(mVehicle), GET_ENTITY_COORDS(mPlayerPed)) < MAX_VEHICLE_SNAPSHOT_DIST
|
|
|
|
//Don't store player vehicle if they are a taxi passenger.
|
|
IF IS_VEHICLE_MODEL(mVehicle, TAXI)
|
|
IF GET_PED_IN_VEHICLE_SEAT(mVehicle, VS_DRIVER) != mPlayerPed
|
|
AND GET_PED_IN_VEHICLE_SEAT(mVehicle, VS_DRIVER) != NULL
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot not storing as player is passenger in taxi.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// don't store the vehicle if it is in the player's garage
|
|
IF IS_VEHICLE_IN_PLAYERS_GARAGE(mVehicle, GET_CURRENT_PLAYER_PED_ENUM(), TRUE)
|
|
STRING sThisScriptName = GET_THIS_SCRIPT_NAME()
|
|
|
|
IF NOT ARE_STRINGS_EQUAL(sThisScriptName, "save_anywhere")
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot not storing, as vehicle is in player's garage [triggered by \"", sThisScriptName, "\"].")
|
|
RETURN FALSE
|
|
ELIF NOT IS_PED_IN_ANY_VEHICLE(mPlayerPed, TRUE)
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot not storing, as vehicle is in player's garage [triggered by \"", sThisScriptName, "\", player [", GET_CURRENT_PLAYER_PED_STRING(), "] inside vehicle].")
|
|
RETURN FALSE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot ok to store storing, vehicle is in player's garage but script trying to save is \"", sThisScriptName, "\", player [", GET_CURRENT_PLAYER_PED_STRING(), "] not in vehicle].")
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot vehicle [", GET_MODEL_NAME_OF_VEHICLE_FOR_DEBUG_ONLY(mVehicle), "] not in current players [", GET_CURRENT_PLAYER_PED_STRING(), "] garage.")
|
|
ENDIF
|
|
|
|
IF bQuickSave = TRUE
|
|
IF DECOR_EXIST_ON(mVehicle, "IgnoredByQuickSave")
|
|
IF DECOR_GET_BOOL(mVehicle, "IgnoredByQuickSave")
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot not storing, as vehicle is flagged to be ignored for quick save.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// // Impound Garage
|
|
// ELIF IS_ENTITY_IN_ANGLED_AREA(mVehicle, <<439.543152,-996.976868,24.883070>>, <<428.293549,-997.019226,28.574581>>, 8.500000)
|
|
// CPRINTLN(DEBUG_REPLAY, "Car in impound garage, don't store")
|
|
// RETURN FALSE
|
|
// ENDIF
|
|
ELSE
|
|
// don't store the blimp unless quick save / repeat play save
|
|
IF IS_VEHICLE_MODEL(mVehicle, BLIMP)
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot not storing blimp.")
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
// the vehicle is safe to snapshot
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot found suitable vehicle.")
|
|
RETURN TRUE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot failed distance check.")
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot not driveable.")
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Is_Vehicle_Available_To_Snapshot does not exist.")
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
RETURN FALSE // vehicle not snapshotted
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Stores information on the player's current vehicle
|
|
/// If he isn't in a vehicle it uses his last vehicle if it is nearby
|
|
/// PARAMS:
|
|
/// mVehicleSnapshot - the vehicle snapshot we are updating
|
|
/// mSnapshot - the start or stage snapshot
|
|
/// mPlayerPed - the player ped we are storing this info for
|
|
/// bDoDistanceCheck - can be set to false to store this info even if player is far away from the vehicle
|
|
/// bStorePosition - can set this to FALSE so we don't overwrite the replay rejected warp position
|
|
/// bQuickSave - true for quick save and repeat play saves. Use to ignore vehicles with "IgnoredByQuickSave" decor
|
|
PROC Store_Vehicle_Snapshot_For_Last_Player_Vehicle(VEHICLE_SNAPSHOT &mVehicleSnapshot, SNAPSHOT_STRUCT &mSnapshot, PED_INDEX mPlayerPed = NULL, BOOL bDoDistanceCheck = TRUE, BOOL bStorePosition = TRUE, BOOL bQuickSave = FALSE)
|
|
|
|
VEHICLE_INDEX mVehicle
|
|
|
|
// set who we are storing this vehicle for
|
|
IF mPlayerPed = NULL
|
|
CPRINTLN(DEBUG_REPLAY, "Storing vehicle snapshot for current player ped")
|
|
mPlayerPed = PLAYER_PED_ID() // default to the player ped
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Storing vehicle snapshot for non-current player ped")
|
|
ENDIF
|
|
|
|
// store vehicle owner info
|
|
IF DOES_ENTITY_EXIST(mPlayerPed)
|
|
mSnapshot.eVehicleOwner = GET_PLAYER_PED_ENUM(mPlayerPed)
|
|
ENDIF
|
|
|
|
// see if there is a suitable vehicle to snapshot
|
|
IF Is_Vehicle_Available_To_Snapshot(mPlayerPed, mVehicle, bDoDistanceCheck, bQuickSave)
|
|
|
|
// store the snapshot info
|
|
Store_Vehicle_Snapshot_For_Vehicle(mVehicleSnapshot, mSnapshot, mVehicle, bStorePosition)
|
|
//B* 1774589: Disabling saving the heli causes player to fall to his death after loading
|
|
ELIF DOES_ENTITY_EXIST(mVehicle)
|
|
IF NOT IS_ENTITY_DEAD(mVehicle)
|
|
IF IS_VEHICLE_MODEL(mVehicle,SKYLIFT) AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(),mVehicle)
|
|
//Store the heli anyway if in air
|
|
Store_Vehicle_Snapshot_For_Vehicle(mVehicleSnapshot, mSnapshot, mVehicle, bStorePosition)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Stores information on the player's current vehicle
|
|
/// If he isn't in a vehicle it uses his last vehicle if it is nearby
|
|
/// This only uses the small vehicle snapshot, so doesn't store the replay snapshot info
|
|
/// PARAMS:
|
|
/// mVehicleSnapshot - the vehicle snapshot we are updating
|
|
/// mPlayerPed - the player ped we are storing this info for
|
|
/// bDoDistanceCheck - can be set to false to store this info even if player is far away from the vehicle
|
|
/// bStorePosition - can set this to FALSE so we don't overwrite the replay rejected warp position
|
|
/// RETURNS:
|
|
/// VEHICLE_INDEX index of the snapshotted vehicle. Will be invalid if no vehicle was snapshotted
|
|
FUNC VEHICLE_INDEX Store_Vehicle_Snapshot_Only_For_Last_Vehicle(VEHICLE_SNAPSHOT &mVehicleSnapshot, PED_INDEX mPlayerPed = NULL, BOOL bDoDistanceCheck = TRUE, BOOL bStorePosition = TRUE)
|
|
|
|
VEHICLE_INDEX mVehicle
|
|
VEHICLE_INDEX mSnapshotVehicle
|
|
|
|
// set who we are storing this vehicle for
|
|
IF mPlayerPed = NULL
|
|
CPRINTLN(DEBUG_REPLAY, "Storing vehicle snapshot for current player ped")
|
|
mPlayerPed = PLAYER_PED_ID() // default to the player ped
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Storing vehicle snapshot for non-current player ped")
|
|
ENDIF
|
|
|
|
// see if there is a suitable vehicle to snapshot
|
|
IF Is_Vehicle_Available_To_Snapshot(mPlayerPed, mSnapshotVehicle, bDoDistanceCheck)
|
|
|
|
// store the snapshot info
|
|
Store_Vehicle_Snapshot_Only(mVehicleSnapshot, mSnapshotVehicle, bStorePosition)
|
|
|
|
// update the return index
|
|
mVehicle = mSnapshotVehicle
|
|
|
|
//B* 1774589: Disabling saving the heli causes player to fall to his death after loading
|
|
ELIF DOES_ENTITY_EXIST(mSnapshotVehicle)
|
|
IF NOT IS_ENTITY_DEAD(mSnapshotVehicle)
|
|
IF IS_VEHICLE_MODEL(mSnapshotVehicle,SKYLIFT) AND IS_PED_IN_VEHICLE(PLAYER_PED_ID(),mSnapshotVehicle)
|
|
//Store the heli anyway if in air
|
|
Store_Vehicle_Snapshot_Only(mVehicleSnapshot, mSnapshotVehicle, bStorePosition)
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
|
|
RETURN mVehicle // this will be null if vehicle not snapshotted
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Stores the player and vehicle snapshots in the repeat play snapshot
|
|
/// (Passes the start snapshot into the vehicle command, though this data isn't used for save anywhere and repeat play)
|
|
/// (This command should only be used at the star of repeat play, or when save anywhere is used)
|
|
PROC Store_RepeatPlay_Snapshot()
|
|
|
|
#IF USE_CLF_DLC
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_REPEAT, "Storing repeat play snapshot")
|
|
Store_Player_Snapshot(g_savedGlobalsClifford.sRepeatPlayData.mPlayerStruct, TRUE)
|
|
Store_Vehicle_Snapshot_For_Last_Player_Vehicle(g_savedGlobalsClifford.sRepeatPlayData.mVehicleStruct, g_startSnapshot, NULL, TRUE, TRUE, TRUE)
|
|
g_savedGlobalsClifford.sRepeatPlayData.eMission = g_eMissionSceneToCleanup
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#IF USE_NRM_DLC
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_REPEAT, "Storing repeat play snapshot")
|
|
Store_Player_Snapshot(g_savedGlobalsnorman.sRepeatPlayData.mPlayerStruct, TRUE)
|
|
Store_Vehicle_Snapshot_For_Last_Player_Vehicle(g_savedGlobalsnorman.sRepeatPlayData.mVehicleStruct, g_startSnapshot, NULL, TRUE, TRUE, TRUE)
|
|
g_savedGlobalsnorman.sRepeatPlayData.eMission = g_eMissionSceneToCleanup
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#IF NOT USE_SP_DLC
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
CPRINTLN(DEBUG_REPEAT, "Storing repeat play snapshot")
|
|
Store_Player_Snapshot(g_savedGlobals.sRepeatPlayData.mPlayerStruct, TRUE)
|
|
Store_Vehicle_Snapshot_For_Last_Player_Vehicle(g_savedGlobals.sRepeatPlayData.mVehicleStruct, g_startSnapshot, NULL, TRUE, TRUE, TRUE)
|
|
g_savedGlobals.sRepeatPlayData.eMission = g_eMissionSceneToCleanup
|
|
|
|
// if nearest valid RC mission is waiting for player to leavbe area we need to store it
|
|
// so when this save is loaded we can stop it from trying to immediately launch
|
|
g_savedGlobals.sRepeatPlayData.eRCMissionToBlock = PRIVATE_Get_Nearest_Valid_RC_Mission()
|
|
IF g_savedGlobals.sRepeatPlayData.eRCMissionToBlock <> NO_RC_MISSION
|
|
IF g_RandomChars[g_savedGlobals.sRepeatPlayData.eRCMissionToBlock].rcIsAwaitingTrigger = FALSE
|
|
AND g_RandomChars[g_savedGlobals.sRepeatPlayData.eRCMissionToBlock].rcLeaveAreaCheck = TRUE
|
|
CPRINTLN(DEBUG_REPEAT, "Saving near an RC mission that is waiting for player to leave area. Store details: ", GET_RC_MISSION_DISPLAY_STRING_FROM_ID(g_savedGlobals.sRepeatPlayData.eRCMissionToBlock))
|
|
ELSE
|
|
// nearest RC mission is not blocked, don't store
|
|
g_savedGlobals.sRepeatPlayData.eRCMissionToBlock = NO_RC_MISSION
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stores various information about the current player character, and some info on all player characters
|
|
/// This can then be restored later on
|
|
/// PARAMS:
|
|
/// paramSnapshot - the mission start snapshot or the checkpoint snapshot
|
|
/// bStoreVehicleInfo - Do we want to store info about the player's vehicle?
|
|
/// iStage - the number of the checkpoint stage
|
|
/// sStageName - the name of this checkpoint stage
|
|
PROC Store_Game_State_Snapshot(SNAPSHOT_STRUCT ¶mSnapshot, STRING sScriptName, INT iStage, STRING sStageName, BOOL bStoreVehicleInfo = TRUE, PED_INDEX mPedForVehicleSnapshot = NULL)
|
|
INT iTempIndex
|
|
INT iCharIndex
|
|
|
|
paramSnapshot.eCharacter = GET_CURRENT_PLAYER_PED_ENUM() // store player character
|
|
paramSnapshot.tTime = GET_CURRENT_TIMEOFDAY() // store time of day
|
|
|
|
// store weather details
|
|
GET_CURR_WEATHER_STATE(paramSnapshot.iPreviousWeather, paramSnapshot.iNextWeather, paramSnapshot.fWeatherInterp)
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
Store_Player_Snapshot(paramSnapshot.mPlayerStruct) // store player pos and heading
|
|
|
|
STORE_PLAYER_PED_ARMOUR(PLAYER_PED_ID()) // store weapons and armour in globals
|
|
STORE_PLAYER_PED_WEAPONS(PLAYER_PED_ID())
|
|
GET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), paramSnapshot.mCurrentWeapon) // store current weapon
|
|
IF paramSnapshot.mCurrentWeapon = WEAPONTYPE_INVALID
|
|
OR paramSnapshot.mCurrentWeapon = WEAPONTYPE_OBJECT // cellphone
|
|
paramSnapshot.mCurrentWeapon = WEAPONTYPE_UNARMED // if weapon invalid, use unarmed instead
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "Storing current weapon as: ", paramSnapshot.mCurrentWeapon, " With ammo: ", GET_AMMO_IN_PED_WEAPON(PLAYER_PED_ID(), paramSnapshot.mCurrentWeapon))
|
|
ENDIF
|
|
|
|
// store info for all playable characters
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
//Armor.
|
|
paramSnapshot.iArmour[iCharIndex] = g_savedGlobals.sPlayerData.sInfo.iArmour[iCharIndex]
|
|
|
|
//Ped variations.
|
|
IF iCharIndex = GET_CURRENT_PLAYER_PED_INT()
|
|
GET_PED_VARIATIONS(PLAYER_PED_ID(), paramSnapshot.mVariations[iCharIndex])
|
|
ELSE
|
|
REPEAT NUM_PED_COMPONENTS iTempIndex
|
|
paramSnapshot.mVariations[iCharIndex].iTextureVariation[iTempIndex] = g_sLastStoredPlayerPedClothes[iCharIndex].iTextureVariation[iTempIndex]
|
|
paramSnapshot.mVariations[iCharIndex].iDrawableVariation[iTempIndex] = g_sLastStoredPlayerPedClothes[iCharIndex].iDrawableVariation[iTempIndex]
|
|
ENDREPEAT
|
|
|
|
// hair / mask / beard stuff
|
|
paramSnapshot.mVariations[iCharIndex].eStoredHairstyle = g_sLastStoredPlayerPedClothes[iCharIndex].eStoredHairstyle
|
|
paramSnapshot.mVariations[iCharIndex].eItemThatForcedHairChange = g_sLastStoredPlayerPedClothes[iCharIndex].eItemThatForcedHairChange
|
|
paramSnapshot.mVariations[iCharIndex].eTypeThatForcedHairChange = g_sLastStoredPlayerPedClothes[iCharIndex].eTypeThatForcedHairChange
|
|
paramSnapshot.mVariations[iCharIndex].eStoredBeard = g_sLastStoredPlayerPedClothes[iCharIndex].eStoredBeard
|
|
paramSnapshot.mVariations[iCharIndex].eItemThatForcedBeardChange = g_sLastStoredPlayerPedClothes[iCharIndex].eItemThatForcedBeardChange
|
|
paramSnapshot.mVariations[iCharIndex].eTypeThatForcedBeardChange = g_sLastStoredPlayerPedClothes[iCharIndex].eTypeThatForcedBeardChange
|
|
|
|
REPEAT NUM_PLAYER_PED_PROPS iTempIndex
|
|
paramSnapshot.mVariations[iCharIndex].iPropIndex[iTempIndex] = g_sLastStoredPlayerPedClothes[iCharIndex].iPropIndex[iTempIndex]
|
|
paramSnapshot.mVariations[iCharIndex].iPropTexture[iTempIndex] = g_sLastStoredPlayerPedClothes[iCharIndex].iPropTexture[iTempIndex]
|
|
ENDREPEAT
|
|
ENDIF
|
|
|
|
//Weapons.
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
paramSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex] = g_savedGlobals.sPlayerData.sInfo.sWeapons[iCharIndex].sWeaponInfo[iTempIndex]
|
|
ENDREPEAT
|
|
REPEAT NUMBER_OF_DLC_WEAPONS iTempIndex
|
|
paramSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex] = g_savedGlobals.sPlayerData.sInfo.sWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex]
|
|
ENDREPEAT
|
|
|
|
//Purchased weapon stats.
|
|
SWITCH INT_TO_ENUM(enumCharacterList, iCharIndex)
|
|
CASE CHAR_MICHAEL
|
|
STAT_GET_INT(SP0_WEAP_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[0])
|
|
STAT_GET_INT(SP0_WEAP_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[1])
|
|
|
|
STAT_GET_INT(SP0_WEAP_ADDON_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0])
|
|
STAT_GET_INT(SP0_WEAP_ADDON_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[1])
|
|
STAT_GET_INT(SP0_WEAP_ADDON_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[2])
|
|
STAT_GET_INT(SP0_WEAP_ADDON_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[3])
|
|
STAT_GET_INT(SP0_WEAP_ADDON_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[4])
|
|
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[0])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[1])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[2])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[3])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[4])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_5, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[5])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_6, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[6])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_7, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[7])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_8, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[8])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_9, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[9])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_10, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[10])
|
|
STAT_GET_INT(SP0_WEAP_TINT_PURCH_11, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[11])
|
|
BREAK
|
|
CASE CHAR_FRANKLIN
|
|
STAT_GET_INT(SP1_WEAP_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[0])
|
|
STAT_GET_INT(SP1_WEAP_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[1])
|
|
|
|
STAT_GET_INT(SP1_WEAP_ADDON_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0])
|
|
STAT_GET_INT(SP1_WEAP_ADDON_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[1])
|
|
STAT_GET_INT(SP1_WEAP_ADDON_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[2])
|
|
STAT_GET_INT(SP1_WEAP_ADDON_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[3])
|
|
STAT_GET_INT(SP1_WEAP_ADDON_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[4])
|
|
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[0])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[1])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[2])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[3])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[4])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_5, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[5])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_6, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[6])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_7, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[7])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_8, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[8])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_9, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[9])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_10, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[10])
|
|
STAT_GET_INT(SP1_WEAP_TINT_PURCH_11, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[11])
|
|
BREAK
|
|
CASE CHAR_TREVOR
|
|
STAT_GET_INT(SP2_WEAP_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[0])
|
|
STAT_GET_INT(SP2_WEAP_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[1])
|
|
|
|
STAT_GET_INT(SP2_WEAP_ADDON_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0])
|
|
STAT_GET_INT(SP2_WEAP_ADDON_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[1])
|
|
STAT_GET_INT(SP2_WEAP_ADDON_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[2])
|
|
STAT_GET_INT(SP2_WEAP_ADDON_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[3])
|
|
STAT_GET_INT(SP2_WEAP_ADDON_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[4])
|
|
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[0])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[1])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[2])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[3])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[4])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_5, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[5])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_6, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[6])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_7, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[7])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_8, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[8])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_9, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[9])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_10, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[10])
|
|
STAT_GET_INT(SP2_WEAP_TINT_PURCH_11, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[11])
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
// Bank accounts
|
|
paramSnapshot.iBankLogIndex[iCharIndex] = g_savedGlobals.sFinanceData.PLAYER_ACCOUNT_LOGS[iCharIndex].iLogIndexPoint
|
|
paramSnapshot.iCash[iCharIndex] = g_BankAccounts[iCharIndex].iBalance
|
|
|
|
// Default vehicle mods
|
|
paramSnapshot.mPlayerVehicle[0][iCharIndex] = g_savedGlobals.sPlayerData.sInfo.sPlayerVehicle[0][iCharIndex]
|
|
paramSnapshot.mPlayerVehicle[1][iCharIndex] = g_savedGlobals.sPlayerData.sInfo.sPlayerVehicle[1][iCharIndex]
|
|
|
|
// tattoos
|
|
FOR iTempIndex = 0 TO MAX_NUMBER_OF_TATTOO_BITSETS -1
|
|
paramSnapshot.sTattoos[iCharIndex].iUnlockedTattoos[iTempIndex] = g_savedGlobals.sPlayerData.sTattoos[iCharIndex].iUnlockedTattoos[iTempIndex]
|
|
paramSnapshot.sTattoos[iCharIndex].iViewedTattoos[iTempIndex] = g_savedGlobals.sPlayerData.sTattoos[iCharIndex].iViewedTattoos[iTempIndex]
|
|
paramSnapshot.sTattoos[iCharIndex].iCurrentTattoos[iTempIndex] = g_savedGlobals.sPlayerData.sTattoos[iCharIndex].iCurrentTattoos[iTempIndex]
|
|
ENDFOR
|
|
|
|
// clothes
|
|
FOR iTempIndex = 0 TO PED_COMPONENT_USED_SLOT
|
|
paramSnapshot.sComponents[iCharIndex].iHeadBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iHeadBitset0[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iBeardBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iBeardBitset0[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iHairBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iHairBitset0[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset1[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset2[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset2[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset3[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset3[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset4[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset4[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset5[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset5[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset6[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset6[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset7[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset7[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset8[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset8[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iTorsoBitset9[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset9[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iLegsBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iLegsBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset1[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iLegsBitset2[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset2[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iLegsBitset3[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset3[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iHandBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iHandBitset0[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iFeetBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iFeetBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset1[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iFeetBitset2[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset2[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iFeetBitset3[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset3[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iFeetBitset4[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset4[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iTeethBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTeethBitset0[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iSpecialBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecialBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iSpecialBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecialBitset1[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iSpecialBitset2[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecialBitset2[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iSpecial2Bitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecial2Bitset0[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iDeclBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iDeclBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iDeclBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iDeclBitset1[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iJbibBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iJbibBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iJbibBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iJbibBitset1[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iOutfitBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iOutfitBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iOutfitBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iOutfitBitset1[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iPropGroupBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropGroupBitset0[iTempIndex]
|
|
|
|
paramSnapshot.sComponents[iCharIndex].iPropsBitset0[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset0[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iPropsBitset1[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset1[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iPropsBitset2[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset2[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iPropsBitset3[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset3[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iPropsBitset4[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset4[iTempIndex]
|
|
paramSnapshot.sComponents[iCharIndex].iPropsBitset5[iTempIndex] = g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset5[iTempIndex]
|
|
ENDFOR
|
|
ENDREPEAT
|
|
|
|
// Special Ability
|
|
STAT_GET_INT(SP0_SPECIAL_ABILITY, paramSnapshot.iSpecialAbility[0])
|
|
STAT_GET_INT(SP1_SPECIAL_ABILITY, paramSnapshot.iSpecialAbility[1])
|
|
STAT_GET_INT(SP2_SPECIAL_ABILITY, paramSnapshot.iSpecialAbility[2])
|
|
CPRINTLN(DEBUG_REPLAY, "Special Ability stored as M= ", paramSnapshot.iSpecialAbility[0], " F= ", paramSnapshot.iSpecialAbility[1], " T= ",paramSnapshot.iSpecialAbility[2])
|
|
|
|
// Vehicle
|
|
paramSnapshot.eVehicleOwner = NO_CHARACTER
|
|
IF bStoreVehicleInfo = TRUE
|
|
Store_Vehicle_Snapshot_For_Last_Player_Vehicle(paramSnapshot.mVehicleStruct, paramSnapshot, mPedForVehicleSnapshot)
|
|
ENDIF
|
|
|
|
// Battle buddy
|
|
TAKE_BATTLEBUDDY_SNAPSHOT(paramSnapshot.mBattleBuddyStruct)
|
|
|
|
// --------------------------------------print debug info-------------------------------------------------
|
|
#IF IS_DEBUG_BUILD
|
|
TEXT_LABEL_63 tTimeOfDay = TIMEOFDAY_TO_TEXT_LABEL(paramSnapshot.tTime)
|
|
CPRINTLN(DEBUG_REPLAY, "Player Char: ",GET_CHARSHEET_DISPLAY_STRING_FROM_CHARSHEET(paramSnapshot.eCharacter))
|
|
CPRINTLN(DEBUG_REPLAY, "Position: ", paramSnapshot.mPlayerStruct.vPos)
|
|
CPRINTLN(DEBUG_REPLAY, "", tTimeOfDay)
|
|
|
|
STRING sWeather = GET_WEATHER_STRING_FROM_HASH(paramSnapshot.iPreviousWeather)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sWeather)
|
|
CPRINTLN(DEBUG_REPLAY,"Storing previous weather as: ", sWeather)
|
|
ENDIF
|
|
sWeather = GET_WEATHER_STRING_FROM_HASH(paramSnapshot.iNextWeather)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sWeather)
|
|
CPRINTLN(DEBUG_REPLAY,"Storing next weather as: ", sWeather)
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY,"Storing weather interp as: ", paramSnapshot.fWeatherInterp)
|
|
|
|
/* commented out- add back in if debugging ammo / armour /bank accounts
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
STRING strCharName = GET_CHARSHEET_DISPLAY_STRING_FROM_CHARSHEET(INT_TO_ENUM(enumCharacterList, iCharIndex))
|
|
INT iCharAmmo = 0
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
iCharAmmo += paramSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex].iAmmoCount
|
|
ENDREPEAT
|
|
CPRINTLN(DEBUG_REPLAY, " -", strCharName, " Armor: ", paramSnapshot.iArmour[iCharIndex]
|
|
ENDREPEAT
|
|
|
|
// bank info
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
CPRINTLN(DEBUG_REPLAY, "Character ", iCharIndex, " Bank log: ", paramSnapshot.iBankLogIndex[iCharIndex], " Cash: ", paramSnapshot.iCash[iCharIndex])
|
|
ENDREPEAT
|
|
*/
|
|
#ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "-----------------------------------------------------------------")
|
|
CPRINTLN(DEBUG_REPLAY, "")
|
|
|
|
// ---------metrics tracking--------------------------------
|
|
//Update start tracking a new metric zone as we step to a new mission stage.
|
|
#IF IS_DEBUG_BUILD
|
|
StartNewMetricsStage(iStage, sScriptName, sStageName)
|
|
#ENDIF
|
|
|
|
#IF IS_FINAL_BUILD
|
|
//Keeps final build compiling.
|
|
sStageName = sStageName
|
|
iStage = iStage
|
|
#ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stores a snapshot of the current game state, and saves it as the start snapshot
|
|
/// PARAMS:
|
|
/// paramScriptName - which script is saving the snapshot
|
|
/// bStoreVehicleInfo - do we want to store info about the player's vehicle?
|
|
PROC Store_Game_State_Snapshot_For_Start(STRING paramScriptName, BOOL bStoreVehicleInfo = TRUE, PED_INDEX mPedForVehicleSnapshot = NULL)
|
|
|
|
// don't do anything if we're on a replay
|
|
IF g_replay.replayStageID <> RS_ACTIVE
|
|
AND g_replay.replayStageID <> RS_ACTIVATE
|
|
CPRINTLN(DEBUG_REPLAY, "")
|
|
CPRINTLN(DEBUG_REPLAY, "-------------- Gamestate Snapshot - Start ----------------")
|
|
|
|
//---------------- store start snapshot------------------------------------
|
|
g_snapshotScriptName = paramScriptName
|
|
Store_Game_State_Snapshot(g_startSnapshot, paramScriptName, 0, "Start", bStoreVehicleInfo, mPedForVehicleSnapshot)
|
|
|
|
// --------------------Copy this start snapshot to the stage snapshot-----------------------
|
|
CopyStartSnapshotToStageSnapshot()
|
|
|
|
// reset shitskip to end bool, as shitskipping from start won't pass the mission
|
|
g_bShitskipToEnd = FALSE
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Not storing start snapshot as we're on a replay")
|
|
ENDIF
|
|
ENDPROC
|
|
|
|
/// PURPOSE:
|
|
/// Stores a snapshot of the current game state, and saves it as the checkpoint snapshot
|
|
PROC Store_Game_State_Snapshot_For_Stage(INT iStage, STRING sStageName, PED_INDEX mPedForVehicleSnapshot = NULL, BOOL bStoreCheckpointVehicle = TRUE)
|
|
CPRINTLN(DEBUG_REPLAY, "")
|
|
CPRINTLN(DEBUG_REPLAY, "-------------- Gamestate Snapshot - Stage ----------------")
|
|
|
|
// --------snapshot-----------------------------------------
|
|
Store_Game_State_Snapshot(g_stageSnapshot, GET_THIS_SCRIPT_NAME(), iStage, sStageName, bStoreCheckpointVehicle, mPedForVehicleSnapshot)
|
|
ENDPROC
|
|
|
|
// ===========================================================================================================
|
|
// SNAPSHOT RESTORING FUNCTIONS
|
|
// ===========================================================================================================
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Uses the specified game state snapshot to restore player's clothes to the state they were in when the snapshot was taken
|
|
/// PARAMS:
|
|
/// paramSnapshot - the mission start or checkpoint snapshot
|
|
PROC Restore_Game_State_Snapshot_Clothes(SNAPSHOT_STRUCT ¶mSnapshot)
|
|
INT iCharIndex
|
|
INT iTempIndex
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "Restoring player outfit.")
|
|
|
|
// Restoring player character variations to snapshot values.
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
REPEAT NUM_PED_COMPONENTS iTempIndex
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].iTextureVariation[iTempIndex] = paramSnapshot.mVariations[iCharIndex].iTextureVariation[iTempIndex]
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].iDrawableVariation[iTempIndex] = paramSnapshot.mVariations[iCharIndex].iDrawableVariation[iTempIndex]
|
|
ENDREPEAT
|
|
REPEAT NUM_PLAYER_PED_PROPS iTempIndex
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].iPropIndex[iTempIndex] = paramSnapshot.mVariations[iCharIndex].iPropIndex[iTempIndex]
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].iPropTexture[iTempIndex] = paramSnapshot.mVariations[iCharIndex].iPropTexture[iTempIndex]
|
|
ENDREPEAT
|
|
// hair / mask / Beard stuff
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].eStoredHairstyle = paramSnapshot.mVariations[iCharIndex].eStoredHairstyle
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].eItemThatForcedHairChange = paramSnapshot.mVariations[iCharIndex].eItemThatForcedHairChange
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].eTypeThatForcedHairChange = paramSnapshot.mVariations[iCharIndex].eTypeThatForcedHairChange
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].eStoredBeard = paramSnapshot.mVariations[iCharIndex].eStoredBeard
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].eItemThatForcedBeardChange = paramSnapshot.mVariations[iCharIndex].eItemThatForcedBeardChange
|
|
g_sLastStoredPlayerPedClothes[iCharIndex].eTypeThatForcedBeardChange = paramSnapshot.mVariations[iCharIndex].eTypeThatForcedBeardChange
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Uses the specified game state snapshot to restore player's weapon purchased stats to the state they were in when the snapshot was taken
|
|
/// PARAMS:
|
|
/// paramSnapshot - the mission start or checkpoint snapshot
|
|
/// NOTES:
|
|
/// This restores the purchased weapon states in the snap shot
|
|
PROC Restore_Game_State_Snapshot_Purchased_Weapons(SNAPSHOT_STRUCT ¶mSnapshot)
|
|
CPRINTLN(DEBUG_REPLAY, "Restoring player purchased weapons stats.")
|
|
|
|
// Restoring player character weapon loadouts to replay snapshot values.
|
|
INT iCharIndex
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
SWITCH INT_TO_ENUM(enumCharacterList, iCharIndex)
|
|
CASE CHAR_MICHAEL
|
|
STAT_SET_INT(SP0_WEAP_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[0])
|
|
STAT_SET_INT(SP0_WEAP_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[1])
|
|
|
|
STAT_SET_INT(SP0_WEAP_ADDON_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0])
|
|
STAT_SET_INT(SP0_WEAP_ADDON_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[1])
|
|
STAT_SET_INT(SP0_WEAP_ADDON_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[2])
|
|
STAT_SET_INT(SP0_WEAP_ADDON_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[3])
|
|
STAT_SET_INT(SP0_WEAP_ADDON_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[4])
|
|
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[0])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[1])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[2])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[3])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[4])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_5, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[5])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_6, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[6])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_7, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[7])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_8, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[8])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_9, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[9])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_10, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[10])
|
|
STAT_SET_INT(SP0_WEAP_TINT_PURCH_11, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[11])
|
|
BREAK
|
|
CASE CHAR_FRANKLIN
|
|
STAT_SET_INT(SP1_WEAP_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[0])
|
|
STAT_SET_INT(SP1_WEAP_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[1])
|
|
|
|
STAT_SET_INT(SP1_WEAP_ADDON_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0])
|
|
STAT_SET_INT(SP1_WEAP_ADDON_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[1])
|
|
STAT_SET_INT(SP1_WEAP_ADDON_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[2])
|
|
STAT_SET_INT(SP1_WEAP_ADDON_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[3])
|
|
STAT_SET_INT(SP1_WEAP_ADDON_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[4])
|
|
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[0])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[1])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[2])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[3])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[4])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_5, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[5])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_6, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[6])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_7, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[7])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_8, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[8])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_9, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[9])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_10, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[10])
|
|
STAT_SET_INT(SP1_WEAP_TINT_PURCH_11, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[11])
|
|
BREAK
|
|
CASE CHAR_TREVOR
|
|
STAT_SET_INT(SP2_WEAP_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[0])
|
|
STAT_SET_INT(SP2_WEAP_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[1])
|
|
|
|
STAT_SET_INT(SP2_WEAP_ADDON_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0])
|
|
STAT_SET_INT(SP2_WEAP_ADDON_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[1])
|
|
STAT_SET_INT(SP2_WEAP_ADDON_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[2])
|
|
STAT_SET_INT(SP2_WEAP_ADDON_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[3])
|
|
STAT_SET_INT(SP2_WEAP_ADDON_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[4])
|
|
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_0, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[0])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_1, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[1])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_2, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[2])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_3, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[3])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_4, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[4])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_5, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[5])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_6, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[6])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_7, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[7])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_8, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[8])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_9, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[9])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_10, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[10])
|
|
STAT_SET_INT(SP2_WEAP_TINT_PURCH_11, paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[11])
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
CDEBUG3LN(DEBUG_REPLAY, "Character ", iCharIndex, ":")
|
|
CDEBUG3LN(DEBUG_REPLAY, "WeaponBitset[0]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[0], " WeaponBitset[1]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponBitset[1])
|
|
CDEBUG3LN(DEBUG_REPLAY, "AddonBitset[0]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0], " AddonBitset[1]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[0])
|
|
CDEBUG3LN(DEBUG_REPLAY, "AddonBitset[2]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[2], " AddonBitset[3]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponAddonBitset[3])
|
|
CDEBUG3LN(DEBUG_REPLAY, "TintBitset[0]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[0], " TintBitset[1]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[1])
|
|
CDEBUG3LN(DEBUG_REPLAY, "TintBitset[2]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[2], " TintBitset[3]:", paramSnapshot.mPurchasedWeapons[iCharIndex].iWeaponTintBitset[3])
|
|
ENDREPEAT
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Uses the specified game state snapshot to restore player's weapons to the state they were in when the snapshot was taken
|
|
/// PARAMS:
|
|
/// paramSnapshot - the mission start or checkpoint snapshot
|
|
/// NOTES:
|
|
/// This restores the weapons in the snap shot
|
|
/// Be aware it writes to the same place where STORE_PLAYER_PED_WEAPONS() writes to.
|
|
PROC Restore_Game_State_Snapshot_Weapons(SNAPSHOT_STRUCT ¶mSnapshot)
|
|
INT iCharIndex
|
|
INT iTempIndex
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "-------------------------.")
|
|
CPRINTLN(DEBUG_REPLAY, "Restoring player weapons.")
|
|
|
|
// Restoring player character weapon loadouts to replay snapshot values.
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
g_savedGlobals.sPlayerData.sInfo.iArmour[iCharIndex] = paramSnapshot.iArmour[iCharIndex]
|
|
REPEAT NUM_PLAYER_PED_WEAPON_SLOTS iTempIndex
|
|
g_savedGlobals.sPlayerData.sInfo.sWeapons[iCharIndex].sWeaponInfo[iTempIndex] = paramSnapshot.mWeapons[iCharIndex].sWeaponInfo[iTempIndex]
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
CDEBUG3LN(DEBUG_REPLAY, "Character ", iCharIndex, ":")
|
|
CDEBUG3LN(DEBUG_REPLAY, "WeaponSlot: ", GET_DEBUG_STRING_FROM_WEAPONSLOT(GET_PLAYER_PED_WEAPON_SLOT_FROM_INT(iTempIndex)), " Weapon: ", GET_WEAPON_NAME(g_savedGlobals.sPlayerData.sInfo.sWeapons[iCharIndex].sWeaponInfo[iTempIndex].eWeaponType), " has ammo: ", g_savedGlobals.sPlayerData.sInfo.sWeapons[iCharIndex].sWeaponInfo[iTempIndex].iAmmoCount)
|
|
#ENDIF
|
|
ENDREPEAT
|
|
|
|
REPEAT NUMBER_OF_DLC_WEAPONS iTempIndex
|
|
g_savedGlobals.sPlayerData.sInfo.sWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex] = paramSnapshot.mWeapons[iCharIndex].sDLCWeaponInfo[iTempIndex]
|
|
ENDREPEAT
|
|
ENDREPEAT
|
|
|
|
// Restore purchased stat values (including weapon mods and addons).
|
|
Restore_Game_State_Snapshot_Purchased_Weapons(paramSnapshot)
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "-------------------------.")
|
|
ENDPROC
|
|
|
|
|
|
/// PURPOSE:
|
|
/// Changes the player to the character specified
|
|
/// PARAMS:
|
|
/// eCharacter - the character to change the player to
|
|
/// RETURNS:
|
|
/// TRUE if character was valid (michael, franklin or Trevor) FALSE otherwise
|
|
FUNC BOOL Replay_Change_Player_Ped(enumCharacterList eCharacter)
|
|
SELECTOR_SLOTS_ENUM replaySelectorPed
|
|
|
|
SWITCH(eCharacter)
|
|
CASE CHAR_MICHAEL
|
|
CPRINTLN(DEBUG_REPLAY, "Setting character to Michael.")
|
|
replaySelectorPed = SELECTOR_PED_MICHAEL
|
|
BREAK
|
|
|
|
CASE CHAR_FRANKLIN
|
|
CPRINTLN(DEBUG_REPLAY, "Setting character to Franklin.")
|
|
replaySelectorPed = SELECTOR_PED_FRANKLIN
|
|
BREAK
|
|
|
|
CASE CHAR_TREVOR
|
|
CPRINTLN(DEBUG_REPLAY, "Setting character to Trevor.")
|
|
replaySelectorPed = SELECTOR_PED_TREVOR
|
|
BREAK
|
|
|
|
DEFAULT
|
|
SCRIPT_ASSERT("Change_Player_Ped: Chosen character was invalid.")
|
|
RETURN FALSE
|
|
|
|
BREAK
|
|
ENDSWITCH
|
|
|
|
VECTOR vLastKnownCoords
|
|
FLOAT fLastKnownHead
|
|
INT iLastKnownRoomKey
|
|
|
|
#IF USE_CLF_DLC
|
|
enumCharacterList eCurrentCharacter = GET_CURRENT_PLAYER_PED_ENUMCLF()
|
|
IF eCurrentCharacter != NO_CHARACTER
|
|
vLastKnownCoords = g_savedGlobalsClifford.sPlayerData.sInfo.vLastKnownCoords[eCurrentCharacter]
|
|
fLastKnownHead = g_savedGlobalsClifford.sPlayerData.sInfo.fLastKnownHead[eCurrentCharacter]
|
|
iLastKnownRoomKey = g_savedGlobalsClifford.sPlayerData.sInfo.iLastKnownRoomKey[eCurrentCharacter]
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#IF USE_NRM_DLC
|
|
enumCharacterList eCurrentCharacter = GET_CURRENT_PLAYER_PED_ENUMNRM()
|
|
IF eCurrentCharacter != NO_CHARACTER
|
|
vLastKnownCoords = g_savedGlobalsnorman.sPlayerData.sInfo.vLastKnownCoords[eCurrentCharacter]
|
|
fLastKnownHead = g_savedGlobalsnorman.sPlayerData.sInfo.fLastKnownHead[eCurrentCharacter]
|
|
iLastKnownRoomKey = g_savedGlobalsnorman.sPlayerData.sInfo.iLastKnownRoomKey[eCurrentCharacter]
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#IF NOT USE_SP_DLC
|
|
enumCharacterList eCurrentCharacter = GET_CURRENT_PLAYER_PED_ENUM()
|
|
IF eCurrentCharacter != NO_CHARACTER
|
|
vLastKnownCoords = g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[eCurrentCharacter]
|
|
fLastKnownHead = g_savedGlobals.sPlayerData.sInfo.fLastKnownHead[eCurrentCharacter]
|
|
iLastKnownRoomKey = g_savedGlobals.sPlayerData.sInfo.iLastKnownRoomKey[eCurrentCharacter]
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
WHILE NOT SET_CURRENT_SELECTOR_PED(replaySelectorPed)
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
CPRINTLN(DEBUG_REPLAY, "Restore last known coords for ", GET_PLAYER_PED_STRING(eCurrentCharacter), " to ", vLastKnownCoords, ".")
|
|
|
|
#IF USE_CLF_DLC
|
|
IF eCurrentCharacter != NO_CHARACTER
|
|
g_savedGlobalsClifford.sPlayerData.sInfo.vLastKnownCoords[eCurrentCharacter] = vLastKnownCoords
|
|
g_savedGlobalsClifford.sPlayerData.sInfo.fLastKnownHead[eCurrentCharacter] = fLastKnownHead
|
|
g_savedGlobalsClifford.sPlayerData.sInfo.iLastKnownRoomKey[eCurrentCharacter] = iLastKnownRoomKey
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#IF USE_NRM_DLC
|
|
IF eCurrentCharacter != NO_CHARACTER
|
|
g_savedGlobalsnorman.sPlayerData.sInfo.vLastKnownCoords[eCurrentCharacter] = vLastKnownCoords
|
|
g_savedGlobalsnorman.sPlayerData.sInfo.fLastKnownHead[eCurrentCharacter] = fLastKnownHead
|
|
g_savedGlobalsnorman.sPlayerData.sInfo.iLastKnownRoomKey[eCurrentCharacter] = iLastKnownRoomKey
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
#IF NOT USE_SP_DLC
|
|
IF eCurrentCharacter != NO_CHARACTER
|
|
g_savedGlobals.sPlayerData.sInfo.vLastKnownCoords[eCurrentCharacter] = vLastKnownCoords
|
|
g_savedGlobals.sPlayerData.sInfo.fLastKnownHead[eCurrentCharacter] = fLastKnownHead
|
|
g_savedGlobals.sPlayerData.sInfo.iLastKnownRoomKey[eCurrentCharacter] = iLastKnownRoomKey
|
|
ENDIF
|
|
#ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
/// PURPOSE:
|
|
/// Uses the specified game state snapshot to restore variables to the state they were in when the snapshot was taken
|
|
/// PARAMS:
|
|
/// paramSnapshot - the mission start or checkpoint snapshot
|
|
PROC Restore_Game_State_Snapshot(SNAPSHOT_STRUCT ¶mSnapshot, BOOL paramSkipCharacterSwap = FALSE)
|
|
|
|
TIMEOFDAY mTextTime // used to remove text messages
|
|
|
|
// Setting clock time back to replay snapshot time.
|
|
SET_CLOCK_TIME( GET_TIMEOFDAY_HOUR(paramSnapshot.tTime),
|
|
GET_TIMEOFDAY_MINUTE(paramSnapshot.tTime),
|
|
GET_TIMEOFDAY_SECOND(paramSnapshot.tTime))
|
|
SET_CLOCK_DATE( GET_TIMEOFDAY_DAY(paramSnapshot.tTime),
|
|
GET_TIMEOFDAY_MONTH(paramSnapshot.tTime),
|
|
GET_TIMEOFDAY_YEAR(paramSnapshot.tTime))
|
|
|
|
SET_CURR_WEATHER_STATE(paramSnapshot.iPreviousWeather, paramSnapshot.iNextWeather, paramSnapshot.fWeatherInterp)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
STRING sWeather = GET_WEATHER_STRING_FROM_HASH(paramSnapshot.iPreviousWeather)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sWeather)
|
|
CPRINTLN(DEBUG_REPLAY,"Restoring previous weather as: ", sWeather)
|
|
ENDIF
|
|
sWeather = GET_WEATHER_STRING_FROM_HASH(paramSnapshot.iNextWeather)
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(sWeather)
|
|
CPRINTLN(DEBUG_REPLAY,"Restoring next weather as: ", sWeather)
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY,"Restoring weather interp as: ", paramSnapshot.fWeatherInterp)
|
|
#ENDIF
|
|
|
|
IF NOT paramSkipCharacterSwap
|
|
// Switching player character to char used to reach last checkpoint.
|
|
IF NOT Replay_Change_Player_Ped(paramSnapshot.eCharacter)
|
|
EXIT // invalid character, exit
|
|
ENDIF
|
|
|
|
// Restoring player character variations to replay snapshot values.
|
|
Restore_Game_State_Snapshot_Clothes(paramSnapshot)
|
|
|
|
// Restoring player character weapon loadouts to replay snapshot values.
|
|
Restore_Game_State_Snapshot_Weapons(paramSnapshot)
|
|
|
|
// Special ability
|
|
STAT_SET_INT(SP0_SPECIAL_ABILITY, paramSnapshot.iSpecialAbility[0])
|
|
STAT_SET_INT(SP1_SPECIAL_ABILITY, paramSnapshot.iSpecialAbility[1])
|
|
STAT_SET_INT(SP2_SPECIAL_ABILITY, paramSnapshot.iSpecialAbility[2])
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
UPDATE_SPECIAL_ABILITY_FROM_STAT(PLAYER_ID())
|
|
ENDIF
|
|
CPRINTLN(DEBUG_REPLAY, "Special Ability restored as M= ", paramSnapshot.iSpecialAbility[0], " F= ", paramSnapshot.iSpecialAbility[1], " T= ",paramSnapshot.iSpecialAbility[2])
|
|
|
|
// Restore text messages (remove any the player received after the snapshot timestamp)
|
|
INT iText = 0
|
|
FOR iText = 0 TO MAX_TEXT_MESSAGES -1
|
|
|
|
IF NOT IS_STRING_NULL_OR_EMPTY(g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgLabel)
|
|
AND (iText <= SP_TEXT_PORTION_END OR iText >= MP_TEXT_PORTION_START) //B* 2204796: Ignore buffered text messages
|
|
CDEBUG1LN( DEBUG_REPLAY, " - ###Text[", iText, "] - TxtMsgMonth(-1) = ", ( g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgMonth - 1 ), " - TxtMsgDay = ", g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgDay )
|
|
|
|
IF g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgDay = 31
|
|
//which iText are we using
|
|
CPRINTLN(DEBUG_REPLAY, "### iText = ",iText)
|
|
//text info
|
|
CPRINTLN(DEBUG_REPLAY, "### TxtMsgLabel = ",g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgLabel)
|
|
ENDIF
|
|
|
|
SET_TIMEOFDAY(mTextTime, g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgSecs,
|
|
g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgMins,
|
|
g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgHours,
|
|
g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgDay,
|
|
INT_TO_ENUM(MONTH_OF_YEAR, g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgMonth-1),
|
|
g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgTimeSent.TxtMsgYear)
|
|
|
|
|
|
IF IS_TIMEOFDAY_AFTER_TIMEOFDAY(mTextTime, paramSnapshot.tTime)
|
|
// text message was sent after the time the snapshot was taken...delete it!
|
|
CPRINTLN(DEBUG_REPLAY, "Unlocking and deleting text message ", g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgLabel)
|
|
UNLOCK_TEXT_MESSAGE_BY_LABEL(g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgLabel, TRUE)
|
|
DELETE_TEXT_MESSAGE_BY_LABEL_FROM_ALL_PLAYER_CHARACTERS(g_SavedGlobals.sTextMessageSavedData.g_TextMessage[iText].TxtMsgLabel)
|
|
|
|
#IF IS_DEBUG_BUILD
|
|
TEXT_LABEL_63 tTOD = TIMEOFDAY_TO_TEXT_LABEL(paramSnapshot.tTime)
|
|
CPRINTLN(DEBUG_REPLAY, "Snapshot TOD = ", tTOD)
|
|
TEXT_LABEL_63 tTDOText = TIMEOFDAY_TO_TEXT_LABEL(mTextTime)
|
|
CPRINTLN(DEBUG_REPLAY, "Text TOD = ", tTDOText)
|
|
#ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDFOR
|
|
|
|
// Don't show cash being updated
|
|
HIDE_HUD_COMPONENT_THIS_FRAME(NEW_HUD_CASH)
|
|
|
|
// updates that need to be done for all player characters
|
|
INT iCharIndex
|
|
INT iTransactionsAltered
|
|
INT iTempIndex
|
|
REPEAT NUM_OF_PLAYABLE_PEDS iCharIndex
|
|
|
|
// restore state of default player vehicles
|
|
g_savedGlobals.sPlayerData.sInfo.sPlayerVehicle[0][iCharIndex] = paramSnapshot.mPlayerVehicle[0][iCharIndex]
|
|
g_savedGlobals.sPlayerData.sInfo.sPlayerVehicle[1][iCharIndex] = paramSnapshot.mPlayerVehicle[1][iCharIndex]
|
|
|
|
// restoring bank accounts to stored values
|
|
CPRINTLN(DEBUG_REPLAY, "Restoring bank account for character: ", iCharIndex)
|
|
//CPRINTLN(DEBUG_REPLAY, "Current log is: ", g_BankAccounts[iCharIndex].iLogIndexPoint)
|
|
//CPRINTLN(DEBUG_REPLAY, "Target log is: ", paramSnapshot.iBankLogIndex[iCharIndex])
|
|
IF g_savedGlobals.sFinanceData.PLAYER_ACCOUNT_LOGS[iCharIndex].iLogIndexPoint <> paramSnapshot.iBankLogIndex[iCharIndex]
|
|
// need to undo transactions
|
|
WHILE g_savedGlobals.sFinanceData.PLAYER_ACCOUNT_LOGS[iCharIndex].iLogIndexPoint <> paramSnapshot.iBankLogIndex[iCharIndex]
|
|
AND iTransactionsAltered < MAX_BANK_ACCOUNT_LOG_ENTRIES // to stop us looping through repeatedly
|
|
UNDO_LAST_BANK_ACCOUNT_ACTION(iCharIndex)
|
|
iTransactionsAltered++
|
|
ENDWHILE
|
|
ELSE
|
|
//CPRINTLN(DEBUG_REPLAY, "No transactions to undo for this character", iCharIndex)
|
|
ENDIF
|
|
|
|
//CPRINTLN(DEBUG_REPLAY, "After undo logs: Current cash is now: ", g_BankAccounts[iCharIndex].iBalance)
|
|
|
|
INT iDiff = g_BankAccounts[iCharIndex].iBalance - paramSnapshot.iCash[iCharIndex]
|
|
IF iDiff <> 0
|
|
//CPRINTLN(DEBUG_REPLAY, "Final update to bank account ")
|
|
g_BankAccounts[INT_TO_ENUM(enumBankAccountName, iCharIndex)].iBalance = paramSnapshot.iCash[iCharIndex]//new total
|
|
BANK_FORCE_UPDATE_LINKED_ACCOUNT_STATS(INT_TO_ENUM(enumBankAccountName, iCharIndex))
|
|
ELSE
|
|
//CPRINTLN(DEBUG_REPLAY, "Account is correct")
|
|
ENDIF
|
|
//CPRINTLN(DEBUG_REPLAY, "Final update: Current cash is now: ", g_BankAccounts[iCharIndex].iBalance)
|
|
//CPRINTLN(DEBUG_REPLAY, "----------------------------------------------------------")
|
|
|
|
// tattoos
|
|
FOR iTempIndex = 0 TO MAX_NUMBER_OF_TATTOO_BITSETS -1
|
|
g_savedGlobals.sPlayerData.sTattoos[iCharIndex].iUnlockedTattoos[iTempIndex] = paramSnapshot.sTattoos[iCharIndex].iUnlockedTattoos[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sTattoos[iCharIndex].iViewedTattoos[iTempIndex] = paramSnapshot.sTattoos[iCharIndex].iViewedTattoos[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sTattoos[iCharIndex].iCurrentTattoos[iTempIndex] = paramSnapshot.sTattoos[iCharIndex].iCurrentTattoos[iTempIndex]
|
|
ENDFOR
|
|
|
|
// clothes
|
|
FOR iTempIndex = 0 TO PED_COMPONENT_USED_SLOT
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iHeadBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iHeadBitset0[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iBeardBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iBeardBitset0[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iHairBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iHairBitset0[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset1[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset2[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset2[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset3[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset3[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset4[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset4[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset5[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset5[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset6[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset6[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset7[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset7[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset8[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset8[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTorsoBitset9[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTorsoBitset9[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iLegsBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iLegsBitset1[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset2[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iLegsBitset2[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iLegsBitset3[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iLegsBitset3[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iHandBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iHandBitset0[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iFeetBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iFeetBitset1[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset2[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iFeetBitset2[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset3[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iFeetBitset3[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iFeetBitset4[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iFeetBitset4[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iTeethBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iTeethBitset0[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecialBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iSpecialBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecialBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iSpecialBitset1[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecialBitset2[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iSpecialBitset2[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iSpecial2Bitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iSpecial2Bitset0[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iDeclBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iDeclBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iDeclBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iDeclBitset1[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iJbibBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iJbibBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iJbibBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iJbibBitset1[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iOutfitBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iOutfitBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iOutfitBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iOutfitBitset1[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropGroupBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iPropGroupBitset0[iTempIndex]
|
|
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset0[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iPropsBitset0[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset1[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iPropsBitset1[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset2[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iPropsBitset2[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset3[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iPropsBitset3[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset4[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iPropsBitset4[iTempIndex]
|
|
g_savedGlobals.sPlayerData.sComponents[iCharIndex].iPropsBitset5[iTempIndex] = paramSnapshot.sComponents[iCharIndex].iPropsBitset5[iTempIndex]
|
|
ENDFOR
|
|
|
|
ENDREPEAT
|
|
|
|
//Restore current player character state.
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
IF IS_PLAYER_PED_PLAYABLE(GET_PLAYER_PED_ENUM(PLAYER_PED_ID()))
|
|
SET_PED_VARIATIONS(PLAYER_PED_ID(), g_sLastStoredPlayerPedClothes[GET_PLAYER_PED_ENUM(PLAYER_PED_ID())])
|
|
ENDIF
|
|
|
|
RESTORE_PLAYER_PED_ARMOUR(PLAYER_PED_ID())
|
|
RESTORE_PLAYER_PED_WEAPONS(PLAYER_PED_ID())
|
|
CLEAR_PED_WETNESS(PLAYER_PED_ID())
|
|
CLEAR_PED_BLOOD_DAMAGE(PLAYER_PED_ID())
|
|
RESET_PED_VISIBLE_DAMAGE(PLAYER_PED_ID())
|
|
|
|
IF HAS_PED_GOT_WEAPON(PLAYER_PED_ID(), paramSnapshot.mCurrentWeapon)
|
|
SET_CURRENT_PED_WEAPON(PLAYER_PED_ID(), paramSnapshot.mCurrentWeapon, TRUE)
|
|
ENDIF
|
|
|
|
SET_ENTITY_HEALTH(PLAYER_PED_ID(),GET_PED_MAX_HEALTH(PLAYER_PED_ID())) //Always set the player to full health.
|
|
|
|
IF IS_PLAYER_PLAYING(PLAYER_ID())
|
|
RESET_PLAYER_STAMINA(PLAYER_ID())
|
|
CPRINTLN(DEBUG_REPLAY, "Player stamina restored!")
|
|
ENDIF
|
|
|
|
RESTORE_PLAYER_PED_TATTOOS(PLAYER_PED_ID()) // clear decorations (scars) + restore tattoos
|
|
CPRINTLN(DEBUG_REPLAY, "Player character's state restored!")
|
|
ENDIF
|
|
ELSE
|
|
CPRINTLN(DEBUG_REPLAY, "Skipped restoring character state.")
|
|
ENDIF
|
|
|
|
//Allow all savehouse vehicles to respawn immediately.
|
|
CPRINTLN(DEBUG_REPLAY, "Resetting safehouse vehicle gens.")
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_MICHAEL_SAVEHOUSE)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_MICHAEL_SAVEHOUSE_COUNTRY)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_FRANKLIN_SAVEHOUSE_CAR)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_FRANKLIN_SAVEHOUSE_BIKE)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_FRANKLIN_SAVEHOUSE_HILLS_CAR)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_FRANKLIN_SAVEHOUSE_HILLS_BIKE)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_TREVOR_SAVEHOUSE_COUNTRY)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_TREVOR_SAVEHOUSE_CITY)
|
|
CLEAR_MUST_LEAVE_AREA_VEHICLE_GEN_FLAG(VEHGEN_TREVOR_SAVEHOUSE_STRIPCLUB)
|
|
|
|
//Reset the players last known ped info
|
|
ResetLastKnownPedInfo(g_savedGlobals.sPlayerData.sInfo, SP_MISSION_NONE)
|
|
ENDPROC
|
|
|
|
FUNC BOOL START_UP_SHAPETEST(VECTOR vStartPos, FLOAT fStartHeading, MODEL_NAMES model = DUMMY_MODEL_FOR_SCRIPT, bool bExcludePlayer = TRUE, BOOL bIsBigModel = FALSE)
|
|
|
|
IF NOT IS_PED_INJURED(PLAYER_PED_ID())
|
|
|
|
IF model = DUMMY_MODEL_FOR_SCRIPT
|
|
model = GET_ENTITY_MODEL(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
ENTITY_INDEX excludeIndex = PLAYER_PED_ID()
|
|
INT includeFlags = LOS_FLAGS_BOUNDING_BOX
|
|
IF NOT bExcludePlayer
|
|
excludeIndex = NULL
|
|
includeFlags = LOS_FLAGS_BOUNDING_BOX
|
|
ENDIF
|
|
|
|
INT iReturnValue = -1
|
|
VECTOR vTempMin, vTempMax, vHitPos, vHitNorm
|
|
SHAPETEST_INDEX shapeTestIndex
|
|
ENTITY_INDEX entityHit
|
|
GET_MODEL_DIMENSIONS(model, vTempMin, vTempMax)
|
|
IF bIsBigModel //Increase the box size by 25% for big models
|
|
vTempMin = vTempMin * 1.25
|
|
vTempMax = vTempMax * 1.25
|
|
ENDIF
|
|
|
|
vtempMax -= vTempMin
|
|
shapeTestIndex = START_SHAPE_TEST_BOX(vStartPos - <<0,0,vTempMin.z>>,vTempMax,<<0.0,0.0,fStartHeading>>,DEFAULT, includeFlags, excludeIndex)
|
|
CDEBUG3LN(debug_replay,"doing shapetest at ",vStartPos, " size ",vTempMax)
|
|
|
|
SHAPETEST_STATUS stResult = GET_SHAPE_TEST_RESULT(shapeTestIndex,iReturnValue,vHitPos,vHitNorm,entityHit)
|
|
WHILE stResult = SHAPETEST_STATUS_RESULTS_NOTREADY
|
|
WAIT(0)
|
|
stResult = GET_SHAPE_TEST_RESULT(shapeTestIndex,iReturnValue,vHitPos,vHitNorm,entityHit)
|
|
ENDWHILE
|
|
|
|
IF stResult = SHAPETEST_STATUS_RESULTS_READY
|
|
CDEBUG3LN(debug_replay,"Shapetest result: hitPos:",vHitPos," hitNorm:",vHitNorm, " entity:",NATIVE_TO_INT(entityHit))
|
|
IF iReturnValue != 0
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
ENDIF
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|
|
|
|
FUNC BOOL IS_EXCLUDED_ROAD_NODE(VECTOR pos, BOOL bIsBigModel = FALSE, INT iNumOfLanes = 0)
|
|
IF bIsBigModel
|
|
//Only use roads with at least 2 lanes
|
|
IF iNumOfLanes < 2
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
//Wide area checks - Pier
|
|
IF VDIST2(pos,<<-1601.68, -1013.90, 12.02>>) < (53 * 53)
|
|
OR VDIST2(pos,<<-1645.58, -1065.69, 17.53>>) < (53 * 53)
|
|
OR VDIST2(pos,<<-1688.35, -1118.13, 12.15>>) < (53 * 53)
|
|
OR VDIST2(pos,<<-1751.62, -1133.60, 12.09>>) < (53 * 53)
|
|
//Around <<-150.30, 969.48, 234.61>>
|
|
OR VDIST2(pos,<<-150.30, 969.48, 234.61>>) < (400) //20 radius
|
|
OR VDIST2(pos,<<-160.50, 1006.18, 233.11>>) < (400)
|
|
OR VDIST2(pos,<<-215.49, 887.98, 207.17>>) < (400)
|
|
OR VDIST2(pos,<<-186.37, 830.33, 202.51>>) < (400)
|
|
OR VDIST2(pos,<<-114.10, 784.55, 201.24>>) < (400)
|
|
OR VDIST2(pos,<<-140.14, 910.92, 237.18>>) < (400)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
|
|
IF ARE_VECTORS_ALMOST_EQUAL(pos,<< 24.2857, -663.82, 31.6286 >>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<< -73.2402, -682.619, 32.6686 >>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<20.6539, -673.9974, 31.3274>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<17.0277, -679.2629, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<13.0123, -681.9813, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<9.3300, -683.0215, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<-3.0009, -684.3066, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<-15.2584, -685.2630, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<-27.7868, -686.3926, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<-40.3021, -687.2850, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<-44.0514, -687.7671, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<-49.7120, -688.2113, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<<-57.6906, -686.7383, 31.3381>>,1)
|
|
OR ARE_VECTORS_ALMOST_EQUAL(pos,<< 1643.25, 20.25, 169.531 >>,1)
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
//Road nodes under the ground Z
|
|
FLOAT fGround
|
|
GET_GROUND_Z_FOR_3D_COORD(pos+<<0,0,10>>,fGround)
|
|
|
|
IF pos.z < fGround - 0.1
|
|
CERRORLN(debug_director, "Road node Z(",pos.z,") is UNDER the ground Z(",fGround,"), this will cause problems!")
|
|
RETURN TRUE
|
|
ENDIF
|
|
|
|
RETURN FALSE
|
|
ENDFUNC
|
|
/// PURPOSE:
|
|
/// Returns a position around a given point going through a spiral pattern
|
|
/// PARAMS:
|
|
/// vPos - Centre of search area
|
|
/// vReturn - Returned vector, if anything found
|
|
/// iIndex - point index, should be defined just outside the loop
|
|
/// ipointsPerArm - #point per arm (i.e. 1st ring has points 8 points, 0-7, 2nd has 8-15, and so on)
|
|
/// fRadius - Maximum search radius, returns false if current point falls outside
|
|
/// fRingDist - distance between concentric rings
|
|
/// RETURNS:
|
|
///
|
|
FUNC BOOL GET_POSITION_IN_SPIRAL_AROUND_POINT(VECTOR vPos, VECTOR &vReturn, INT &iIndex, INT ipointsPerArm = 8, FLOAT fRadius = 100.0, FLOAT fRingDist = 0.5)
|
|
//Get the current point position
|
|
INT iDist = iIndex / iPointsPerArm
|
|
INT iPoint = iIndex % iPointsPerArm
|
|
|
|
//Check if it falls outside the max radius
|
|
FLOAT fDist = iDist * fRingDist
|
|
IF fDist > fRadius
|
|
// CPRINTLN(debug_dan,"Current point ",iIndex," outside of max search range")
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
//check if its index is > max number of points
|
|
IF iIndex > iPointsPerArm * fRadius / fRingDist
|
|
// CPRINTLN(debug_dan,"Current point ",iIndex," higher than the max for the given range: ",iPointsPerArm * fRadius / fRingDist)
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
//Calculate point angle
|
|
FLOAT theta = 360.0 / iPointsPerArm * iPoint
|
|
// CPRINTLN(debug_dan,iIndex,": Theta is ",theta)
|
|
|
|
//Calculate point deltas
|
|
FLOAT fdx = COS(theta) * fRingDist * (iDist +1)
|
|
FLOAT fdy = SIN(theta) * fRingDist * (iDist +1)
|
|
|
|
vReturn = vPos + <<fdx,fdy,0>>
|
|
iIndex ++
|
|
|
|
RETURN TRUE
|
|
ENDFUNC
|
|
|
|
FUNC BOOL START_UP_ROAD_NODE_TEST(VECTOR &vStartPos, FLOAT &fStartHeading, MODEL_NAMES model = DUMMY_MODEL_FOR_SCRIPT,
|
|
BOOL bExcludeInteriorNodes = FALSE, bool bExcludePlayer = TRUE, FLOAT fRodeNodeDistModifier = 1.0)
|
|
|
|
INT iNodeIterator = 1
|
|
INT iNumOfLanes
|
|
INT iTemp = 0
|
|
FLOAT fRotTemp
|
|
VECTOR vPosTemp, vPosTemp2
|
|
BOOL b2ndCheckPassed
|
|
BOOL bIsBigModel
|
|
|
|
FLOAT fRoadeNodeLoadDist = TO_FLOAT( DEFAULT_ROAD_NODE_LOAD_DIST ) * fRodeNodeDistModifier
|
|
|
|
IF model = DUMMY_MODEL_FOR_SCRIPT
|
|
model = GET_ENTITY_MODEL(PLAYER_PED_ID())
|
|
ENDIF
|
|
|
|
//Get model's dimensions, check if large vehicle
|
|
VECTOR vModelMin, vModelMax
|
|
GET_MODEL_DIMENSIONS(model, vModelMin, vModelMax)
|
|
vModelMax = vModelMax - vModelMin //Use vModelMax as total model size
|
|
bIsBigModel = IS_THIS_MODEL_A_BOAT(model) OR IS_THIS_MODEL_A_HELI(model) OR IS_THIS_MODEL_A_PLANE(model) OR IS_THIS_MODEL_A_TRAIN(model)
|
|
OR (vModelMax.x > 6 OR vmodelMax.y > 6 OR vModelMax.z > 6)
|
|
|
|
REQUEST_PATH_NODES_IN_AREA_THIS_FRAME(vStartPos.X-fRoadeNodeLoadDist, vStartPos.Y-fRoadeNodeLoadDist,
|
|
vStartPos.X+fRoadeNodeLoadDist, vStartPos.Y+fRoadeNodeLoadDist)
|
|
|
|
INT timer = GET_GAME_TIMER()
|
|
|
|
WHILE NOT ARE_NODES_LOADED_FOR_AREA(vStartPos.X-fRoadeNodeLoadDist, vStartPos.Y-fRoadeNodeLoadDist,
|
|
vStartPos.X+fRoadeNodeLoadDist, vStartPos.Y+fRoadeNodeLoadDist)
|
|
AND GET_GAME_TIMER() - timer < 5000 // Fail safe for soft crash to drop out of while if stuck for > 5 seconds. B* 2314430
|
|
WAIT(0)
|
|
ENDWHILE
|
|
|
|
CPRINTLN(DEBUG_REPLAY, " snapshot_private - START_UP_ROAD_NODE_TEST - ARE_NODES_LOADED_FOR_AREA: PASSED OR timer buffer exceed: ",GET_GAME_TIMER() - timer," /5 seconds")
|
|
|
|
IF IS_THIS_MODEL_A_BOAT(model) OR IS_THIS_MODEL_A_JETSKI(model)
|
|
//Special model checks
|
|
OR model = SUBMERSIBLE OR model = SUBMERSIBLE2
|
|
iNodeIterator = 0
|
|
vModelMax.x = vModelMax.x /2
|
|
vModelMax.y = vModelMax.y /2
|
|
vModelMax.z = 0
|
|
|
|
FLOAT fVehicleArea = VMAG(vModelMax)
|
|
FLOAT fTestHeight, fGroundZ
|
|
CPRINTLN(DEBUG_REPLAY, " snapshot_private - START_UP_ROAD_NODE_TEST - This is a boat, looking for water nodes at ",vstartPos, " with model surface ",fVehicleArea)
|
|
WHILE GET_POSITION_IN_SPIRAL_AROUND_POINT(vStartPos,vPosTemp,iNodeIterator,16,300,3.0)
|
|
IF TEST_VERTICAL_PROBE_AGAINST_ALL_WATER(vPosTemp + <<0,0,100>>,SCRIPT_INCLUDE_OBJECT|SCRIPT_INCLUDE_GLASS|SCRIPT_INCLUDE_MOVER|SCRIPT_INCLUDE_VEHICLE,fTestHeight) = SCRIPT_WATER_TEST_RESULT_WATER
|
|
vPosTemp.z = fTestHeight
|
|
GET_GROUND_Z_FOR_3D_COORD(vPosTemp+<<0,0,100>>,fGroundZ)
|
|
IF fGroundZ <= vPosTemp.z
|
|
//2nd area check
|
|
b2ndcheckPassed = TRUE
|
|
iTemp = 0
|
|
WHILE GET_POSITION_IN_SPIRAL_AROUND_POINT(vPosTemp, vPosTemp2,iTemp,16,fVehicleArea,0.3)
|
|
IF TEST_VERTICAL_PROBE_AGAINST_ALL_WATER(vPosTemp2+<<0,0,10>>,SCRIPT_INCLUDE_OBJECT|SCRIPT_INCLUDE_GLASS|SCRIPT_INCLUDE_MOVER|SCRIPT_INCLUDE_VEHICLE,fTestHeight) = SCRIPT_WATER_TEST_RESULT_WATER
|
|
vPosTemp2.z = fTestHeight
|
|
GET_GROUND_Z_FOR_3D_COORD(vPosTemp2+<<0,0,10>>,fGroundZ)
|
|
IF fGroundZ > vPosTemp2.z
|
|
b2ndCheckPassed = FALSE
|
|
ENDIF
|
|
ELSE
|
|
b2ndCheckPassed = FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
IF b2ndCheckPassed
|
|
CPRINTLN(DEBUG_REPLAY,"START_UP_ROAD_NODE_TEST: 2nd check passed for vehicle water spawn at ",vPosTemp)
|
|
IF START_UP_SHAPETEST(vPosTemp, fRotTemp, model, bExcludePlayer)
|
|
vStartPos = vPosTemp
|
|
fStartHeading = fRotTemp
|
|
CPRINTLN(DEBUG_REPLAY, " snapshot_private - : in water vStartPos = ", vStartPos)
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDIF
|
|
ENDWHILE
|
|
RETURN FALSE
|
|
ENDIF
|
|
|
|
WHILE GET_NTH_CLOSEST_VEHICLE_NODE_WITH_HEADING(vStartPos,iNodeIterator,vPosTemp,fRotTemp,iNumOfLanes)
|
|
IF VDIST2(vStartPos, vPosTemp) <= (fRoadeNodeLoadDist * fRoadeNodeLoadDist)
|
|
IF NOT (bExcludeInteriorNodes AND IS_VALID_INTERIOR(GET_INTERIOR_AT_COORDS(vPosTemp)))
|
|
AND NOT IS_EXCLUDED_ROAD_NODE(vPosTemp, bIsBigModel, iNumOfLanes)
|
|
IF START_UP_SHAPETEST(vPosTemp, fRotTemp, model, bExcludePlayer, bIsBigModel)
|
|
CPRINTLN(DEBUG_REPLAY, "Found valid road node at ", vPosTemp)
|
|
vStartPos = vPosTemp
|
|
fStartHeading = fRotTemp
|
|
RETURN TRUE
|
|
ENDIF
|
|
ENDIF
|
|
iNodeIterator++
|
|
ELSE
|
|
RETURN FALSE
|
|
ENDIF
|
|
ENDWHILE
|
|
|
|
RETURN FALSE
|
|
|
|
ENDFUNC
|