mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
Space Viking's many mercs changes plus numerous generic bug fixes
git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@2498 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user