Files
gtav-src/script/dev_ng/singleplayer/include/public/scrap_common.sch
T
2025-09-29 00:52:08 +02:00

697 lines
23 KiB
Scheme
Executable File

// *****************************************************************************************
// *****************************************************************************************
//
// FILE NAME : scrap_common.sch
// AUTHOR : Aaron Gandaa
//
// *****************************************************************************************
// *****************************************************************************************
//----------------------
// INCLUDES
//----------------------
USING "RC_Helper_Functions.sch"
USING "common_packages.sch"
USING "CompletionPercentage_public.sch"
//----------------------
// CONSTS
//----------------------
CONST_INT SCRAPS_TO_CHECK_PER_FRAME 1
CONST_FLOAT PICKUP_HACK_DISTANCE 5.0 //so the Player can collect pickups in a submersible
//----------------------
// STRUCTS
//----------------------
STRUCT SCRAP_COLLECT_DATA
INT iScrap0to31 = 0 // Bitfields storing whether scraps 0 to 63 have been picked up
INT iScrap32to63 = 0 // Not used for spaceship and letter scraps as these are globally stored for Chop
INT iPackNumBase = 0 // Index in the pack stat bools for the start of the array
INT iMaxScraps = 0 // Maximum number of scraps to collect
INT iScrapsCollected = 0 // Total number of scraps that have been collected
ENDSTRUCT
STRUCT SCRAP_MISSION_DATA
SCRAP_MISSION missionType // Spaceship, letter scrap, etc.
SCRAP_COLLECT_DATA scrapData // Scrap collection data
STATSENUM packageStat // Hidden package stat
MODEL_NAMES packageMdl // Model type for pickup
STRING sScrapGetMsg // Message upon collecting a scrap
INT iMessageTimer = 0
INT iCurrentCheckIndex = 0 // Current scrap being checked
BOOL bDisplayMessage = FALSE
BOOL bMessageOnDisplay
ENDSTRUCT
//----------------------
// FUNCTIONS
//----------------------
BOOL bShowScrapDebugTTY = TRUE
BOOL bUseQuickScrapCollectCheck = TRUE
//----------------------
// FUNCTIONS
//----------------------
/// PURPOSE:
/// Checks to see if a pickup has been collected whilst the Player is in a vehicle like a submersible.
/// Since pickup collection doesn't work with a vehicle we have to check for distance instead
/// PARAMS:
/// thePickup - the pickup to check
/// RETURNS:
/// true if scrap has been collected whilst in a water vehicle
FUNC BOOL HAS_PLAYER_COLLECTED_PICKUP_IN_WATER_VEHICLE(PICKUP_INDEX thePickup)
IF NOT DOES_PICKUP_EXIST(thePickup)
RETURN FALSE
ENDIF
IF IS_ENTITY_ALIVE(PLAYER_PED_ID())
IF IS_PED_IN_ANY_VEHICLE(PLAYER_PED_ID())
// Get player vehicle
VEHICLE_INDEX tmpVehicle
MODEL_NAMES tmpModel
tmpVehicle = GET_VEHICLE_PED_IS_IN(PLAYER_PED_ID())
tmpModel = GET_ENTITY_MODEL(tmpVehicle)
IF tmpModel = SUBMERSIBLE
OR tmpModel = SUBMERSIBLE2
IF VDIST2(GET_ENTITY_COORDS(PLAYER_PED_ID()), GET_PICKUP_COORDS(thePickup)) < (PICKUP_HACK_DISTANCE * PICKUP_HACK_DISTANCE)
OR IS_ENTITY_TOUCHING_ENTITY(PLAYER_PED_ID(), GET_PICKUP_OBJECT(thePickup)) // Added because the sub2 has bits that stick out >5m from player coords
RETURN TRUE
ENDIF
ENDIF
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
// Print a message stating how many signs have been destroyed if this is needed...
// Now using the Midsized message UI as per Les request
/// PARAMS:
// data - contains needed data
// iMessageStage - the stage of the message displaying (for the case statement)
// siMessage - scaleform index
// sTitle - the message string to display (e.g so many scraps collected/ destroyed)
PROC UPDATE_DISPLAY_MESSAGE(BOOL &bDisplayMessage, BOOL &bMessageOnDisplay, INT &iMessageTimer, SCRAP_MISSION missionType, INT &iMessageStage, SCALEFORM_INDEX &siMessage, STRING sTitle, STRING sScrapGetMsg)
INT iSplashSoundID
//Failsafe: set this flag false at the beginning
SET_COLLECTED_SCREEN_DISPLAYING(FALSE)
IF bDisplayMessage
SWITCH iMessageStage
CASE 0
siMessage = REQUEST_SCALEFORM_MOVIE("MIDSIZED_MESSAGE")
IF HAS_SCALEFORM_MOVIE_LOADED(siMessage)
iSplashSoundID = GET_SOUND_ID()
IF missionType = SCRAP_PEYOTE
PLAY_SOUND_FRONTEND(iSplashSoundID, "PEYOTE_COMPLETED", "HUD_AWARDS")
ELSE
PLAY_SOUND_FRONTEND(iSplashSoundID, "COLLECTED", "HUD_AWARDS")
ENDIF
iMessageStage++
ENDIF
BREAK
CASE 1
BEGIN_SCALEFORM_MOVIE_METHOD(siMessage, "SHOW_SHARD_MIDSIZED_MESSAGE")
BEGIN_TEXT_COMMAND_SCALEFORM_STRING(sTitle)
END_TEXT_COMMAND_SCALEFORM_STRING()
BEGIN_TEXT_COMMAND_SCALEFORM_STRING(sScrapGetMsg)
ADD_TEXT_COMPONENT_INTEGER(GET_NUM_SCRAPS_SORTED(missionType))
END_TEXT_COMMAND_SCALEFORM_STRING()
END_SCALEFORM_MOVIE_METHOD()
iMessageTimer = GET_GAME_TIMER()
iMessageStage++
BREAK
CASE 2
IF (GET_GAME_TIMER() - iMessageTimer) > DEFAULT_GOD_TEXT_TIME - 500
BEGIN_SCALEFORM_MOVIE_METHOD(siMessage, "SHARD_ANIM_OUT")
SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(ENUM_TO_INT(HUD_COLOUR_WHITE))
SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(0.33)
END_SCALEFORM_MOVIE_METHOD()
iMessageStage++
ELSE
IF NOT IS_RESULT_SCREEN_DISPLAYING()
IF HAS_SCALEFORM_MOVIE_LOADED(siMessage)
SET_COLLECTED_SCREEN_DISPLAYING(TRUE)
DRAW_SCALEFORM_MOVIE_FULLSCREEN(siMessage, 100, 100, 100, 255 )
ENDIF
ENDIF
ENDIF
BREAK
CASE 3
IF (GET_GAME_TIMER() - iMessageTimer) > DEFAULT_GOD_TEXT_TIME
iMessageStage++
ELSE
IF NOT IS_RESULT_SCREEN_DISPLAYING()
IF HAS_SCALEFORM_MOVIE_LOADED(siMessage)
SET_COLLECTED_SCREEN_DISPLAYING(TRUE)
DRAW_SCALEFORM_MOVIE_FULLSCREEN(siMessage, 100, 100, 100, 255 )
ENDIF
ENDIF
ENDIF
BREAK
CASE 4
IF HAS_SCALEFORM_MOVIE_LOADED(siMessage)
SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(siMessage)
ENDIF
SET_COLLECTED_SCREEN_DISPLAYING(FALSE)
bMessageOnDisplay = FALSE
bDisplayMessage = FALSE
iMessageStage = 0
BREAK
ENDSWITCH
ENDIF
ENDPROC
PROC CALCULATE_TOTAL_HIDDEN_PACKAGES_COLLECTED_PERCENTAGE()
INT iValue
INT iTotalGot, iTotal
INT iPercent = 0
//Get stats and update collected scap achievement
STAT_GET_INT(GET_HIDDEN_PACKAGES_NUM(SCRAP_SHIP), iValue) iTotalGot += iValue // Spaceship Parts
IF iValue>0
SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH15),iValue)
ENDIF
STAT_GET_INT(GET_HIDDEN_PACKAGES_NUM(SCRAP_LETTER), iValue) iTotalGot += iValue // Letter Scraps
IF iValue>0
SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH16),iValue)
ENDIF
STAT_GET_INT(GET_HIDDEN_PACKAGES_NUM(SCRAP_SUB), iValue) iTotalGot += iValue // Submarine parts
IF iValue>0
SET_ACHIEVEMENT_PROGRESS_SAFE(ENUM_TO_INT(ACH17),iValue)
ENDIF
iTotal = GET_NUM_PARTS(SCRAP_SHIP) + GET_NUM_PARTS(SCRAP_LETTER) + GET_NUM_PARTS(SCRAP_SUB)
IF (iTotal > 0)
iPercent = (iTotalGot * 100) / iTotal
ENDIF
STAT_SET_INT(PERCENT_HIDDEN_PACKAGES, iPercent)
ENDPROC
/// PURPOSE:
/// Checks to see if a scrap from a list has been collected
/// PARAMS:
/// list - scrap list reference
/// index - index to check
/// RETURNS:
/// true if scrap has been collected
FUNC BOOL HAS_SCRAP_BEEN_COLLECTED(SCRAP_COLLECT_DATA &list, INT index)
IF (index < 0) OR (index >= 64)
SCRIPT_ASSERT("SCRAP INDEX IS INVALID!!")
RETURN FALSE
ENDIF
// if scrap index is 31 or less use first int
IF (index <= 31)
RETURN IS_BIT_SET(list.iScrap0to31, index)
ENDIF
// else take 32 from index and use second int
RETURN IS_BIT_SET(list.iScrap32to63, index - 32)
ENDFUNC
/// PURPOSE:
/// Marks a scrap in the list as collected
/// PARAMS:
/// collectData - scrap list reference
/// index - index to mark
/// bCollected - set this as true to mark is collected, false to uncollect
PROC SET_SCRAP_AS_COLLECTED(SCRAP_COLLECT_DATA &collectData, INT index, BOOL bCollected=TRUE)
IF (index < 0) OR (index >= 64)
SCRIPT_ASSERT("SET_SCRAP_AS_COLLECTED - SCRAP INDEX IS INVALID!!!")
EXIT
ENDIF
// If scrap index is 31 or less use first int
IF (index <= 31)
IF (bCollected)
SET_BIT(collectData.iScrap0to31, index)
ELSE
CLEAR_BIT(collectData.iScrap0to31, index)
ENDIF
EXIT
ENDIF
// Otherwise take 32 from index and use second int
IF (bCollected)
SET_BIT(collectData.iScrap32to63, index - 32)
ELSE
CLEAR_BIT(collectData.iScrap32to63, index - 32)
ENDIF
ENDPROC
/// PURPOSE:
/// Update global bitsets for Chop
/// Current duplicate bitsets for letter scraps and spaceship parts
/// Ambient script will check locals - Chop will access the globals - not ideal, but simplest for now
/// To be improved..
PROC UPDATE_GLOBAL_SCRAP_DATA(SCRAP_MISSION missionType, INT index, BOOL bCollected=TRUE)
IF (index < 0) OR (index >= 64)
SCRIPT_ASSERT("UPDATE_GLOBAL_SCRAP_DATA - SCRAP INDEX IS INVALID!!!")
EXIT
ENDIF
// Letter scraps
IF missionType = SCRAP_LETTER
IF (index <= 31)
IF (bCollected)
SET_BIT(g_savedGlobals.sAmbient.sLetterScrapData.iScrap0to31, index)
ELSE
CLEAR_BIT(g_savedGlobals.sAmbient.sLetterScrapData.iScrap0to31, index)
ENDIF
EXIT
ENDIF
IF (bCollected)
SET_BIT(g_savedGlobals.sAmbient.sLetterScrapData.iScrap32to63, index - 32)
ELSE
CLEAR_BIT(g_savedGlobals.sAmbient.sLetterScrapData.iScrap32to63, index - 32)
ENDIF
// Spaceship parts
ELIF missionType = SCRAP_SHIP
IF (index <= 31)
IF (bCollected)
SET_BIT(g_savedGlobals.sAmbient.sSpaceshipPartData.iScrap0to31, index)
ELSE
CLEAR_BIT(g_savedGlobals.sAmbient.sSpaceshipPartData.iScrap0to31, index)
ENDIF
EXIT
ENDIF
IF (bCollected)
SET_BIT(g_savedGlobals.sAmbient.sSpaceshipPartData.iScrap32to63, index - 32)
ELSE
CLEAR_BIT(g_savedGlobals.sAmbient.sSpaceshipPartData.iScrap32to63, index - 32)
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// This looks at the packed stats and fills the scrap list from it
/// PARAMS:
/// list - scrap list reference
/// iStatPackIndex - first index of the stats to use - eg for letter scraps use PACKSTAT_LETTER_START
/// iMaxScraps - the total number of scraps to collect, so for letter scraps this would be 50
PROC SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS(SCRAP_COLLECT_DATA &list, INT iStatPackIndex, INT iMaxScraps)
INT i
INT cnt = 0
// clear scrap list - we'll fill these from packed stats in a second
list.iScrap0to31 = 0
list.iScrap32to63 = 0
// set max scraps and stat packed list index
list.iPackNumBase = iStatPackIndex
list.iMaxScraps = iMaxScraps
// fill scrap array from stats
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Checking Scrap List From Stats - Stat Index Base:", list.iPackNumBase, " Max Scraps:", list.iMaxScraps)
ENDIF
REPEAT list.iMaxScraps i
IF GET_PACKED_STAT_BOOL(INT_TO_ENUM(STATS_PACKED, list.iPackNumBase + i))
cnt ++
SET_SCRAP_AS_COLLECTED(list, i)
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Scrap Index: ", i, " has been collected.")
ENDIF
ENDIF
ENDREPEAT
list.iScrapsCollected = cnt
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Number of Scraps Collected: ", cnt)
CPRINTLN(DEBUG_AMBIENT, "Number of Scraps Remaining: ", list.iMaxScraps - cnt)
ENDIF
ENDPROC
/// PURPOSE:
/// This sets packed stats from a scrap collect list
/// Make sure list.iPackNumBase and list.iMaxScraps has been set before using this
/// PARAMS:
/// list -
PROC SET_PACKED_STATS_FROM_SCRAP_COLLECT_DATA(SCRAP_COLLECT_DATA &list)
INT i
INT cnt = 0
IF (list.iMaxScraps <= 0)
SCRIPT_ASSERT("list.iMaxScraps is invalid - set this using SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS()")
ENDIF
IF (list.ipackNumBase <= 0)
SCRIPT_ASSERT("list.ipackNumBase is invalid - set this using SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS()")
ENDIF
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Checking Scrap List From Scrap List - Stat Index Base:", list.iPackNumBase, " Max Scraps:", list.iMaxScraps)
ENDIF
REPEAT list.iMaxScraps i
IF HAS_SCRAP_BEEN_COLLECTED(list, i)
cnt ++
SET_PACKED_STAT_BOOL(INT_TO_ENUM(STATS_PACKED, list.ipackNumBase + i), TRUE)
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Scrap Index: ", i, " has been collected.")
ENDIF
ENDIF
ENDREPEAT
list.iScrapsCollected = cnt
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Number of Scraps Collected: ", cnt)
CPRINTLN(DEBUG_AMBIENT, "Number of Scraps Remaining: ", list.iMaxScraps - cnt)
ENDIF
//Activate Dreyfus mission as soon as all are collected
IF (cnt=list.iMaxScraps) AND (list.ipackNumBase = PACKSTAT_LETTER_START)
Execute_Code_ID(CID_DREYFUSS1_COMPLETE_LETTER_SCRAPS, 0)
ENDIF
ENDPROC
/// PURPOSE:
/// This sets packed stats from a scrap collect list
/// Make sure list.iPackNumBase and list.iMaxScraps has been set before using this
/// PARAMS:
/// list -
PROC SET_SINGLE_PACKED_STAT_FROM_SCRAP_COLLECT_DATA(SCRAP_COLLECT_DATA &list, INT iIndex)
CPRINTLN(DEBUG_AMBIENT, "SET_SINGLE_PACKED_STAT_FROM_SCRAP_COLLECT_DATA - ", iIndex)
IF (list.iMaxScraps <= 0)
SCRIPT_ASSERT("list.iMaxScraps is invalid - set this using SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS()")
ENDIF
IF (list.ipackNumBase <= 0)
SCRIPT_ASSERT("list.ipackNumBase is invalid - set this using SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS()")
ENDIF
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Checking Scrap List From Scrap List - Stat Index Base:", list.iPackNumBase, " Max Scraps:", list.iMaxScraps)
ENDIF
IF (iIndex >= list.iMaxScraps)
SCRIPT_ASSERT("trying to pass in an index which is bigger than the maximum number of scraps")
ENDIF
IF HAS_SCRAP_BEEN_COLLECTED(list, iIndex)
list.iScrapsCollected ++
SET_PACKED_STAT_BOOL(INT_TO_ENUM(STATS_PACKED, list.ipackNumBase + iIndex), TRUE)
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Scrap Index: ", iIndex, " has been collected.")
ENDIF
ENDIF
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "Number of Scraps Collected: ", list.iScrapsCollected)
CPRINTLN(DEBUG_AMBIENT, "Number of Scraps Remaining: ", list.iMaxScraps - list.iScrapsCollected)
ENDIF
//Activate Dreyfus mission as soon as all are collected
IF (list.iScrapsCollected=list.iMaxScraps) AND (list.ipackNumBase = PACKSTAT_LETTER_START)
Execute_Code_ID(CID_DREYFUSS1_COMPLETE_LETTER_SCRAPS, 0)
ENDIF
ENDPROC
/// PURPOSE:
/// Checks to see if all scrap from a list has been collected
/// SET_PACKED_STATS_FROM_SCRAP_COLLECT_DATA() or SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS()
/// should called at least once before using this...
/// PARAMS:
/// list - script reference
/// RETURNS:
/// true if scrap has been collected
FUNC BOOL HAVE_ALL_SCRAPS_BEEN_COLLECTED(SCRAP_COLLECT_DATA &list)
IF (list.iMaxScraps <= 0)
SCRIPT_ASSERT("list.iMaxScraps is invalid - call this SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS() or SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS() at least once before using this")
ENDIF
RETURN (list.iScrapsCollected >= list.iMaxScraps)
ENDFUNC
/// PURPOSE:
/// Collects A Scrap
/// PARAMS:
/// missionData - scrap mission data reference
/// pickupData - reference to mission scrap array
/// iIndex - index of scrap to collect
PROC COLLECT_SCRAP(SCRAP_MISSION_DATA &missionData, SCRAP_PICKUP_DATA &pickupData[], INT iIndex)
CPRINTLN(DEBUG_AMBIENT, "Scrap ", iIndex, " Collected")
INT ipackNum = (GET_PACK_STAT(missionData.missionType)) + iIndex
// Remove pickup and blip
SAFE_REMOVE_PICKUP(pickupData[iIndex].pickup)
SAFE_REMOVE_BLIP(pickupData[iIndex].blip)
// Update pickup data
pickupData[iIndex].pickup = NULL
pickupData[iIndex].bActive = FALSE
// Mark scrap as collected
SET_SCRAP_AS_COLLECTED(missionData.scrapData, iIndex)
// Update globals for Chop
IF missionData.missionType = SCRAP_LETTER
OR missionData.missionType = SCRAP_SHIP
UPDATE_GLOBAL_SCRAP_DATA(missionData.missionType, iIndex)
ENDIF
// Rumble on collection
SET_CONTROL_SHAKE(PLAYER_CONTROL, PICKUP_RUMBLE_DURATION, PICKUP_RUMBLE_FREQ)
// Update stats
STAT_INCREMENT(missionData.packageStat, 1.0)
IF (bUseQuickScrapCollectCheck)
SET_SINGLE_PACKED_STAT_FROM_SCRAP_COLLECT_DATA(missionData.scrapData, iIndex)
ELSE
SET_PACKED_STATS_FROM_SCRAP_COLLECT_DATA(missionData.scrapData)
ENDIF
CALCULATE_TOTAL_HIDDEN_PACKAGES_COLLECTED_PERCENTAGE()
PLAYSTATS_ACQUIRED_HIDDEN_PACKAGE(ipackNum)
// Request autosave
SET_AUTOSAVE_IGNORES_ON_MISSION_FLAG(TRUE)
MAKE_AUTOSAVE_REQUEST()
// Signal that a message needs to be displayed
missionData.bDisplayMessage = TRUE
ENDPROC
/// PURPOSE:
/// Sets all the pickups in the given array to false
/// PARAMS:
/// pickupData - reference to mission scrap array
PROC SET_PICKUPS_ACTIVE_TO_FALSE(SCRAP_PICKUP_DATA& pickupData[])
INT i
REPEAT (COUNT_OF(pickupData)) i
pickupData[i].bActive = FALSE
ENDREPEAT
ENDPROC
/// PURPOSE:
/// returns the closest coord to the player
/// PARAMS:
/// vec1 - the first coord to check
/// vec2 - the second coord to check
FUNC VECTOR RETURN_CLOSEST(VECTOR vec1, VECTOR vec2)
IF (GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vec1) < GET_DISTANCE_BETWEEN_ENTITY_AND_COORD(PLAYER_PED_ID(), vec2))
RETURN vec1
ELSE
RETURN vec2
ENDIF
ENDFUNC
/// PURPOSE:
/// Handles looking at a pickup
/// PARAMS:
/// pickupData - reference to mission scrap array
/// index - the index of the pickup
PROC SORT_HEADTRACKING(SCRAP_PICKUP_DATA &pickupData[], INT iIndex)
// Pickup is active and has been created
IF pickupData[iIndex].bActive
IF (pickupData[iIndex].pickup != NULL)
//sort looking at scrap if close
IF IS_ENTITY_IN_RANGE_COORDS(PLAYER_PED_ID(), pickupData[iIndex].vCoords, 10.0)
TASK_LOOK_AT_COORD(PLAYER_PED_ID(), pickupData[iIndex].vCoords, 300, SLF_WHILE_NOT_IN_FOV, SLF_LOOKAT_LOW)
IF (bShowScrapDebugTTY)
CPRINTLN(DEBUG_AMBIENT, "look at scrap")
ENDIF
ENDIF
ENDIF
ENDIF
ENDPROC
/// PURPOSE:
/// Handles collecting and removing a pickup
/// PARAMS:
/// missionData - mission scrap data reference
/// pickupData - reference to mission scrap array
/// playerPos - we just pass this in to save calling GET_ENTITY_COORDS()
FUNC BOOL UPDATE_SCRAP_PICKUP(SCRAP_MISSION_DATA &missionData, SCRAP_PICKUP_DATA &pickupData[], VECTOR playerPos)
// Get current index
INT iIndex = missionData.iCurrentCheckIndex
// Pickup is active and has been created
IF pickupData[iIndex].bActive
IF (pickupData[iIndex].pickup != NULL)
// Has the player collected the pickup?
IF HAS_PICKUP_BEEN_COLLECTED(pickupData[iIndex].pickup)
OR HAS_PLAYER_COLLECTED_PICKUP_IN_WATER_VEHICLE(pickupData[iIndex].pickup)
COLLECT_SCRAP(missionData, pickupData, iIndex)
RETURN TRUE
ENDIF
ENDIF
ENDIF
// Handle removing the pickup - we use vdist2 it's quicker
IF DOES_PICKUP_EXIST(pickupData[iIndex].pickup)
IF (VDIST2(playerPos, GET_PICKUP_COORDS(pickupData[iIndex].pickup)) > (CLEANUP_PICKUP_DISTANCE * CLEANUP_PICKUP_DISTANCE))
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_ANIMAL)
OR IS_CURRENTLY_ON_MISSION_OF_TYPE(MISSION_TYPE_DIRECTOR) //Don't allow creation of pickups while playing as a none story character.
SAFE_REMOVE_PICKUP(pickupData[iIndex].pickup)
pickupData[iIndex].pickup = NULL
pickupData[iIndex].bActive = FALSE
ENDIF
ENDIF
RETURN FALSE
ENDFUNC
/// PURPOSE:
/// Returns the nearest pickup index from a position
/// PARAMS:
/// missionData - mission scrap data reference
/// pickupData - reference to mission scrap array
/// pos - position we need to check
/// out - Index into array or -1 if one can't be found
/// RETURNS:
/// TRUE / FALSE
FUNC BOOL GET_NEAREST_PICKUP_INDEX(SCRAP_MISSION_DATA &missionData, SCRAP_PICKUP_DATA& pickupData[], VECTOR pos, INT &out)
INT i = 0
FLOAT dist = 0
FLOAT minDist = -1.0
REPEAT COUNT_OF(pickupData) i
IF NOT HAS_SCRAP_BEEN_COLLECTED(missionData.scrapData, i)
dist = VDIST2(pos, pickupData[i].vCoords)
IF (minDist = -1.0) OR (dist < minDist)
out = i
minDist = dist
ENDIF
ENDIF
ENDREPEAT
RETURN (out <> -1)
ENDFUNC
/// PURPOSE:
/// Blips all scrap positions
PROC BLIP_SCRAP_POSITIONS(SCRAP_MISSION_DATA &missionData, SCRAP_PICKUP_DATA &pickupData[], BOOL bShowBlip = TRUE)
INT i
REPEAT COUNT_OF(pickupData) i
SAFE_REMOVE_BLIP(pickupData[i].blip)
IF (bShowBlip)
pickupData[i].blip = CREATE_COORD_BLIP(pickupData[i].vCoords, BLIPPRIORITY_MED, FALSE)
IF DOES_BLIP_EXIST(pickupData[i].blip)
IF HAS_SCRAP_BEEN_COLLECTED(missionData.scrapData, i)
SET_BLIP_SCALE(pickupData[i].blip, 0.25)
ELSE
SET_BLIP_SCALE(pickupData[i].blip, 1)
ENDIF
SET_BLIP_COLOUR(pickupData[i].blip, BLIP_COLOUR_GREEN)
ENDIF
ENDIF
ENDREPEAT
ENDPROC
/// PURPOSE:
/// Setups Variables for a scrap mission
/// PARAMS:
/// data - mission data reference
/// type - mission type num
/// mdl - model of the package
/// sGetMsg - message to be shown when one piece of scrap is got
/// sAllGetMsg - message to be show when all scrap is got
PROC SETUP_SCRAP_MISSION(SCRAP_MISSION_DATA &data, SCRAP_MISSION type, MODEL_NAMES mdl, STRING sGetMsg)
data.missionType = type
data.packageMdl = mdl
data.sScrapGetMsg = sGetMsg
data.iCurrentCheckIndex = 0
ENDPROC
/// PURPOSE:
/// Setups Variables for a scrap mission
/// PARAMS:
/// data - mission data reference
/// stat - enum to the stat we write to - eg: for letter scraps this would be NUM_HIDDEN_PACKAGES_0
/// statpacnum - first index of the stats to use - eg: for letter scraps use PACKSTAT_LETTER_START
/// maxScrap - the total number of scraps to collect - eg: for letter scraps this would be 50
PROC SETUP_SCRAP_MISSION_STATS(SCRAP_MISSION_DATA &data, STATSENUM stat, INT statpacnum, INT maxScrap)
data.packageStat = stat
SET_SCRAP_COLLECT_DATA_FROM_PACKED_STATS(data.scrapData, statpacnum, maxScrap)
ENDPROC
/// PURPOSE:
/// This sets packed stats from a scrap collect list
/// Make sure list.iPackNumBase and list.iMaxScraps has been set before using this
/// PARAMS:
/// list -
PROC RESET_SCRAP_MISSION_COLLECTION(SCRAP_MISSION_DATA &data)
INT i
CPRINTLN(DEBUG_AMBIENT, "Resetting Scrap Collection")
STAT_SET_INT(data.packageStat, 0)
REPEAT data.scrapData.iMaxScraps i
SET_SCRAP_AS_COLLECTED(data.scrapData, i, FALSE)
ENDREPEAT
SET_PACKED_STATS_FROM_SCRAP_COLLECT_DATA(data.scrapData)
ENDPROC
/// PURPOSE:
/// Helper function for finding an available grass cull sphere.
/// Check that this returns TRUE before using the passed INT!
/// PARAMS:
/// iSphere - Will be set to an available sphere index, or -1
/// RETURNS:
/// TRUE if a valid sphere index was set. FALSE if all spheres are in use.
FUNC BOOL IS_A_CULLSPHERE_AVAILABLE(INT &iSphere)
iSphere = 0
REPEAT NUMBER_AVAILABLE_CULLSPHERES iSphere
IF NOT PROCGRASS_IS_CULLSPHERE_ENABLED(iSphere)
CPRINTLN(DEBUG_AMBIENT, "IS_A_CULLSPHERE_AVAILABLE returning index: ", iSphere, " to script: ", GET_THIS_SCRIPT_NAME())
RETURN TRUE
ENDIF
ENDREPEAT
CERRORLN(DEBUG_AMBIENT, "IS_A_CULLSPHERE_AVAILABLE was unable to find an available index for script: ", GET_THIS_SCRIPT_NAME())
iSphere = -1
RETURN FALSE
ENDFUNC