mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
* Fixing upper/lower case for includes types.h, zconf.h and zlib.h were renamed so that global includes like Types.h are not used.
276 lines
7.7 KiB
C++
276 lines
7.7 KiB
C++
#include "builddefines.h"
|
|
#include <stdio.h>
|
|
#include "XML.h"
|
|
#include "expat.h"
|
|
#include "DEBUG.H"
|
|
#include "string.h"
|
|
#include "Tactical Save.h"
|
|
#include "FileMan.h"
|
|
#include "MemMan.h"
|
|
#include "Debug Control.h"
|
|
#include "GameSettings.h"
|
|
#include "GameInitOptionsScreen.h"
|
|
|
|
typedef enum
|
|
{
|
|
EXTRAITEMS_ELEMENT_NONE = 0,
|
|
EXTRAITEMS_ELEMENT_EXTRAITEMS,
|
|
EXTRAITEMS_ELEMENT_ITEM,
|
|
EXTRAITEMS_ELEMENT,
|
|
} EXTRAITEMS_PARSE_STAGE;
|
|
|
|
typedef struct
|
|
{
|
|
EXTRAITEMS_PARSE_STAGE curElement;
|
|
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
|
UINT32 currentDepth;
|
|
UINT32 maxReadDepth;
|
|
|
|
UINT32 item;
|
|
UINT32 quantity;
|
|
UINT32 condition;
|
|
UINT32 gridno;
|
|
BOOLEAN visible;
|
|
} ExtraItemsParseData;
|
|
|
|
|
|
static bool gSectorIsLoaded = false;
|
|
static UINT8 gX = 0;
|
|
static UINT8 gY = 0;
|
|
static UINT8 gZ = 0;
|
|
|
|
/** Process the opening tag in this expat callback.
|
|
*/
|
|
static void XMLCALL
|
|
ExtraItemsStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
|
|
{
|
|
ExtraItemsParseData * pData = (ExtraItemsParseData *) userData;
|
|
|
|
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
|
{
|
|
if(strcmp(name, "ExtraItems") == 0 && pData->curElement == EXTRAITEMS_ELEMENT_NONE)
|
|
{
|
|
pData->curElement = EXTRAITEMS_ELEMENT_EXTRAITEMS;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
else if(strcmp(name, "Item") == 0 && pData->curElement == EXTRAITEMS_ELEMENT_EXTRAITEMS)
|
|
{
|
|
pData->curElement = EXTRAITEMS_ELEMENT_ITEM;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
|
|
// set defaults
|
|
pData->quantity = 1;
|
|
pData->condition = 100;
|
|
pData->gridno = 0;
|
|
pData->visible = FALSE;
|
|
}
|
|
else if(pData->curElement == EXTRAITEMS_ELEMENT_ITEM &&
|
|
(strcmp(name, "uiIndex") == 0 ||
|
|
strcmp(name, "quantity") == 0 ||
|
|
strcmp(name, "condition") == 0 ||
|
|
strcmp(name, "gridno") == 0 ||
|
|
strcmp(name, "visible") == 0 ))
|
|
{
|
|
pData->curElement = EXTRAITEMS_ELEMENT;
|
|
pData->maxReadDepth++;
|
|
}
|
|
pData->szCharData[0] = '\0';
|
|
}
|
|
pData->currentDepth++;
|
|
}
|
|
|
|
/** Process any text content in this callback.
|
|
*/
|
|
static void XMLCALL
|
|
ExtraItemsCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
|
{
|
|
ExtraItemsParseData * pData = (ExtraItemsParseData *) userData;
|
|
|
|
if(pData->currentDepth <= pData->maxReadDepth && strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
|
|
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
|
|
}
|
|
|
|
/** Process the closing tag in this expat callback.
|
|
*/
|
|
static void XMLCALL
|
|
ExtraItemsEndElementHandle(void *userData, const XML_Char *name)
|
|
{
|
|
ExtraItemsParseData * pData = (ExtraItemsParseData *) userData;
|
|
|
|
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
|
{
|
|
if(pData->curElement == EXTRAITEMS_ELEMENT_EXTRAITEMS &&
|
|
strcmp(name, "ExtraItems") == 0)
|
|
{
|
|
pData->curElement = EXTRAITEMS_ELEMENT_NONE;
|
|
}
|
|
else if(pData->curElement == EXTRAITEMS_ELEMENT_ITEM &&
|
|
strcmp(name, "Item") == 0 &&
|
|
pData->item > 0 && // Make sure not to create 0-index objects!
|
|
pData->quantity > 0 && // Quantity should be positive. Not sure what the LIMIT is, if any.
|
|
pData->condition > 0 && pData->condition <= 100 ) // Condition between 1 and 100!
|
|
{
|
|
OBJECTTYPE object;
|
|
CreateItem(pData->item, pData->condition, &object);
|
|
for (unsigned cnt=1; cnt <= pData->quantity; ++cnt) {
|
|
if (gSectorIsLoaded) {
|
|
AddItemToPool( pData->gridno, &object, pData->visible, 0, WORLD_ITEM_REACHABLE, 0 );
|
|
} else {
|
|
AddItemsToUnLoadedSector( gX, gY, gZ, pData->gridno, pData->visible, &object, 0, WORLD_ITEM_REACHABLE, 0, 1, 0 );
|
|
}
|
|
}
|
|
pData->curElement = EXTRAITEMS_ELEMENT_EXTRAITEMS;
|
|
}
|
|
|
|
else if( pData->curElement == EXTRAITEMS_ELEMENT &&
|
|
strcmp( name, "uiIndex" ) == 0)
|
|
{
|
|
pData->item = (UINT32)atol( pData->szCharData );
|
|
pData->curElement = EXTRAITEMS_ELEMENT_ITEM;
|
|
}
|
|
else if( pData->curElement == EXTRAITEMS_ELEMENT &&
|
|
strcmp( name, "quantity" ) == 0)
|
|
{
|
|
pData->quantity = (UINT32)atol( pData->szCharData );
|
|
pData->curElement = EXTRAITEMS_ELEMENT_ITEM;
|
|
}
|
|
else if( pData->curElement == EXTRAITEMS_ELEMENT &&
|
|
strcmp( name, "condition" ) == 0)
|
|
{
|
|
pData->condition = (UINT32)atol( pData->szCharData );
|
|
pData->curElement = EXTRAITEMS_ELEMENT_ITEM;
|
|
}
|
|
else if( pData->curElement == EXTRAITEMS_ELEMENT &&
|
|
strcmp( name, "gridno" ) == 0)
|
|
{
|
|
pData->gridno = (UINT32)atol( pData->szCharData );
|
|
pData->curElement = EXTRAITEMS_ELEMENT_ITEM;
|
|
}
|
|
else if( pData->curElement == EXTRAITEMS_ELEMENT &&
|
|
strcmp( name, "visible" ) == 0)
|
|
{
|
|
pData->visible = (UINT32)atol( pData->szCharData );
|
|
pData->curElement = EXTRAITEMS_ELEMENT_ITEM;
|
|
}
|
|
pData->maxReadDepth--;
|
|
}
|
|
pData->currentDepth--;
|
|
}
|
|
|
|
|
|
void AddExtraItems(UINT8 x, UINT8 y, UINT8 z, bool sectorIsLoaded)
|
|
{
|
|
char fileName[MAX_PATH];
|
|
strcpy(fileName, TABLEDATA_DIRECTORY);
|
|
if (x < 10) {
|
|
strcat(fileName, EXTRAITEMSFILENAME);
|
|
char* spot = strstr(fileName, "A9_0");
|
|
Assert(spot);
|
|
if (!spot)
|
|
return;
|
|
*spot = 'A' + y-1;
|
|
*(spot+1) = '0' + x;
|
|
*(spot+3) = '0' + z;
|
|
} else {
|
|
strcat(fileName, EXTRAITEMSFILENAME2);
|
|
char* spot = strstr(fileName, "A11_0");
|
|
Assert(spot);
|
|
if (!spot)
|
|
return;
|
|
*spot = 'A' + y-1;
|
|
*(spot+1) = '0' + x / 10;
|
|
*(spot+2) = '0' + x % 10;
|
|
*(spot+4) = '0' + z;
|
|
}
|
|
|
|
// Remember the base file name length
|
|
int baseFNLength = strlen(fileName);
|
|
|
|
// Append a suffix based on the difficulty
|
|
switch (gGameOptions.ubDifficultyLevel)
|
|
{
|
|
case DIF_LEVEL_EASY:
|
|
strcat(fileName, "_Novice");
|
|
break;
|
|
case DIF_LEVEL_MEDIUM:
|
|
strcat(fileName, "_Experienced");
|
|
break;
|
|
case DIF_LEVEL_HARD:
|
|
strcat(fileName, "_Expert");
|
|
break;
|
|
case DIF_LEVEL_INSANE:
|
|
strcat(fileName, "_Insane");
|
|
break;
|
|
default:
|
|
{
|
|
CHAR8 str[20];
|
|
sprintf( str, "_Diff_%d", gGameOptions.ubDifficultyLevel );
|
|
strcat( fileName, str );
|
|
}
|
|
break;
|
|
}
|
|
|
|
strcat(fileName, ".xml");
|
|
if(!FileExists(fileName))//dnl ch75 261013 just to avoid sdd::exception under debug from VFS when file not exist
|
|
return;
|
|
|
|
// Open extra items file
|
|
HWFILE hFile;
|
|
// Try "special" difficulty level file first
|
|
if (!(hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE ))) {
|
|
// OK, that didn't work so try the "plain" file
|
|
fileName[baseFNLength] = '\0';
|
|
if (!(hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE ))) {
|
|
// There isn't a file for this sector, just return
|
|
return;
|
|
}
|
|
}
|
|
|
|
gSectorIsLoaded = sectorIsLoaded;
|
|
gX = x;
|
|
gY = y;
|
|
gZ = z;
|
|
|
|
UINT32 uiBytesRead;
|
|
XML_Parser parser = XML_ParserCreate(NULL);
|
|
ExtraItemsParseData pData;
|
|
|
|
UINT32 uiFSize = FileGetSize(hFile);
|
|
CHAR8 * lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
|
|
|
//Read in block
|
|
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) ) {
|
|
MemFree(lpcBuffer);
|
|
XML_ParserFree(parser);
|
|
return;
|
|
}
|
|
|
|
lpcBuffer[uiFSize] = 0; //add a null terminator
|
|
|
|
FileClose( hFile );
|
|
|
|
// Setup expat callbacks
|
|
XML_SetElementHandler(parser, ExtraItemsStartElementHandle, ExtraItemsEndElementHandle);
|
|
XML_SetCharacterDataHandler(parser, ExtraItemsCharacterDataHandle);
|
|
|
|
memset(&pData,0,sizeof(pData));
|
|
XML_SetUserData(parser, &pData);
|
|
|
|
if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE))
|
|
{
|
|
CHAR8 errorBuf[511];
|
|
|
|
sprintf(errorBuf, "XML Parser Error in ExtraItems.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
|
LiveMessage(errorBuf);
|
|
|
|
MemFree(lpcBuffer);
|
|
XML_ParserFree(parser);
|
|
return;
|
|
}
|
|
|
|
MemFree(lpcBuffer);
|
|
|
|
XML_ParserFree(parser);
|
|
return;
|
|
}
|