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

876 lines
32 KiB
Python
Executable File

//////////////////////////////////////////////////////////////////////////////////
// //
// SCRIPT NAME : playthrough_builder.sc //
// AUTHOR : Kenneth Ross //
// DESCRIPTION : Used to generate the xml file that stores all the //
// playthrough missions in order. //
// //
//////////////////////////////////////////////////////////////////////////////////
USING "rage_builtins.sch"
USING "globals.sch"
#IF IS_DEBUG_BUILD
USING "commands_script.sch"
USING "script_player.sch"
USING "commands_xml.sch"
CONST_INT MAX_NUM_PLAYTHROUGH_FILES 22
CONST_INT MAX_NUM_PLAYTHROUGH_MISSIONS 100
STRING sXMLFile = "SPPlaythrough/SP_playthrough_builder.xml"
// Hash keys for the builder data
CONST_INT PB_HASH_ITEM_LIST HASH("listItem")
CONST_INT PB_HASH_MENU_FILE HASH("menuFile")
CONST_INT PB_HASH_PAGE_FILE HASH("pageFile")
CONST_INT PB_HASH_ORDER_FILE HASH("orderFile")
CONST_INT PB_HASH_LIST_SIZE HASH("listSize")
CONST_INT PB_HASH_FILE0 HASH("file0")
CONST_INT PB_HASH_FILE1 HASH("file1")
CONST_INT PB_HASH_FILE2 HASH("file2")
CONST_INT PB_HASH_FILE3 HASH("file3")
CONST_INT PB_HASH_FILE4 HASH("file4")
CONST_INT PB_HASH_FILE5 HASH("file5")
CONST_INT PB_HASH_FILE6 HASH("file6")
CONST_INT PB_HASH_FILE7 HASH("file7")
CONST_INT PB_HASH_FILE8 HASH("file8")
CONST_INT PB_HASH_FILE9 HASH("file9")
CONST_INT PB_HASH_FILE10 HASH("file10")
CONST_INT PB_HASH_FILE11 HASH("file11")
CONST_INT PB_HASH_FILE12 HASH("file12")
CONST_INT PB_HASH_FILE13 HASH("file13")
CONST_INT PB_HASH_FILE14 HASH("file14")
CONST_INT PB_HASH_FILE15 HASH("file15")
CONST_INT PB_HASH_FILE16 HASH("file16")
CONST_INT PB_HASH_FILE17 HASH("file17")
CONST_INT PB_HASH_FILE18 HASH("file18")
CONST_INT PB_HASH_FILE19 HASH("file19")
CONST_INT PB_HASH_FILE20 HASH("file20")
CONST_INT PB_HASH_FILE21 HASH("file21")
// Hash keys for the debug menu data
CONST_INT PB_HASH_ITEM_MISSION HASH("missionItem")
CONST_INT PB_HASH_POSX HASH("x")
CONST_INT PB_HASH_POSY HASH("y")
CONST_INT PB_HASH_POSZ HASH("z")
CONST_INT PB_HASH_HEADING HASH("heading")
CONST_INT PB_HASH_INTERIOR HASH("interior")
CONST_INT PB_HASH_FILE HASH("file")
CONST_INT PB_HASH_TITLE HASH("title")
CONST_INT PB_HASH_INFO HASH("info")
CONST_INT PB_HASH_CODE_ID HASH("codeID")
CONST_INT PB_HASH_CODE_ID_PRELAUNCH HASH("preCodeID")
CONST_INT PB_HASH_DISPLAY_ID HASH("displayID")
CONST_INT PB_HASH_ENABLE_ID HASH("enableID")
CONST_INT PB_HASH_MISSION_ID HASH("missionID")
CONST_INT PB_HASH_AUTHOR HASH("author")
CONST_INT PB_HASH_PERCENTAGE HASH("percentage")
CONST_INT PB_HASH_HIGHLIGHT HASH("highlight")
CONST_INT PB_HASH_CHARACTER HASH("character")
ENUM PLAYTHROUGH_BUILDER_STAGE
STAGE_GET_SCRIPTS = 0,
STAGE_STORE_DATA,
STAGE_SORT_DATA,
STAGE_WRITE_XML,
STAGE_COMPLETE
ENDENUM
STRUCT MISSION_ITEM_STRUCT
TEXT_LABEL_63 sFile
TEXT_LABEL_31 sTitle
TEXT_LABEL_31 sCodeID
TEXT_LABEL_31 sCodeIDPreLaunch
TEXT_LABEL_31 sDisplayID
TEXT_LABEL_31 sEnableID
TEXT_LABEL_15 sAuth
TEXT_LABEL_15 sInfo
TEXT_LABEL_15 sMissionID
TEXT_LABEL_15 sMissionInterior
TEXT_LABEL_15 sCharacter
INT iPerc
BOOL bHighlight
VECTOR vCoord
FLOAT fHeading
ENDSTRUCT
STRUCT BUILD_DATA_STRUCT
PLAYTHROUGH_BUILDER_STAGE eStage
MISSION_ITEM_STRUCT sMissions[MAX_NUM_PLAYTHROUGH_MISSIONS]
INT iCurrentList // The current listItem in the xml file
INT iFileCount // The total files used to search for missions
INT iCurrentFile // The current file used to search for missions
INT iMissionCount // The total missions we have found
INT iPageCount // The total playthrough pages we need to geberate
INT iListSize // The total missions we can add to each playthrough page
INT iCurrentSize // The current size of the playthrough page
BOOL bFinalList, bBuildComplete
TEXT_LABEL_63 sPlaythroughFiles[MAX_NUM_PLAYTHROUGH_FILES]
TEXT_LABEL_63 sMenuFile
TEXT_LABEL_63 sPageFile
TEXT_LABEL_63 sOrderFile
ENDSTRUCT
/// PURPOSE: Finds and replaced the XXX delimiter with the specified integer
FUNC STRING GET_PAGE_FILE_NAME(STRING sName, INT iNumber)
IF NOT ARE_STRINGS_EQUAL(sName, "")
INT i
FOR i = 0 TO GET_LENGTH_OF_LITERAL_STRING(sName)
IF i <= GET_LENGTH_OF_LITERAL_STRING(sName)-3
IF ARE_STRINGS_EQUAL(GET_STRING_FROM_STRING(sName, i, i+3), "XXX")
TEXT_LABEL_63 sFilename
sFilename = GET_STRING_FROM_STRING(sName, 0, i)
sFilename += iNumber
sFilename += GET_STRING_FROM_STRING(sName, i+3, GET_LENGTH_OF_LITERAL_STRING(sName))
RETURN GET_STRING_FROM_STRING(sFilename, 0, GET_LENGTH_OF_LITERAL_STRING(sFilename))
ENDIF
ENDIF
ENDFOR
ENDIF
RETURN ""
ENDFUNC
/// PURPOSE: Load the initial xml so we can obtain a reference to all the other xml files that contain missions for playthrough
PROC DO_GET_SCRIPTS(BUILD_DATA_STRUCT &sData)
// Load in xml file if it exists
IF LOAD_XML_FILE(sXMLFile)
PRINTSTRING("Playthrough Builder - Grabbing mission scripts from '")PRINTSTRING(sXMLFile)PRINTSTRING("'")PRINTNL()
INT iNodeCount = GET_NUMBER_OF_XML_NODES()
// Check that the xml contains some nodes
IF iNodeCount <> 0
// Integers used for the FOR loops going through all the nodes and attributes
INT eachNode, eachAttribute, listCount
// Loop through all the nodes
FOR eachNode = 0 TO (iNodeCount-1)
// Convert the current node name to a hash key so it can be used in a switch against the const's created at the top of this file
SWITCH GET_HASH_KEY(GET_XML_NODE_NAME())
CASE PB_HASH_ITEM_LIST
// Only deal with the current build
IF listCount = sData.iCurrentList
// Check the node has some attributes
IF GET_NUMBER_OF_XML_NODE_ATTRIBUTES() <> 0
// Loop through all the attributes
FOR eachAttribute = 0 TO (GET_NUMBER_OF_XML_NODE_ATTRIBUTES()-1)
// Convert the attribute name to a hash key like we did with the nodes so we can use a switch statement
SWITCH GET_HASH_KEY(GET_XML_NODE_ATTRIBUTE_NAME(eachAttribute))
// Grab the menu file name
CASE PB_HASH_MENU_FILE
sData.sMenuFile = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the page file name
CASE PB_HASH_PAGE_FILE
sData.sPageFile = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the order file name
CASE PB_HASH_ORDER_FILE
sData.sOrderFile = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the list size
CASE PB_HASH_LIST_SIZE
sData.iListSize = GET_INT_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the file
CASE PB_HASH_FILE0
CASE PB_HASH_FILE1
CASE PB_HASH_FILE2
CASE PB_HASH_FILE3
CASE PB_HASH_FILE4
CASE PB_HASH_FILE5
CASE PB_HASH_FILE6
CASE PB_HASH_FILE7
CASE PB_HASH_FILE8
CASE PB_HASH_FILE9
CASE PB_HASH_FILE10
CASE PB_HASH_FILE11
CASE PB_HASH_FILE12
CASE PB_HASH_FILE13
CASE PB_HASH_FILE14
CASE PB_HASH_FILE15
CASE PB_HASH_FILE16
CASE PB_HASH_FILE17
CASE PB_HASH_FILE18
CASE PB_HASH_FILE19
CASE PB_HASH_FILE20
CASE PB_HASH_FILE21
IF sData.iFileCount < MAX_NUM_PLAYTHROUGH_FILES
sData.sPlaythroughFiles[sData.iFileCount] = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
sData.iFileCount++
ELSE
SCRIPT_ASSERT("Playthrough Builder - max file count reached. Tell Kenneth R.")
ENDIF
BREAK
// End of the attribute switch statement
ENDSWITCH
// End for loop going through the attributes
ENDFOR
ENDIF
ENDIF
listCount++
BREAK
// End of the node switch statement
ENDSWITCH
// Tell the script to goto the next node in the xml file
GET_NEXT_XML_NODE()
// End of for loop going through the nodes
ENDFOR
// Now we have gone through all the nodes you need to unload the xml file
DELETE_XML_FILE()
IF sData.iCurrentList >= listCount-1
sData.bFinalList = TRUE
ENDIF
sData.eStage = STAGE_STORE_DATA
EXIT
ENDIF
// Failed to load XML file
ELSE
PRINTSTRING("Playthrough Builder - Failed to load xml file '")PRINTSTRING(sXMLFile)PRINTSTRING("'")PRINTNL()
ENDIF
sData.bBuildComplete = TRUE
ENDPROC
/// PURPOSE: Cycles through each of the stored file names, loads the xml and reads in the data
PROC DO_STORE_DATA(BUILD_DATA_STRUCT &sData)
// Make sure we have a file to search
IF sData.iFileCount > 0
IF NOT ARE_STRINGS_EQUAL(sData.sPlaythroughFiles[sData.iCurrentFile], "")
// Load in xml file if it exists
IF LOAD_XML_FILE(sData.sPlaythroughFiles[sData.iCurrentFile])
PRINTSTRING("Playthrough Builder - Grabbing mission items from '")PRINTSTRING(sData.sPlaythroughFiles[sData.iCurrentFile])PRINTSTRING("'")PRINTNL()
INT iNodeCount = GET_NUMBER_OF_XML_NODES()
// Check that the xml contains some nodes
IF iNodeCount <> 0
// Integers used for the FOR loops going through all the nodes and attributes
INT eachNode, eachAttribute
// Loop through all the nodes
FOR eachNode = 0 TO (iNodeCount-1)
// Convert the current node name to a hash key so it can be used in a switch against the const's created at the top of this file
SWITCH GET_HASH_KEY(GET_XML_NODE_NAME())
CASE PB_HASH_ITEM_MISSION
// Reset the data
sData.sMissions[sData.iMissionCount].sFile = ""
sData.sMissions[sData.iMissionCount].sTitle = ""
sData.sMissions[sData.iMissionCount].sCodeID = ""
sData.sMissions[sData.iMissionCount].sCodeIDPreLaunch = ""
sData.sMissions[sData.iMissionCount].sDisplayID = ""
sData.sMissions[sData.iMissionCount].sEnableID = ""
sData.sMissions[sData.iMissionCount].sAuth = ""
sData.sMissions[sData.iMissionCount].sInfo = ""
sData.sMissions[sData.iMissionCount].sMissionID = ""
sData.sMissions[sData.iMissionCount].sMissionInterior = ""
sData.sMissions[sData.iMissionCount].sCharacter = ""
sData.sMissions[sData.iMissionCount].bHighlight = FALSE
sData.sMissions[sData.iMissionCount].iPerc = 0
sData.sMissions[sData.iMissionCount].fHeading = -9999.99
sData.sMissions[sData.iMissionCount].vCoord.x = -9999.99
sData.sMissions[sData.iMissionCount].vCoord.y = -9999.99
sData.sMissions[sData.iMissionCount].vCoord.z = -9999.99
sData.sMissions[sData.iMissionCount].fHeading = -9999.99
// Check the node has some attributes
IF GET_NUMBER_OF_XML_NODE_ATTRIBUTES() <> 0
// Loop through all the attributes
FOR eachAttribute = 0 TO (GET_NUMBER_OF_XML_NODE_ATTRIBUTES()-1)
// Convert the attribute name to a hash key like we did with the nodes so we can use a switch statement
SWITCH GET_HASH_KEY(GET_XML_NODE_ATTRIBUTE_NAME(eachAttribute))
// Grab the title
CASE PB_HASH_TITLE
sData.sMissions[sData.iMissionCount].sTitle = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the file name
CASE PB_HASH_FILE
sData.sMissions[sData.iMissionCount].sFile = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab info
CASE PB_HASH_INFO
sData.sMissions[sData.iMissionCount].sInfo = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the x coord
CASE PB_HASH_POSX
sData.sMissions[sData.iMissionCount].vCoord.x = GET_FLOAT_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the y coord
CASE PB_HASH_POSY
sData.sMissions[sData.iMissionCount].vCoord.y = GET_FLOAT_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the z coord
CASE PB_HASH_POSZ
sData.sMissions[sData.iMissionCount].vCoord.z = GET_FLOAT_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the heading
CASE PB_HASH_HEADING
sData.sMissions[sData.iMissionCount].fHeading = GET_FLOAT_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the interior
CASE PB_HASH_INTERIOR
sData.sMissions[sData.iMissionCount].sMissionInterior = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the displayID
CASE PB_HASH_DISPLAY_ID
sData.sMissions[sData.iMissionCount].sDisplayID = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the selectID
CASE PB_HASH_ENABLE_ID
sData.sMissions[sData.iMissionCount].sEnableID = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the author
CASE PB_HASH_AUTHOR
sData.sMissions[sData.iMissionCount].sAuth = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the missionID
CASE PB_HASH_MISSION_ID
sData.sMissions[sData.iMissionCount].sMissionID = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the character
CASE PB_HASH_CHARACTER
sData.sMissions[sData.iMissionCount].sCharacter = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the percentage
CASE PB_HASH_PERCENTAGE
sData.sMissions[sData.iMissionCount].iPerc = GET_INT_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the highlight flag
CASE PB_HASH_HIGHLIGHT
sData.sMissions[sData.iMissionCount].bHighlight = GET_BOOL_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the code ID
CASE PB_HASH_CODE_ID
sData.sMissions[sData.iMissionCount].sCodeID = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// Grab the pre-launch code ID
CASE PB_HASH_CODE_ID_PRELAUNCH
sData.sMissions[sData.iMissionCount].sCodeIDPreLaunch = GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute)
BREAK
// End of the attribute switch statement
ENDSWITCH
// End for loop going through the attributes
ENDFOR
sData.iMissionCount++
ENDIF
BREAK
// End of the node switch statement
ENDSWITCH
// Tell the script to goto the next node in the xml file
GET_NEXT_XML_NODE()
// End of for loop going through the nodes
ENDFOR
// Now we have gone through all the nodes you need to unload the xml file
DELETE_XML_FILE()
ENDIF
// Failed to load XML file
ELSE
PRINTSTRING("Playthrough Builder - Failed to load xml file '")PRINTSTRING(sData.sPlaythroughFiles[sData.iCurrentFile])PRINTSTRING("'")PRINTNL()
ENDIF
ENDIF
// Prepare for the next cycle
sData.iCurrentFile++
ENDIF
// Progress to next stage if we have stored all the data from each file
IF sData.iCurrentFile >= sData.iFileCount
// Make sure we have set a valid listSize
IF sData.iListSize = 0
sData.iListSize = 15
ENDIF
sData.eStage = STAGE_SORT_DATA
ENDIF
ENDPROC
/// PURPOSE: Sort the data into playthrough order
PROC DO_SORT_DATA(BUILD_DATA_STRUCT &sData)
PRINTSTRING("Playthrough Builder - Sorting the missions into playthrough order")PRINTNL()
IF NOT ARE_STRINGS_EQUAL(sData.sOrderFile, "")
// Load in xml file if it exists
IF LOAD_XML_FILE(sData.sOrderFile)
PRINTSTRING("Playthrough Builder - Grabbing playthrough order form '")PRINTSTRING(sData.sOrderFile)PRINTSTRING("'")PRINTNL()
INT iNodeCount = GET_NUMBER_OF_XML_NODES()
// Check that the xml contains some nodes
IF iNodeCount <> 0
// Integers used for the FOR loops going through all the nodes and attributes
INT eachNode, eachAttribute, iSeek, iNextSortedSlot
MISSION_ITEM_STRUCT sTempItem
BOOL bFound
// Loop through all the nodes
FOR eachNode = 0 TO (iNodeCount-1)
// Convert the current node name to a hash key so it can be used in a switch against the const's created at the top of this file
SWITCH GET_HASH_KEY(GET_XML_NODE_NAME())
CASE PB_HASH_ITEM_MISSION
// Check the node has some attributes
IF GET_NUMBER_OF_XML_NODE_ATTRIBUTES() <> 0
// Loop through all the attributes
FOR eachAttribute = 0 TO (GET_NUMBER_OF_XML_NODE_ATTRIBUTES()-1)
// Convert the attribute name to a hash key like we did with the nodes so we can use a switch statement
SWITCH GET_HASH_KEY(GET_XML_NODE_ATTRIBUTE_NAME(eachAttribute))
// Grab the file
CASE PB_HASH_FILE
bFound = FALSE
iSeek = iNextSortedSlot
// Cycle through our missions to find a matching ID
WHILE iSeek <= sData.iMissionCount
AND NOT bFound
// Use hashkeys to compare so we dont run into trouble with case
IF GET_HASH_KEY(sData.sMissions[iSeek].sFile) = GET_HASH_KEY(GET_STRING_FROM_XML_NODE_ATTRIBUTE(eachAttribute))
// Make a copy of the data that we need to move out of the sorted slot
sTempItem = sData.sMissions[iNextSortedSlot]
// Set the data in the next sorted slot to the item we found
sData.sMissions[iNextSortedSlot] = sData.sMissions[iSeek]
// Set the data in the item we found with the copy data
sData.sMissions[iSeek] = sTempItem
bFound = TRUE
iNextSortedSlot++
ENDIF
iSeek++
ENDWHILE
BREAK
// End of the attribute switch statement
ENDSWITCH
// End for loop going through the attributes
ENDFOR
ENDIF
BREAK
// End of the node switch statement
ENDSWITCH
// Tell the script to goto the next node in the xml file
GET_NEXT_XML_NODE()
// End of for loop going through the nodes
ENDFOR
// Now we have gone through all the nodes you need to unload the xml file
DELETE_XML_FILE()
// Resize the mission count if need be
IF sData.iMissionCount > iNextSortedSlot
sData.iMissionCount = iNextSortedSlot
ENDIF
ENDIF
// Failed to load XML file
ELSE
PRINTSTRING("Playthrough Builder - Failed to load xml file '")PRINTSTRING(sData.sOrderFile)PRINTSTRING("'")PRINTNL()
ENDIF
// Order file not set
ELSE
PRINTSTRING("Playthrough Builder - Order file not specified")PRINTNL()
ENDIF
// Work out how much playthrough pages we need to create
sData.iPageCount = 0
IF sData.iMissionCount > 0
INT i
WHILE i < sData.iMissionCount-1
sData.iPageCount++
i += sData.iListSize
ENDWHILE
ENDIF
sData.eStage = STAGE_WRITE_XML
ENDPROC
/// PURPOSE: Write all the missions to the playthrough xml so it can be read by the debug menu
PROC DO_WRITE_XML(BUILD_DATA_STRUCT &sData)
// Make sure we have an output file to save to
IF NOT ARE_STRINGS_EQUAL(sData.sMenuFile, "")
INT i, j, iFile
STRING sPathname = "X:/gta5/titleupdate/dev_ng/common/data/script/xml/"
STRING sFilename = GET_STRING_FROM_STRING(sData.sMenuFile, 0, GET_LENGTH_OF_LITERAL_STRING(sData.sMenuFile))
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Create the playthrough menu xml
PRINTSTRING("Playthrough Builder - Generating '")PRINTSTRING(sFilename)PRINTSTRING("' with ")PRINTINT(sData.iPageCount)PRINTSTRING(" playthrough pages")PRINTNL()
// Add some comments so people know not to overwrite
CLEAR_NAMED_DEBUG_FILE(sPathname, sFilename)
OPEN_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("<!-- This file has been generated using playthrough_builder.sc -->", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("<!-- Please do not edit this file directly as changes will be lost. -->", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
// Add the initial xml data to the file
SAVE_STRING_TO_NAMED_DEBUG_FILE("<?xml version='1.0'?>", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("<DebugMenuItems>", sPathname, sPathname)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
// Add all the playthrough pages
IF sData.iPageCount > 0
FOR i = 0 TO sData.iPageCount-1
iFile = i+1 // Use +1 so we dont get 0
TEXT_LABEL_63 sFile = GET_PAGE_FILE_NAME(sData.sPageFile, iFile)
IF NOT ARE_STRINGS_EQUAL(sFilename, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" <menuItem title=\"DM_PAGE_", sPathname, sFilename)
SAVE_INT_TO_NAMED_DEBUG_FILE(iFile, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\" file=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sFile, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"/>", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
ENDIF
ENDFOR
ENDIF
// Add the final xml data
SAVE_STRING_TO_NAMED_DEBUG_FILE("</DebugMenuItems>", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
CLOSE_DEBUG_FILE()
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Create each playthrough page
IF sData.iPageCount > 0
FOR i = 0 TO sData.iPageCount-1
iFile = i+1 // Use +1 so we dont get 0
sFilename = GET_PAGE_FILE_NAME(sData.sPageFile, iFile)// Use +1 so we dont get 0
IF NOT ARE_STRINGS_EQUAL(sFilename, "")
PRINTSTRING("Playthrough Builder - Generating playthrough page '")PRINTSTRING(sFilename)PRINTSTRING("'")PRINTNL()
// Add some comments so people know not to overwrite
CLEAR_NAMED_DEBUG_FILE(sPathname, sFilename)
OPEN_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("<!-- This file has been generated using playthrough_builder.sc -->", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("<!-- Please do not edit this file directly as changes will be lost. -->", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
// Add the initial xml data to the file
SAVE_STRING_TO_NAMED_DEBUG_FILE("<?xml version='1.0'?>", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("<DebugMenuItems>", sPathname, sPathname)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
// Output all the mission items to the current page
INT iStart = sData.iCurrentSize
INT iEnd = sData.iCurrentSize+sData.iListSize-1
FOR j = iStart TO iEnd
IF j < sData.iMissionCount
SAVE_STRING_TO_NAMED_DEBUG_FILE(" <missionItem", sPathname, sFilename)
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sMissionID, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" missionID=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sMissionID, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sFile, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" file=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sFile, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sTitle, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" title=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sTitle, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sAuth, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" author=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sAuth, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
SAVE_STRING_TO_NAMED_DEBUG_FILE(" percentage=\"", sPathname, sFilename)
SAVE_INT_TO_NAMED_DEBUG_FILE(sData.sMissions[j].iPerc, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
IF sData.sMissions[j].bHighlight
SAVE_STRING_TO_NAMED_DEBUG_FILE(" highlight=\"TRUE\"", sPathname, sFilename)
ELSE
SAVE_STRING_TO_NAMED_DEBUG_FILE(" highlight=\"FALSE\"", sPathname, sFilename)
ENDIF
IF sData.sMissions[j].vCoord.x <> -9999.99
SAVE_STRING_TO_NAMED_DEBUG_FILE(" x=\"", sPathname, sFilename)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(sData.sMissions[j].vCoord.x, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF sData.sMissions[j].vCoord.y <> -9999.99
SAVE_STRING_TO_NAMED_DEBUG_FILE(" y=\"", sPathname, sFilename)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(sData.sMissions[j].vCoord.y, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF sData.sMissions[j].vCoord.z <> -9999.99
SAVE_STRING_TO_NAMED_DEBUG_FILE(" z=\"", sPathname, sFilename)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(sData.sMissions[j].vCoord.z, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF sData.sMissions[j].fHeading <> -9999.99
SAVE_STRING_TO_NAMED_DEBUG_FILE(" heading=\"", sPathname, sFilename)
SAVE_FLOAT_TO_NAMED_DEBUG_FILE(sData.sMissions[j].fHeading, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sMissionInterior, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" interior=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sMissionInterior, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sInfo, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" info=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sInfo, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sCharacter, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" character=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sCharacter, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sCodeID, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" codeID=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sCodeID, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sCodeIDPreLaunch, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" preCodeID=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sCodeIDPreLaunch, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sDisplayID, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" displayID=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sDisplayID, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
IF NOT ARE_STRINGS_EQUAL(sData.sMissions[j].sEnableID, "")
SAVE_STRING_TO_NAMED_DEBUG_FILE(" enableID=\"", sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE(sData.sMissions[j].sEnableID, sPathname, sFilename)
SAVE_STRING_TO_NAMED_DEBUG_FILE("\"", sPathname, sFilename)
ENDIF
SAVE_STRING_TO_NAMED_DEBUG_FILE("/>", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
sData.iCurrentSize++
ENDIF
ENDFOR
// Add the final xml data
SAVE_STRING_TO_NAMED_DEBUG_FILE("</DebugMenuItems>", sPathname, sFilename)
SAVE_NEWLINE_TO_NAMED_DEBUG_FILE(sPathname, sFilename)
CLOSE_DEBUG_FILE()
WAIT(0) // So we dont run over mipf
ENDIF
ENDFOR
ENDIF
ENDIF
sData.eStage = STAGE_COMPLETE
ENDPROC
#ENDIF
SCRIPT
IF HAS_FORCE_CLEANUP_OCCURRED(FORCE_CLEANUP_FLAG_SP_TO_MP)
PRINTNL()
PRINTSTRING("PLAYTHROUGH BUILDER SCRIPT CLEANING UP (SP TO MP)")
PRINTNL()
TERMINATE_THIS_THREAD()
ENDIF
#IF IS_DEBUG_BUILD
WAIT(1000)
PRINTSTRING("PLAYTHROUGH BUILDER: Waiting for gameflow launch to finish...")
PRINTNL()
WHILE g_flowUnsaved.bUpdatingGameflow
WAIT(0)
ENDWHILE
PRINTSTRING("PLAYTHROUGH BUILDER: Gameflow launch finished.")
PRINTNL()
PRINTNL()
PRINTSTRING("PLAYTHROUGH BUILDER SCRIPT STARTING")
PRINTNL()
BUILD_DATA_STRUCT sData
WHILE NOT sData.bBuildComplete
SWITCH sData.eStage
CASE STAGE_GET_SCRIPTS
DO_GET_SCRIPTS(sData)
BREAK
CASE STAGE_STORE_DATA
DO_STORE_DATA(sData)
BREAK
CASE STAGE_SORT_DATA
DO_SORT_DATA(sData)
BREAK
CASE STAGE_WRITE_XML
DO_WRITE_XML(sData)
BREAK
CASE STAGE_COMPLETE
IF sData.bFinalList
sData.bBuildComplete = TRUE
ELSE
sData.iFileCount = 0
sData.iMissionCount = 0
sData.iCurrentFile = 0
sData.iCurrentList = 0
sData.sMenuFile = ""
sData.sPageFile = ""
sData.iCurrentList++
sData.eStage = STAGE_GET_SCRIPTS
ENDIF
BREAK
ENDSWITCH
ENDWHILE
PRINTNL()
PRINTSTRING("PLAYTHROUGH BUILDER SCRIPT TERMINATING")
PRINTNL()
#ENDIF
ENDSCRIPT