//zilpin: pellet spread patterns externalized in XML
#include "sgp.h"
#include "overhead types.h"
#include "Soldier Control.h"
#include "overhead.h"
#include "Event Pump.h"
#include "weapons.h"
#include "Animation Control.h"
#include "Handle UI.h"
#include "Isometric Utils.h"
#include "math.h"
#include "ai.h"
#include "los.h"
#include "renderworld.h"
#include "interface.h"
#include "message.h"
#include "campaign.h"
#include "items.h"
#include "weapons.h"
#include "text.h"
#include "Soldier Profile.h"
#include "Dialogue Control.h"
#include "SkillCheck.h"
#include "Quests.h"
#include "Physics.h"
#include "Random.h"
#include "Vehicles.h"
#include "bullets.h"
#include "morale.h"
#include "SkillCheck.h"
#include "gamesettings.h"
#include "SaveLoadMap.h"
#include "Debug Control.h"
#include "expat.h"
#include "XML.h"
#define LIST_BUFFER_LEN (32)
#define LIST_BUFFER_SIZE (LIST_BUFFER_LEN * sizeof(t_SpreadPattern))
#define CALC_NEW_LIST_SIZE(c) ( LIST_BUFFER_SIZE * (1+ ((c) / LIST_BUFFER_LEN)) )
#define ARRAY_BUFFER_LEN (32)
#define ARRAY_BUFFER_SIZE (ARRAY_BUFFER_LEN * sizeof(DOUBLE))
#define CALC_NEW_ARRAY_SIZE(c) ( ARRAY_BUFFER_SIZE * (1+ ((c) / ARRAY_BUFFER_LEN)) )
struct
{
PARSE_STAGE curElement;
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH+1];
UINT32 currentDepth;
UINT32 maxReadDepth;
}
typedef spreadpatternParseData;
static void XMLCALL
spreadpatternStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts)
{
spreadpatternParseData * pData = (spreadpatternParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //are we reading this element?
{
if(strcmp(name, "SPREADPATTERNLIST") == 0 && pData->curElement == ELEMENT_NONE)
{
pData->curElement = ELEMENT_LIST;
giSpreadPatternCount = 0;
gpSpreadPattern = NULL;
gpSpreadPattern = (t_SpreadPattern *)MemAlloc( LIST_BUFFER_SIZE );
Assert(gpSpreadPattern);
memset( gpSpreadPattern, 0, LIST_BUFFER_SIZE );
pData->maxReadDepth++; //we are not skipping this element
}
else if(strcmp(name, "SPREADPATTERN") == 0 && pData->curElement == ELEMENT_LIST)
{
pData->curElement = ELEMENT_LIST;
giSpreadPatternCount++;
if( !(giSpreadPatternCount % LIST_BUFFER_LEN) ){
//End of buffer. Expand buffer.
gpSpreadPattern = (t_SpreadPattern *)MemRealloc(gpSpreadPattern, CALC_NEW_LIST_SIZE(giSpreadPatternCount) );
Assert(gpSpreadPattern);
}
memset( &(gpSpreadPattern[giSpreadPatternCount-1]) , 0 , sizeof(t_SpreadPattern) );
gpSpreadPattern[giSpreadPatternCount-1].iCount = 0;
gpSpreadPattern[giSpreadPatternCount-1].xspread = 0.0;
gpSpreadPattern[giSpreadPatternCount-1].yspread = 0.0;
gpSpreadPattern[giSpreadPatternCount-1].method = giSpreadPatternMethod_Default;
gpSpreadPattern[giSpreadPatternCount-1].x = (DOUBLE *)MemAlloc( ARRAY_BUFFER_SIZE );
Assert( gpSpreadPattern[giSpreadPatternCount-1].x );
memset( gpSpreadPattern[giSpreadPatternCount-1].x , 0 , ARRAY_BUFFER_SIZE );
gpSpreadPattern[giSpreadPatternCount-1].y = (DOUBLE *)MemAlloc( ARRAY_BUFFER_SIZE );
Assert( gpSpreadPattern[giSpreadPatternCount-1].y );
memset( gpSpreadPattern[giSpreadPatternCount-1].y , 0 , ARRAY_BUFFER_SIZE );
pData->maxReadDepth++; //we are not skipping this element
}
else if(strcmp(name, "p") == 0 )//&& pData->curElement == ELEMENT_LIST)
{
pData->curElement = ELEMENT;
gpSpreadPattern[giSpreadPatternCount-1].iCount++;
if( !(gpSpreadPattern[giSpreadPatternCount-1].iCount % ARRAY_BUFFER_LEN ) ){
//End of buffer. Expand.
gpSpreadPattern[giSpreadPatternCount-1].x = (DOUBLE *)MemRealloc(gpSpreadPattern[giSpreadPatternCount-1].x, CALC_NEW_ARRAY_SIZE(gpSpreadPattern[giSpreadPatternCount-1].iCount) );
Assert( gpSpreadPattern[giSpreadPatternCount-1].x );
gpSpreadPattern[giSpreadPatternCount-1].y = (DOUBLE *)MemRealloc(gpSpreadPattern[giSpreadPatternCount-1].y, CALC_NEW_ARRAY_SIZE(gpSpreadPattern[giSpreadPatternCount-1].iCount) );
Assert( gpSpreadPattern[giSpreadPatternCount-1].y );
}
gpSpreadPattern[giSpreadPatternCount-1].x[ gpSpreadPattern[giSpreadPatternCount-1].iCount - 1 ] = 0.0;
gpSpreadPattern[giSpreadPatternCount-1].y[ gpSpreadPattern[giSpreadPatternCount-1].iCount - 1 ] = 0.0;
pData->maxReadDepth++; //we are not skipping this element
}
else if( //pData->curElement == ELEMENT &&
( strcmp(name, "x") == 0
|| strcmp(name, "y") == 0
|| strcmp(name, "xspread") == 0
|| strcmp(name, "yspread") == 0
|| strcmp(name, "NAME") == 0
|| strcmp(name, "method") == 0
))
{
pData->curElement = ELEMENT_PROPERTY;
pData->maxReadDepth++; //we are not skipping this element
}
pData->szCharData[0] = '\0';
}
pData->currentDepth++;
}
static void XMLCALL
spreadpatternCharacterDataHandle(void *userData, const XML_Char *str, int len)
{
spreadpatternParseData * pData = (spreadpatternParseData *)userData;
if( (pData->currentDepth <= pData->maxReadDepth) &&
(strlen(pData->szCharData) < MAX_CHAR_DATA_LENGTH)
&& pData->curElement == ELEMENT_PROPERTY
){
strncat(pData->szCharData,str,__min((unsigned int)len,MAX_CHAR_DATA_LENGTH-strlen(pData->szCharData)));
}
}
static void XMLCALL
spreadpatternEndElementHandle(void *userData, const XML_Char *name)
{
DOUBLE d;
spreadpatternParseData * pData = (spreadpatternParseData *)userData;
if(pData->currentDepth <= pData->maxReadDepth) //we're at the end of an element that we've been reading
{
if(strcmp(name, "SPREADPATTERNLIST") == 0)
{
pData->curElement = ELEMENT_NONE;
}
else if(strcmp(name, "SPREADPATTERN") == 0)
{
pData->curElement = ELEMENT_LIST;
}
else if(strcmp(name, "p") == 0)
{
//I would prefer the format to be:
//