mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
* HAM 3.6 (by Headrock) * ************************* - Info: Needed GameDir files for HAM 3.6 are not committed yet to the SVN GameDir. Will do that in the next few days - For more infos on HAM 3.6 check out: http://www.ja-galaxy-forum.com/board/ubbthreads.php?ubb=showflat&Number=244808&page=0&fpart=1 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@3323 3b4a5df2-a311-0410-b5c6-a8a6f20db521
344 lines
11 KiB
C++
344 lines
11 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Strategic All.h"
|
|
#include "XML.h"
|
|
#else
|
|
#include "builddefines.h"
|
|
#include <stdio.h>
|
|
#include "XML.h"
|
|
#include "expat.h"
|
|
#include "string.h"
|
|
#include "Campaign Types.h"
|
|
#include "FileMan.h"
|
|
#include "MemMan.h"
|
|
#include "Debug Control.h"
|
|
#include "mapscreen.h"
|
|
#endif
|
|
|
|
#define MAX_CHAR_DATA_LENGTH 500
|
|
|
|
// This array stores all XML-read placement data. There are four arrays for each sector, one array for each difficulty
|
|
// level. Please note that the Placement Type is only stored in array 0 (gBloodcatPlacements[x][0].PlacementType). It
|
|
// is not possible to have different placement types at different difficulty levels. Yet.
|
|
BLOODCATPLACEMENT gBloodcatPlacements[256][4];
|
|
// Location of the Bloodcat Lair. There can be only one, as there's a quest that relies on its location. This is a
|
|
// sectorID, 0-255.
|
|
UINT8 gubBloodcatLairSectorId;
|
|
|
|
typedef enum
|
|
{
|
|
BLOODCAT_ELEMENT_NONE = 0,
|
|
BLOODCAT_ELEMENT_PLACEMENTS,
|
|
BLOODCAT_ELEMENT_SECTOR,
|
|
BLOODCAT_ELEMENT,
|
|
BLOODCAT_ELEMENT_DIFFICULTY,
|
|
BLOODCAT_ELEMENT_DIFFICULTY_DATA,
|
|
} BLOODCAT_PARSE_STAGE;
|
|
|
|
typedef struct
|
|
{
|
|
BLOODCAT_PARSE_STAGE curElement;
|
|
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
|
|
UINT8 sCurSectorX;
|
|
UINT8 sCurSectorY;
|
|
BLOODCATPLACEMENT CurPlacement[4];
|
|
UINT8 ubCurDifficulty;
|
|
UINT32 currentDepth;
|
|
UINT32 maxReadDepth;
|
|
} BloodcatsParseData;
|
|
|
|
|
|
static void XMLCALL
|
|
BloodcatsStartElementHandle(void *userData, const XML_Char *name, const char **atts)
|
|
{
|
|
BloodcatsParseData * pData = (BloodcatsParseData *) userData;
|
|
|
|
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
|
|
{
|
|
|
|
if(strcmp(name, "BLOODCAT_PLACEMENTS") == 0 && pData->curElement == BLOODCAT_ELEMENT_NONE)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_PLACEMENTS;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
// Initiate Array by setting first character to 0.
|
|
for (UINT16 x = 0; x < 256; x++)
|
|
{
|
|
for (UINT16 y = 0; y < 4; y++)
|
|
{
|
|
gBloodcatPlacements[x][y].ubFactionAffiliation = 0;
|
|
gBloodcatPlacements[x][y].fRespawn = 0;
|
|
gBloodcatPlacements[x][y].PlacementType = 0;
|
|
gBloodcatPlacements[x][y].ubAmbushChance = 0;
|
|
gBloodcatPlacements[x][y].ubMaxBloodcats = 0;
|
|
gBloodcatPlacements[x][y].ubMinBloodcats = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
else if(strcmp(name, "SECTOR") == 0 && pData->curElement == BLOODCAT_ELEMENT_PLACEMENTS)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
|
|
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
|
(strcmp(name, "SectorGrid") == 0 ||
|
|
strcmp(name, "ubPlacementType") == 0) )
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT;
|
|
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
|
|
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
|
strcmp(name, "NOVICE") == 0)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->ubCurDifficulty = 0;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
|
|
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
|
strcmp(name, "EXPERIENCED") == 0)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->ubCurDifficulty = 1;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
|
strcmp(name, "EXPERT") == 0)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->ubCurDifficulty = 2;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
else if(pData->curElement == BLOODCAT_ELEMENT_SECTOR &&
|
|
strcmp(name, "INSANE") == 0)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->ubCurDifficulty = 3;
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
|
|
else if(pData->curElement == BLOODCAT_ELEMENT_DIFFICULTY &&
|
|
(strcmp(name, "ubMinBloodcats") == 0 ||
|
|
strcmp(name, "ubMaxBloodcats") == 0 ||
|
|
strcmp(name, "ubAmbushChance") == 0 ||
|
|
strcmp(name, "ubFactionAffiliation") == 0 ||
|
|
strcmp(name, "fRespawn") == 0 ))
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY_DATA;
|
|
|
|
pData->maxReadDepth++; //we are not skipping this element
|
|
}
|
|
|
|
pData->szCharData[0] = '\0';
|
|
}
|
|
|
|
pData->currentDepth++;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void XMLCALL
|
|
BloodcatsCharacterDataHandle(void *userData, const XML_Char *str, int len)
|
|
{
|
|
BloodcatsParseData * pData = (BloodcatsParseData *) 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)));
|
|
}
|
|
|
|
|
|
static void XMLCALL
|
|
BloodcatsEndElementHandle(void *userData, const XML_Char *name)
|
|
{
|
|
BloodcatsParseData * pData = (BloodcatsParseData *)userData;
|
|
|
|
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
|
|
{
|
|
if(strcmp(name, "BLOODCAT_PLACEMENTS") == 0)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_NONE;
|
|
}
|
|
else if(strcmp(name, "SECTOR") == 0)
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_PLACEMENTS;
|
|
|
|
UINT8 ubSectorId = SECTOR(pData->sCurSectorX, pData->sCurSectorY);
|
|
if (ubSectorId >= 0 && ubSectorId < 256)
|
|
{
|
|
// Set placement type for this sector. Only first array has this set, as it is not difficulty-dependent.
|
|
gBloodcatPlacements[ ubSectorId ][0].PlacementType = pData->CurPlacement[0].PlacementType;
|
|
for (UINT8 x = 0; x < 4; x++)
|
|
{
|
|
if (pData->CurPlacement[0].PlacementType == 0)
|
|
{
|
|
// Ambush placement. Bloodcats will appear in this sector randomly.
|
|
gBloodcatPlacements[ ubSectorId ][x].ubMinBloodcats = pData->CurPlacement[x].ubMinBloodcats;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubMaxBloodcats = pData->CurPlacement[x].ubMaxBloodcats;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubAmbushChance = pData->CurPlacement[x].ubAmbushChance;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubFactionAffiliation = 0;
|
|
gBloodcatPlacements[ ubSectorId ][x].fRespawn = 0;
|
|
}
|
|
|
|
else if (pData->CurPlacement[0].PlacementType == 1)
|
|
{
|
|
// Static placement. Bloodcats always appear here, but never respawn, and may be unaggressive
|
|
// to enemies.
|
|
gBloodcatPlacements[ ubSectorId ][x].ubMinBloodcats = 0;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubMaxBloodcats = pData->CurPlacement[x].ubMaxBloodcats;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubAmbushChance = 0;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubFactionAffiliation = pData->CurPlacement[x].ubFactionAffiliation;
|
|
gBloodcatPlacements[ ubSectorId ][x].fRespawn = 0;
|
|
}
|
|
|
|
else if (pData->CurPlacement[0].PlacementType == 2)
|
|
{
|
|
// Lair sector. There can be only one, and it is affected by the Quest. Bloodcats can regenerate
|
|
// their numbers here over time.
|
|
gBloodcatPlacements[ ubSectorId ][x].ubMinBloodcats = 0;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubMaxBloodcats = pData->CurPlacement[x].ubMaxBloodcats;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubAmbushChance = 0;
|
|
gBloodcatPlacements[ ubSectorId ][x].ubFactionAffiliation = 0;
|
|
gBloodcatPlacements[ ubSectorId ][x].fRespawn = pData->CurPlacement[x].fRespawn;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
else if(strcmp(name, "SectorGrid") == 0 )
|
|
{
|
|
UINT8 x, y;
|
|
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
|
|
|
y = (UINT8)pData->szCharData[0] & 0x1F;
|
|
x = (UINT8)atol(&pData->szCharData[1]);
|
|
if ( x > 0 && x <= 16 && y > 0 && y <= 16 )
|
|
{
|
|
pData->sCurSectorX = x;
|
|
pData->sCurSectorY = y;
|
|
}
|
|
THROWIFFALSE( (SECTOR(x,y) >= 0 && SECTOR(x,y) < 256) , L"Illegal sector number in BloodcatPlacements.XML" );
|
|
}
|
|
else if(strcmp(name, "ubPlacementType") == 0 )
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
|
// Only set for first array (Difficulty Irrelevant)
|
|
pData->CurPlacement[0].PlacementType = (UINT8) atol(pData->szCharData);
|
|
}
|
|
|
|
else if(strcmp(name, "NOVICE") == 0 )
|
|
{
|
|
// Just return to sector data.
|
|
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
|
}
|
|
|
|
else if(strcmp(name, "EXPERIENCED") == 0 )
|
|
{
|
|
// Just return to sector data.
|
|
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
|
}
|
|
|
|
else if(strcmp(name, "EXPERT") == 0 )
|
|
{
|
|
// Just return to sector data.
|
|
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
|
}
|
|
|
|
else if(strcmp(name, "INSANE") == 0 )
|
|
{
|
|
// Just return to sector data.
|
|
pData->curElement = BLOODCAT_ELEMENT_SECTOR;
|
|
}
|
|
|
|
else if(strcmp(name, "ubMinBloodcats") == 0 )
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->CurPlacement[pData->ubCurDifficulty].ubMinBloodcats = (UINT8) atol(pData->szCharData);
|
|
}
|
|
|
|
else if(strcmp(name, "ubMaxBloodcats") == 0 )
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->CurPlacement[pData->ubCurDifficulty].ubMaxBloodcats = (UINT8) atol(pData->szCharData);
|
|
}
|
|
|
|
else if(strcmp(name, "ubAmbushChance") == 0 )
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->CurPlacement[pData->ubCurDifficulty].ubAmbushChance = (UINT8) atol(pData->szCharData);
|
|
}
|
|
|
|
else if(strcmp(name, "ubFactionAffiliation") == 0 )
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->CurPlacement[pData->ubCurDifficulty].ubFactionAffiliation = (UINT8) atol(pData->szCharData);
|
|
}
|
|
|
|
else if(strcmp(name, "fRespawn") == 0 )
|
|
{
|
|
pData->curElement = BLOODCAT_ELEMENT_DIFFICULTY;
|
|
pData->CurPlacement[pData->ubCurDifficulty].fRespawn = (UINT8) atol(pData->szCharData);
|
|
}
|
|
|
|
pData->maxReadDepth--;
|
|
}
|
|
|
|
pData->currentDepth--;
|
|
}
|
|
|
|
|
|
BOOLEAN ReadInBloodcatPlacements(STR fileName)
|
|
{
|
|
HWFILE hFile;
|
|
UINT32 uiBytesRead;
|
|
UINT32 uiFSize;
|
|
CHAR8 * lpcBuffer;
|
|
XML_Parser parser = XML_ParserCreate(NULL);
|
|
|
|
BloodcatsParseData pData;
|
|
|
|
hFile = FileOpen( fileName, FILE_ACCESS_READ, FALSE );
|
|
if ( !hFile )
|
|
return( FALSE );
|
|
|
|
uiFSize = FileGetSize(hFile);
|
|
lpcBuffer = (CHAR8 *) MemAlloc(uiFSize+1);
|
|
|
|
//Read in block
|
|
if ( !FileRead( hFile, lpcBuffer, uiFSize, &uiBytesRead ) )
|
|
{
|
|
MemFree(lpcBuffer);
|
|
return( FALSE );
|
|
}
|
|
|
|
lpcBuffer[uiFSize] = 0; //add a null terminator
|
|
|
|
FileClose( hFile );
|
|
|
|
|
|
XML_SetElementHandler(parser, BloodcatsStartElementHandle, BloodcatsEndElementHandle);
|
|
XML_SetCharacterDataHandler(parser, BloodcatsCharacterDataHandle);
|
|
|
|
|
|
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 BloodcatPlacements.xml: %s at line %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
|
|
LiveMessage(errorBuf);
|
|
|
|
MemFree(lpcBuffer);
|
|
return FALSE;
|
|
}
|
|
|
|
MemFree(lpcBuffer);
|
|
|
|
XML_ParserFree(parser);
|
|
|
|
return TRUE;
|
|
}
|