Files
source/Strategic/XML_ExtraItems.cpp
T

247 lines
6.5 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"
typedef enum
{
EXTRAITEMS_ELEMENT_NONE = 0,
EXTRAITEMS_ELEMENT_EXTRAITEMS,
EXTRAITEMS_ELEMENT_ITEM
} 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;
} 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
// Extract the attributes
// defaults
pData->quantity = 1;
pData->condition = 100;
pData->gridno = 0;
for(unsigned uiAttrIndex = 0;atts[uiAttrIndex] != NULL;uiAttrIndex += 2)
{
if(strcmp(atts[uiAttrIndex], "quantity") == 0)
{
pData->quantity = atol(atts[uiAttrIndex+1]);
if (pData->quantity < 1 || pData->quantity > 100) {
pData->quantity = 1;
}
}
else if(strcmp(atts[uiAttrIndex], "condition") == 0)
{
pData->condition = atol(atts[uiAttrIndex+1]);
if (pData->condition < 1 || pData->condition > 100) {
pData->condition = 100;
}
}
else if(strcmp(atts[uiAttrIndex], "gridno") == 0)
{
pData->gridno = atol(atts[uiAttrIndex+1]);
//if (pData->gridno < ???? || pData->gridno > ????) {
// pData->gridno = 0;
//}
}
}
}
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(strcmp(name, "ExtraItems") == 0 && pData->curElement == EXTRAITEMS_ELEMENT_EXTRAITEMS)
{
pData->curElement = EXTRAITEMS_ELEMENT_NONE;
}
else if(strcmp(name, "Item") == 0 && pData->curElement == EXTRAITEMS_ELEMENT_ITEM)
{
pData->item = atol(pData->szCharData);
OBJECTTYPE object;
CreateItem(pData->item, pData->condition, &object);
for (unsigned cnt=1; cnt <= pData->quantity; ++cnt) {
if (gSectorIsLoaded) {
AddItemToPool( pData->gridno, &object, 1, 0, WORLD_ITEM_REACHABLE, 0 );
} else {
AddItemsToUnLoadedSector( gX, gY, gZ, pData->gridno, 1, &object, 0, WORLD_ITEM_REACHABLE, 0, 1, 0 );
}
}
pData->curElement = EXTRAITEMS_ELEMENT_EXTRAITEMS;
}
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_ZERO:
break;
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;
case DIF_LEVEL_FIVE:
break;
default:
break;
}
// 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;
}