LOBOT code (by Asdow, original code by Bio).

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8755 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Sevenfm
2020-02-15 16:19:35 +00:00
parent 25701acf7b
commit 8e9f9cb8a1
51 changed files with 9659 additions and 1730 deletions
@@ -0,0 +1,212 @@
#include "AbstractXMLLoader.h"
namespace LogicalBodyTypes {
AbstractXMLLoader::AbstractXMLLoader(XML_StartElementHandler startHandler, XML_EndElementHandler endHandler, XML_CharacterDataHandler charHandler, ParseDataFactoryFunc parseDataFactF) {
startElementHandler = startHandler;
endElementHandler = endHandler;
characterDataHandler = charHandler;
parseDataFactFuncPntr = parseDataFactF;
}
AbstractXMLLoader::~AbstractXMLLoader(void) {
}
AbstractXMLLoader::ParseData::ParseData(XML_Parser* parser) {
pParser = parser;
state = E_NONE;
level = 0;
szCharData[0] = '\0';
szErrorTxt[0] = '\0';
}
AbstractXMLLoader::ParseData* AbstractXMLLoader::MakeParseData(XML_Parser* parser) {
return new ParseData(parser);
}
bool AbstractXMLLoader::LoadFromFile(const char* directoryName, const char* fileName) {
HWFILE hFile;
UINT32 uiBytesRead;
UINT32 uiFSize;
CHAR8* lpcBuffer;
char fileNameFull[MAX_PATH + 1];
if (strlen(fileName) + strlen(directoryName) >= MAX_PATH) {
LiveMessage("Can't load file. Concatinated filename too long for buffer!");
return false;
}
SetDirectoryName(directoryName);
SetFileName(fileName);
strcpy(fileNameFull, directoryName);
strcat(fileNameFull, fileName);
XML_Parser parser = XML_ParserCreate(NULL);
AbstractXMLLoader::ParseData* data = parseDataFactFuncPntr(&parser);
std::string msg = "Loading ";
msg += fileName;
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, msg.c_str());
hFile = FileOpen(fileNameFull, FILE_ACCESS_READ, FALSE);
if (!hFile) {
delete data;
return false;
}
uiFSize = FileGetSize(hFile);
lpcBuffer = (CHAR8*)MemAlloc(uiFSize + 1);
if (!FileRead(hFile, lpcBuffer, uiFSize, &uiBytesRead)) {
MemFree(lpcBuffer);
delete data;
return false;
}
lpcBuffer[uiFSize] = 0;
FileClose(hFile);
ExternalEntityArgs eeArgs;
eeArgs.directoryName = directoryName;
eeArgs.fileName = fileName;
eeArgs.pParser = &parser;
XML_SetElementHandler(parser, startElementHandler, endElementHandler);
XML_SetCharacterDataHandler(parser, characterDataHandler);
XML_SetUserData(parser, data);
XML_SetExternalEntityRefHandler(parser, ExternalEntityHandler);
XML_SetExternalEntityRefHandlerArg(parser, (void*)&eeArgs);
try {
if (!XML_Parse(parser, lpcBuffer, uiFSize, TRUE)) {
CHAR8 errorBuf[512];
sprintf(errorBuf, "XML Parser Error in %s[%d]: %s", fileNameFull, XML_GetCurrentLineNumber(parser), XML_ErrorString(XML_GetErrorCode(parser)));
LiveMessage(errorBuf);
MemFree(lpcBuffer);
delete data;
return false;
}
} catch (XMLParseException e) {
CHAR8 errorBuf[512];
sprintf(errorBuf, "XML Parser Exception in %s[%d]: %s", fileNameFull, e._LINE, e.what());
LiveMessage(errorBuf);
MemFree(lpcBuffer);
XML_ParserFree(parser);
delete data;
return false;
}
MemFree(lpcBuffer);
XML_ParserFree(parser);
delete data;
return true;
}
int XMLCALL AbstractXMLLoader::ExternalEntityHandler(XML_Parser args, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId) {
ExternalEntityArgs* eArgs = (ExternalEntityArgs*)args;
char fileNameFull[MAX_PATH + 1];
UINT32 uiBytesRead;
UINT32 uiFSize;
CHAR8* lpcBuffer;
HWFILE hFile;
if (strlen(eArgs->directoryName) + strlen(systemId) >= MAX_PATH) {
LiveMessage("Can't load file specified in external entity. Concatinated filename too long for buffer!");
return XML_STATUS_ERROR;
}
strcpy(fileNameFull, eArgs->directoryName);
strcat(fileNameFull, systemId);
hFile = FileOpen(fileNameFull, FILE_ACCESS_READ, FALSE);
if (!hFile) {
LiveMessage("File specified in external entity can't be opened!");
return XML_STATUS_ERROR;
}
uiFSize = FileGetSize(hFile);
lpcBuffer = (CHAR8*)MemAlloc(uiFSize + 1);
if (!FileRead(hFile, lpcBuffer, uiFSize, &uiBytesRead)) {
LiveMessage("File specified in external entity couldn't be read!");
MemFree(lpcBuffer);
return XML_STATUS_ERROR;
}
lpcBuffer[uiFSize] = 0;
FileClose(hFile);
XML_Parser extParser = XML_ExternalEntityParserCreate(*eArgs->pParser, context, NULL);
ParseData* data = (ParseData*)XML_GetUserData(*eArgs->pParser);
data->pParser = &extParser;
try {
if (!XML_Parse(extParser, lpcBuffer, uiFSize, TRUE)) {
CHAR8 errorBuf[512];
sprintf(errorBuf, "XML Parser Error in external entity %s[%d]: %s", systemId, XML_GetCurrentLineNumber(extParser), XML_ErrorString(XML_GetErrorCode(extParser)));
LiveMessage(errorBuf);
return XML_STATUS_ERROR;
}
} catch (XMLParseException e) {
CHAR8 errorBuf[512];
sprintf(errorBuf, "XML Parser Exception in external entity %s[%d]: %s", systemId, e._LINE, e.what());
LiveMessage(errorBuf);
XML_ParserFree(extParser);
return XML_STATUS_ERROR;
}
data->pParser = eArgs->pParser;
XML_ParserFree(extParser);
return XML_STATUS_OK;
};
const char* AbstractXMLLoader::GetFileName() {
return fileName;
}
const char* AbstractXMLLoader::GetDirectoryName() {
return directoryName;
}
void AbstractXMLLoader::SetFileName(const char* fileName) {
strcpy(this->fileName, fileName);
}
void AbstractXMLLoader::SetDirectoryName(const char* directoryName) {
strcpy(this->directoryName, directoryName);
}
const XML_Char* AbstractXMLLoader::GetAttribute(const XML_Char* name, const XML_Char** atts) {
for (const XML_Char** pIter = atts; *pIter != NULL; pIter++) {
const XML_Char* key = *pIter++;
if (strcmp(key, name) == 0) return *pIter;
}
return NULL;
}
bool AbstractXMLLoader::ConvertStringToINT8(const XML_Char* num, INT8* int8) {
long l = strtol(num, NULL, 10);
if (l > 127 || l < -128) return false;
if (l == 0 && strcmp(num, "0") != 0) return false;
*int8 = (INT8)l;
return true;
}
bool AbstractXMLLoader::ConvertStringToUINT8(const XML_Char* num, UINT8* uInt8) {
unsigned long ul = strtoul(num, NULL, 10);
if (ul > 255) return false;
if (ul == 0 && strcmp(num, "0") != 0) return false;
*uInt8 = (UINT8)ul;
return true;
}
bool AbstractXMLLoader::ConvertStringToINT32(const XML_Char* num, INT32* int32) {
long l = strtol(num, NULL, 10);
// TODO: add range checks also for long types (and use the defined macros)
// TODO: string should be trimmed (other convert functions also)
if (l == 0 && strcmp(num, "0") != 0) return false;
*int32 = (INT32)l;
return true;
}
bool AbstractXMLLoader::ConvertStringToUINT32(const XML_Char* num, UINT32* uInt32) {
unsigned long ul = strtoul(num, NULL, 10);
if (ul == 0 && strcmp(num, "0") != 0) return false;
*uInt32 = ul;
return true;
}
bool AbstractXMLLoader::ConvertStringToBOOLEAN(const XML_Char* num, BOOLEAN* fBoolean) {
unsigned long ul = strtoul(num, NULL, 10);
if (ul == 0 && strcmp(num, "0") != 0) return false;
*fBoolean = ul != 0;
return true;
}
}
@@ -0,0 +1,84 @@
#pragma once
#ifndef _LBT_ABSTRACTXMLLOADER__H_
#define _LBT_ABSTRACTXMLLOADER__H_
#include <string>
#include <map>
#include "expat.h"
#include "Types.h"
#include "XML.h"
#include "TopicIDs.h"
#include "TopicOps.h"
#include "DEBUG.H"
#include "FileMan.h"
#include "MemMan.h"
#include "Debug Control.h"
#include "Sys Globals.h"
#include "LogicalBodyTypes/Singleton.h"
#include "LogicalBodyTypes/XMLParseException.h"
namespace LogicalBodyTypes {
class AbstractXMLLoader : public ISingleton<AbstractXMLLoader>
{
protected:
enum ParseState {
E_NONE,
FIRST_SUBCLASS_STATE
};
class ParseData {
public:
ParseData(XML_Parser* parser = NULL);
XML_Parser* pParser;
int state; // we sacrifice type safety for the enumerators so subclasses can define their own states
UINT32 level;
CHAR8 szCharData[MAX_CHAR_DATA_LENGTH + 1];
CHAR8 szErrorTxt[MAX_PATH + 1];
} typedef ParseData;
struct ExternalEntityArgs {
const char* directoryName;
const char* fileName;
XML_Parser* pParser;
} typedef ExternalEntityArgs;
typedef ParseData* (*ParseDataFactoryFunc) (XML_Parser* parser);
private:
XML_StartElementHandler startElementHandler;
XML_EndElementHandler endElementHandler;
XML_CharacterDataHandler characterDataHandler;
ParseDataFactoryFunc parseDataFactFuncPntr;
char directoryName[MAX_PATH + 1];
char fileName[MAX_PATH + 1];
public:
AbstractXMLLoader(XML_StartElementHandler startHandler, XML_EndElementHandler endHandler, XML_CharacterDataHandler charHandler, ParseDataFactoryFunc parseDataFactF = MakeParseData);
~AbstractXMLLoader(void);
bool LoadFromFile(const char* directoryName, const char* fileName);
const char* GetFileName();
const char* GetDirectoryName();
void SetFileName(const char* fileName);
void SetDirectoryName(const char* directoryName);
protected:
static const XML_Char* GetAttribute(const XML_Char* name, const XML_Char** atts);
static bool ConvertStringToINT8(const XML_Char* num, INT8* uInt8);
static bool ConvertStringToUINT8(const XML_Char* num, UINT8* uInt8);
static bool ConvertStringToINT32(const XML_Char* num, INT32* int32);
static bool ConvertStringToUINT32(const XML_Char* num, UINT32* uInt32);
static bool ConvertStringToBOOLEAN(const XML_Char* num, BOOLEAN* fBoolean);
static ParseData* MakeParseData(XML_Parser* parser);
private:
static AbstractXMLLoader& Instance();
static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts);
static void XMLCALL EndElementHandle(void* userData, const XML_Char* name);
static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len);
static int XMLCALL ExternalEntityHandler(XML_Parser args, const XML_Char *context, const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId);
};
}
#endif
+59
View File
@@ -0,0 +1,59 @@
#include "BodyType.h"
namespace LogicalBodyTypes {
BodyType::BodyType(UINT32 cacheSize, Filter* filterP) {
filter = filterP;
hasSurfaces = false;
cache = new SurfaceCache(cacheSize);
animstates.resize(NUMANIMATIONSTATES);
physAnimSurfaces.resize(NUMANIMATIONSURFACETYPES);
for (int i = 0; i < NUMANIMATIONSTATES; i++) {
animstates[i].resize(Layers::Instance().GetCount());
}
for (int i = 0; i < NUMANIMATIONSURFACETYPES; i++) {
physAnimSurfaces[i].resize(Layers::Instance().GetCount());
}
// initialize body type specific layer properties with the layer specific layer properties.
Layers::LayerPropertiesVector::size_type numLayers = Layers::Instance().GetCount();
layerProperties.resize(numLayers);
for (Layers::LayerPropertiesVector::size_type layer = 0; layer < numLayers; layer++) {
layerProperties[layer] = Layers::Instance().GetLayerProperties(layer);
}
}
BodyType::~BodyType(void) {
delete cache;
}
void BodyType::AddSurfaceForAnimState(UINT16 usAnimState, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType, Filter* filter, PaletteTable* paletteTable) {
STRUCTURE_FILE_REF* pStructFile = SurfaceDB::Instance().GetStructFile(animSurfaceType);
UINT32 idx = cache->AddSurface(animSurfaceType, pStructFile);
UINT32 idxAlpha = 0;
if (alphaSurfaceType != NULL) {
idxAlpha = cache->AddSurface(alphaSurfaceType, pStructFile);
}
animstates[usAnimState][layer].push_back(FilterSurfaceTypePair(filter, FilterSurfaceTypePair::second_type(idx, LogicalSurfaceType(animSurfaceType, alphaSurfaceType, idxAlpha, paletteTable))));
hasSurfaces = true;
}
void BodyType::AddSurfaceForPhysSurface(UINT16 usAnimSurface, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType, Filter* filter, PaletteTable* paletteTable) {
STRUCTURE_FILE_REF* pStructFile = SurfaceDB::Instance().GetStructFile(animSurfaceType);
UINT32 idx = cache->AddSurface(animSurfaceType, pStructFile);
UINT32 idxAlpha = 0;
if (alphaSurfaceType != NULL) {
idxAlpha = cache->AddSurface(alphaSurfaceType, pStructFile);
}
physAnimSurfaces[usAnimSurface][layer].push_back(FilterSurfaceTypePair(filter, FilterSurfaceTypePair::second_type(idx, LogicalSurfaceType(animSurfaceType, alphaSurfaceType, idxAlpha, paletteTable))));
hasSurfaces = true;
}
void BodyType::SetLayerProperties(Layers::LayerPropertiesVector::size_type index, Layers::LayerProperties properties) {
layerProperties[index] = properties; // TODO range check?
}
const Layers::LayerProperties* BodyType::GetLayerProperties(Layers::LayerPropertiesVector::size_type index) {
return &layerProperties[index]; // TODO range check?
}
}
+107
View File
@@ -0,0 +1,107 @@
#pragma once
#ifndef _LBT_BODYTYPE__H_
#define _LBT_BODYTYPE__H_
#include "LogicalBodyTypes/Layers.h"
#include "LogicalBodyTypes/Filter.h"
#include "LogicalBodyTypes/SurfaceCache.h"
#include "LogicalBodyTypes/SurfaceDB.h"
#include "LogicalBodyTypes/PaletteDB.h"
#include "LogicalBodyTypes/PaletteTable.h"
#include "Animation Data.h"
#include "Animation Control.h"
namespace LogicalBodyTypes {
class BodyType {
public:
struct LogicalSurfaceType {
LogicalSurfaceType(AnimationSurfaceType* physicalSurfaceType, AnimationSurfaceType* alphaSurfaceType, UINT32 alphaSurfaceIdx, PaletteTable* paletteTable)
: paletteTable(paletteTable), physicalSurfaceType(physicalSurfaceType), alphaSurfaceType(alphaSurfaceType), alphaSurfaceIdx(alphaSurfaceIdx) {};
const PaletteTable* paletteTable;
const AnimationSurfaceType* physicalSurfaceType;
const AnimationSurfaceType* alphaSurfaceType;
UINT32 alphaSurfaceIdx;
} typedef LogicalSurfaceType;
private:
typedef std::pair<Filter*, std::pair<UINT32, LogicalSurfaceType> > FilterSurfaceTypePair;
typedef std::list<FilterSurfaceTypePair> FilterSurfaceTypeList;
typedef std::vector<FilterSurfaceTypeList> LayerVector;
typedef std::vector<LayerVector> AnimStateVector;
typedef std::vector<LayerVector> PhysAnimSurfaceVector;
AnimStateVector animstates;
PhysAnimSurfaceVector physAnimSurfaces;
Layers::LayerPropertiesVector layerProperties;
Filter* filter;
bool hasSurfaces;
UINT32 numCacheNodes;
UINT32 maxCacheNodes;
SurfaceCache* cache;
public:
BodyType(UINT32 cacheSize, Filter* filterP = NULL);
~BodyType(void);
void AddSurfaceForAnimState(UINT16 usAnimState, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType = NULL, Filter* filter = NULL, PaletteTable* paletteTable = NULL);
void AddSurfaceForPhysSurface(UINT16 usAnimSurface, Layers::LayerPropertiesVector::size_type layer, AnimationSurfaceType* animSurfaceType, AnimationSurfaceType* alphaSurfaceType = NULL, Filter* filter = NULL, PaletteTable* paletteTable = NULL);
void SetLayerProperties(Layers::LayerPropertiesVector::size_type index, Layers::LayerProperties properties);
const Layers::LayerProperties* GetLayerProperties(Layers::LayerPropertiesVector::size_type index);
inline bool Match(SOLDIERTYPE* pSoldier) {
if (filter != NULL) return filter->Match(pSoldier);
return false; // no filter specified - matches none
};
inline bool HasSurfaces() {
return hasSurfaces;
}
inline BodyType::LogicalSurfaceType* GetLogicalSurfaceType(Layers::LayerPropertiesVector::size_type layer, SOLDIERTYPE* pSoldier) {
FilterSurfaceTypeList::iterator end = animstates[pSoldier->usAnimState][layer].end();
for (FilterSurfaceTypeList::iterator i = animstates[pSoldier->usAnimState][layer].begin(); i != end; i++) {
Filter* f = (*i).first;
if (f != NULL) {
if (f->Match(pSoldier)) {
bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL;
if ((*i).second.second.alphaSurfaceType != NULL) {
isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL);
}
return (isLoaded) ? &(*i).second.second : NULL;
}
} else { // no filter specified - matches all
bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL;
if ((*i).second.second.alphaSurfaceType != NULL) {
isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL);
}
return (isLoaded) ? &(*i).second.second : NULL;
}
}
end = physAnimSurfaces[pSoldier->usAnimSurface][layer].end();
for (FilterSurfaceTypeList::iterator i = physAnimSurfaces[pSoldier->usAnimSurface][layer].begin(); i != end; i++) {
Filter* f = (*i).first;
if (f != NULL) {
if (f->Match(pSoldier)) {
bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL;
if ((*i).second.second.alphaSurfaceType != NULL) {
isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL);
}
return (isLoaded) ? &(*i).second.second : NULL;
}
} else { // no filter specified - matches all
bool isLoaded = cache->GetLoadedSurface((*i).second.first) != NULL;
if ((*i).second.second.alphaSurfaceType != NULL) {
isLoaded = isLoaded && (cache->GetLoadedSurface((*i).second.second.alphaSurfaceIdx) != NULL);
}
return (isLoaded) ? &(*i).second.second : NULL;
}
}
return NULL;
};
};
}
#endif
File diff suppressed because it is too large Load Diff
+78
View File
@@ -0,0 +1,78 @@
#pragma once
#ifndef _LBT_BODYTYPEDB__H_
#define _LBT_BODYTYPEDB__H_
#include <list>
#include "LogicalBodyTypes/Singleton.h"
#include "LogicalBodyTypes/AbstractXMLLoader.h"
#include "LogicalBodyTypes/BodyType.h"
#include "LogicalBodyTypes/FilterDB.h"
#include "LogicalBodyTypes/SurfaceDB.h"
namespace LogicalBodyTypes {
class BodyTypeDB : public AbstractXMLLoader, public Singleton<BodyTypeDB> {
public:
using Singleton <BodyTypeDB>::Instance;
typedef std::list<BodyType*> BodyTypeList;
//TOTAL_SOLDIERS
private:
enum ParseState {
E_ELEMENT_BODYTYPES = FIRST_SUBCLASS_STATE,
E_ELEMENT_BODYTYPE,
E_ELEMENT_LAYER_CONFIGS,
E_ELEMENT_LAYER_CONFIG,
E_ELEMENT_SURFACES,
E_ELEMENT_LAYER,
E_ELEMENT_PROP,
E_ELEMENT_SURFACE
};
struct ParseData : public AbstractXMLLoader::ParseData { // shadow ParseData type and also extend the ParseData stuct of the base class
ParseData(XML_Parser* parser) : AbstractXMLLoader::ParseData(parser) {
currentBodyType = NULL;
filter = NULL;
paletteTable = NULL;
layer = -1;
layerPropertiesConfig.clear();
};
~ParseData() {
if (currentBodyType != NULL) delete currentBodyType;
};
BodyType* currentBodyType;
Filter* filter;
PaletteTable* paletteTable;
Layers::LayerPropertiesVector::size_type layer;
std::map<Layers::LayerPropertiesVector::size_type, Layers::LayerProperties> layerPropertiesConfig;
} typedef ParseData;
BodyTypeList bodyTypes;
public:
BodyTypeDB(void);
~BodyTypeDB(void);
void Add(BodyType* bodyType);
inline BodyType* Find(SOLDIERTYPE* pSoldier) {
BodyTypeList::iterator end = bodyTypes.end();
for (BodyTypeList::iterator i = bodyTypes.begin(); i != end; i++) {
// if we find a bodytype, but it does not have any surfaces, it is meant to exclude objects
// from being matched against bodytypes so we return NULL in that case.
if ((*i)->Match(pSoldier)) return ((*i)->HasSurfaces()) ? *i : NULL;
}
return NULL;
};
private:
static void RegisterEnumerators();
static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts);
static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len);
static void XMLCALL EndElementHandle(void* userData, const XML_Char* name);
static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId);
static AbstractXMLLoader::ParseData* MakeParseData(XML_Parser* parser); // shadow factory function for ParseData instances
};
}
#endif
@@ -0,0 +1,64 @@
#include "EnumeratorDB.h"
namespace LogicalBodyTypes {
EnumeratorDB::EnumeratorDB() {
}
EnumeratorDB::~EnumeratorDB(void) {
}
void EnumeratorDB::AddEnum(std::string enumName, int num, char* strEnumerators, ...) {
int strLen = strlen(strEnumerators);
char* str = new char[strLen + 1];
strcpy(str, strEnumerators);
// for detecting synchronization issue between the actual enum declaration and the DB insertion
// assert that the number of provided enumerators matches the expected number
int numSemiColons = 0;
for (int i = 0; i < strLen; i++) if (strEnumerators[i] == ',') numSemiColons++;
// TODO: remove output to cout Log this event somehow not just do the assertion!
if (numSemiColons + 1 != num) {
std::cout << enumName << " expected " << num << " got " << numSemiColons + 1 << std::endl;
}
assert(numSemiColons + 1 == num);
// if enumeration already in DB, delete
EnumerationMap::iterator i = enumerations.find(enumName);
if (i != enumerations.end()) enumerations.erase(enumName);
char* token = strtok(str, ", ");
va_list vl;
va_start(vl, strEnumerators);
for (int i = 0; i < num; i++) {
enumerations[enumName][token] = va_arg(vl, int);
token = strtok(NULL, ", ");
}
va_end(vl);
delete str;
}
bool EnumeratorDB::GetEnumeratorStr(const char* enumeration, int enumerator, std::string& str) {
EnumerationMap::iterator i = enumerations.find(enumeration);
if (i != enumerations.end()) {
for (EnumeratorMap::iterator j = i->second.begin(); j != i->second.end(); j++) {
if (j->second == enumerator) {
str = j->first;
return true;
}
}
}
return false;
}
bool EnumeratorDB::GetEnumeratorByStr(const char* enumeration, const char* enumerationStr, int& enumerator) {
EnumerationMap::iterator i = enumerations.find(enumeration);
if (i == enumerations.end()) return false;
EnumeratorMap::iterator j = i->second.find(enumerationStr);
if (j == i->second.end()) return false;
enumerator = j->second;
return true;
}
}
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#ifndef _LBT_ENUMERATORDB__H_
#define _LBT_ENUMERATORDB__H_
#include "LogicalBodyTypes/Singleton.h"
#include <string>
#include <map>
#include <stdarg.h>
#include <iostream>
#define LOGBT_ENUMDB_ADD(enumName, count, ...) EnumeratorDB::Instance().AddEnum(enumName, count, #__VA_ARGS__, __VA_ARGS__)
namespace LogicalBodyTypes {
class EnumeratorDB : public Singleton<EnumeratorDB> {
public:
typedef std::map<std::string, int> EnumeratorMap;
typedef std::map<std::string, EnumeratorMap> EnumerationMap;
EnumerationMap enumerations;
public:
EnumeratorDB();
~EnumeratorDB();
void AddEnum(std::string enumName, int num, char* strEnumerators, ...);
// Note: this will return the FIRST enumerator of the specified enumeration
// that matches the provided ordinal value!
// Also: it is expected that this will only be called in situations where the efficiency is not relevant
// (like for generating a list of enumerators for testing/documentation)
// otherwise a different mechanism for storing the enumerations should be implemented.
bool GetEnumeratorStr(const char* enumeration, int enumerator, std::string& str);
bool GetEnumeratorByStr(const char* enumeration, const char* enumerationStr, int& enumerator);
};
};
#endif
+303
View File
@@ -0,0 +1,303 @@
#include "Filter.h"
namespace LogicalBodyTypes {
Filter::Filter(void) {
}
Filter::~Filter(void) {
for (CriteriaMap::iterator i = criteria.begin(); i != criteria.end(); i++) {
if (i->first & _TYPE_STRING) {
if (i->first & _TYPE_LIST) delete i->second.stringList;
else delete i->second.string;
}
else if (i->first & _TYPE_INTEGER) {
if (i->first & _TYPE_PAIR) delete i->second.numberPair;
else if (i->first & _TYPE_LIST) delete i->second.numberList;
}
}
}
void Filter::AddCriterion(UINT32 type, std::wstring& value) {
type &= ~_TYPE_INTEGER;
type |= _TYPE_STRING;
std::wstring* str = new std::wstring(value);
criterionVariant val;
val.string = str;
criteria.insert(CriteriaMap::value_type(type, val));
}
void Filter::AddCriterion(UINT32 type, STR16 value) {
type &= ~_TYPE_INTEGER;
type |= _TYPE_STRING;
std::wstring* str = new std::wstring(value);
criterionVariant val;
val.string = str;
criteria.insert(CriteriaMap::value_type(type, val));
}
void Filter::AddCriterion(UINT32 type, StringList& list) {
type &= ~_TYPE_INTEGER;
type |= _TYPE_STRING;
criterionVariant val;
val.stringList = new StringList(list); // I don't trust copy constructors, but oh well...
criteria.insert(CriteriaMap::value_type(type, val));
}
void Filter::AddCriterion(UINT32 type, INT32 value) {
type &= ~_TYPE_STRING;
type |= _TYPE_INTEGER;
criterionVariant val;
val.number = value;
criteria.insert(CriteriaMap::value_type(type, val));
}
void Filter::AddCriterion(UINT32 type, INT32 value1, INT32 value2) {
type &= ~_TYPE_STRING;
type |= _TYPE_INTEGER;
criterionVariant val;
val.numberPair = new NumberPair(value1, value2);
criteria.insert(CriteriaMap::value_type(type, val));
}
void Filter::AddCriterion(UINT32 type, NumberList& list) {
type &= ~_TYPE_STRING;
type |= _TYPE_INTEGER;
criterionVariant val;
val.numberList = new NumberList(list); // I don't trust copy constructors, but oh well...
criteria.insert(CriteriaMap::value_type(type, val));
}
void Filter::AddCriterion(UINT32 type, Filter* filter) {
type |= _TYPE_FILTER;
criterionVariant val;
val.filter = filter;
criteria.insert(CriteriaMap::value_type(type, val));
}
void Filter::Dump(std::wstringstream& stream) {
stream << L"<-------- Filter" << std::endl;
for (CriteriaMap::iterator ii = criteria.begin(); ii != criteria.end(); ii++) {
UINT32 flags = ii->first & _UNSET_FLAGS;
UINT32 cType = ii->first & ~_UNSET_FLAGS;
std::string op = "";
if (flags & _REQ_OR) op += "OR";
if (flags & _REQ_AND) op += "AND";
std::string cmpop = "";
if ((flags & _REQ_NOT) && (flags & _REQ_EQ)) cmpop = "!=";
if (((flags & _REQ_NOT) != _REQ_NOT) && (flags & _REQ_EQ)) cmpop = "==";
if ((flags & _REQ_NOT) && (flags & _REQ_GT)) cmpop = ">";
if (((flags & _REQ_NOT) != _REQ_NOT) && (flags & _REQ_GT)) cmpop = "<=";
if ((flags & _REQ_NOT) && (flags & _REQ_LT)) cmpop = "<";
if (((flags & _REQ_NOT) != _REQ_NOT) && (flags & _REQ_LT)) cmpop = ">=";
if (flags & Filter::_TYPE_STRING) {
std::string enumStr;
EnumeratorDB::Instance().GetEnumeratorStr("StringFilterCriterionTypes", cType, enumStr);
stream << L"criterion: " << op << L" str " << enumStr << L" " << cmpop << L" " << *ii->second.string << std::endl;
}
if (flags & Filter::_TYPE_INTEGER) {
std::string enumStr;
// first try to find the enumerator in the integer criterion type list then in the enum list
bool foundEnumerator = EnumeratorDB::Instance().GetEnumeratorStr("IntegerFilterCriterionTypes", cType, enumStr);
if (!foundEnumerator) EnumeratorDB::Instance().GetEnumeratorStr("EnumFilterCriterionTypes", cType, enumStr);
stream << L"criterion: " << op << L" str " << enumStr << L" " << cmpop << L" " << ii->second.number << std::endl;
}
// TODO: drop method or update to match the additional types that have been added.
}
stream << L"-------->" << std::endl;
}
// quite an ugly implementation. Should be re-done
bool Filter::Match(SOLDIERTYPE* pSoldier) {
bool orReq = false;
bool orRes = false;
UINT32 operation = _REQ_AND;
// TODO: make sure container is a BT, since we need no random access anyways!
for (CriteriaMap::iterator ii = criteria.begin(); ii != criteria.end(); ii++) {
UINT32 r = ii->first;
if ((r & _REQ_AND) == _REQ_AND) {
operation = _REQ_AND;
}
else if ((r & _REQ_OR) == _REQ_OR) {
if (orRes) continue;
orReq = true;
operation = _REQ_OR;
}
char sgn;
if (r & _TYPE_INTEGER) {
INT32 cmp_val;
UINT32 q = r & ~_UNSET_FLAGS;
switch (q) {
case REQ_BODYTYPE:
cmp_val = pSoldier->ubBodyType;
break;
case REQ_TEAM:
cmp_val = pSoldier->bTeam;
break;
case REQ_SOLDIER_CLASS:
cmp_val = pSoldier->ubSoldierClass;
break;
case REQ_CIVILIANGROUP:
cmp_val = pSoldier->ubCivilianGroup;
break;
case REQ_CAMO:
cmp_val = pSoldier->bCamo;
break;
case REQ_URBANCAMO:
cmp_val = pSoldier->urbanCamo;
break;
case REQ_DESERTCAMO:
cmp_val = pSoldier->desertCamo;
break;
case REQ_SNOWCAMO:
cmp_val = pSoldier->snowCamo;
break;
case REQ_EXPLEVEL:
cmp_val = pSoldier->stats.bExpLevel;
break;
case REQ_STRENGTH:
cmp_val = pSoldier->stats.bStrength;
break;
case REQ_LEADERSHIP:
cmp_val = pSoldier->stats.bLeadership;
break;
case REQ_WISDOM:
cmp_val = pSoldier->stats.bWisdom;
break;
/* case REQ_SKILLTRAIT1:
cmp_val = pSoldier->stats.ubSkillTrait1;
break;
case REQ_SKILLTRAIT2:
cmp_val = pSoldier->stats.ubSkillTrait2;
break;*/
case REQ_FACEINDEX:
if (pSoldier->ubProfile == NO_PROFILE
|| pSoldier->ubProfile < 1
|| pSoldier->ubProfile > NUM_PROFILES - 2) return false;
cmp_val = gMercProfiles[pSoldier->ubProfile].ubFaceIndex;
break;
case REQ_WEAPON_IN_HAND:
cmp_val = WeaponInHand(pSoldier);
break;
case REQ_MERC_TYPE:
cmp_val = pSoldier->ubWhatKindOfMercAmI;
break;
case REQ_WEAPON_CLASS:
cmp_val = Weapon[pSoldier->inv[HANDPOS].usItem].ubWeaponClass;
break;
case REQ_WEAPON_TYPE:
cmp_val = Weapon[pSoldier->inv[HANDPOS].usItem].ubWeaponType;
break;
case REQ_CALIBRE:
cmp_val = Weapon[pSoldier->inv[HANDPOS].usItem].ubCalibre;
break;
case REQ_VEST_AMOR_PROTECTION:
cmp_val = Armour[Item[pSoldier->inv[VESTPOS].usItem].ubClassIndex].ubProtection;
break;
case REQ_VEST_AMOR_COVERAGE:
cmp_val = Armour[Item[pSoldier->inv[VESTPOS].usItem].ubClassIndex].ubCoverage;
break;
case REQ_HELMET_AMOR_PROTECTION:
cmp_val = Armour[Item[pSoldier->inv[HELMETPOS].usItem].ubClassIndex].ubProtection;
break;
case REQ_HELMET_AMOR_COVERAGE:
cmp_val = Armour[Item[pSoldier->inv[HELMETPOS].usItem].ubClassIndex].ubCoverage;
break;
default:
if (q < NUM_REQTYPESINV) {
cmp_val = pSoldier->inv[q].usItem;
} else {
// not implemented. We should log this somehow(must be cached).
return false;
}
}
if (r & _TYPE_LIST) {
NumberList* nl = ii->second.numberList;
sgn = -1; // -1 or 1 doesn't matter
for (NumberList::iterator i = nl->begin(); i != nl->end(); i++) {
if (*i == cmp_val) {
sgn = 0;
break;
}
}
} else if (r & _TYPE_PAIR) {
NumberPair* nl = ii->second.numberPair;
// TODO: resolve compiler warning about usigned/signed and the comparison ops?!?
sgn = (nl->second > cmp_val) ? -1 : (nl->first < cmp_val) ? 1 : 0;
} else {
sgn = (ii->second.number > cmp_val) ? -1 : (ii->second.number < cmp_val) ? 1 : 0;
}
} else if (r & _TYPE_STRING) {
// string comparison is quite costly at the moment. should be avoided or reimplemented.
// would probably be much more sensible just to loop and make a wchar for wchar check.
// I wanted to use the signum compare as with the integer values. But since that
// is more like a code gimmick than an actual useful feature, probably better to
// drop the check for > < for strings alltogether.
std::wstring cmp_val;
CHAR16 wStr[31];
switch (r & ~_UNSET_FLAGS) {
case REQ_NAME:
wcscpy(wStr, pSoldier->name);
cmp_val = wStr;
break;
case REQ_PROFILENAME:
if (pSoldier->ubProfile == NO_PROFILE
|| pSoldier->ubProfile < 1
|| pSoldier->ubProfile > NUM_PROFILES - 2) return false;
wcscpy(wStr, gMercProfiles[pSoldier->ubProfile].zName);
cmp_val = wStr;
break;
case REQ_NICKNAME:
if (pSoldier->ubProfile == NO_PROFILE
|| pSoldier->ubProfile < 1
|| pSoldier->ubProfile > NUM_PROFILES - 2) return false;
wcscpy(wStr, gMercProfiles[pSoldier->ubProfile].zNickname);
cmp_val = wStr;
break;
default:
// not implemented. We should log this somehow(must be cached).
return false;
}
if (r & _TYPE_LIST) {
StringList* sl = ii->second.stringList;
sgn = -1; // -1 or 1 doesn't matter
for (StringList::iterator i = sl->begin(); i != sl->end(); i++) {
if (*i == cmp_val) {
sgn = 0;
break;
}
}
}
else {
std::wstring* sp = ii->second.string;
sgn = cmp_val.compare(*sp);
}
} else if (r & _TYPE_FILTER) {
if (ii->second.filter == NULL) {
// TODO: log or exception
return false;
}
sgn = (ii->second.filter->Match(pSoldier)) ? 0 : -1; // -1 or 1 doesn't matter
} else {
// TODO: log or exception
return false;
}
bool res = ((r & _REQ_NOT) == _REQ_NOT) ^ (
(((r & _REQ_EQ) == _REQ_EQ) && sgn == 0)
|| (((r & _REQ_IN) == _REQ_IN) && sgn == 0)
|| (((r & _REQ_BTWN) == _REQ_BTWN) && sgn == 0)
|| (((r & _REQ_GT) == _REQ_GT) && sgn == 1)
|| (((r & _REQ_LT) == _REQ_LT) && sgn == -1)
);
if (operation == _REQ_AND) {
if (!res) return false;
} else if (operation == _REQ_OR) {
orRes |= res;
}
}
return !orReq || orRes;
};
};
+118
View File
@@ -0,0 +1,118 @@
#pragma once
#ifndef _LBT_FILTER__H_
#define _LBT_FILTER__H_
#include <string>
#include <map>
#include "DEBUG.H"
#include "Soldier Control.h"
#include "soldier profile type.h"
#include "Soldier Profile.h"
#include "Weapons.h"
#include "LogicalBodyTypes/EnumeratorDB.h"
namespace LogicalBodyTypes {
class Filter {
public:
enum ConditionTypes
{
// lowest two bytes are reserved for enumerators
REQ_HELMETPOS,
REQ_VESTPOS,
REQ_LEGPOS,
REQ_HEAD1POS,
REQ_HEAD2POS,
REQ_HANDPOS,
REQ_SECONDHANDPOS,
REQ_VESTPOCKPOS,
REQ_LTHIGHPOCKPOS,
REQ_RTHIGHPOCKPOS,
REQ_CPACKPOCKPOS,
REQ_BPACKPOCKPOS,
REQ_GUNSLINGPOCKPOS,
REQ_KNIFEPOCKPOS,
NUM_REQTYPESINV,
REQ_SEX,
REQ_MERC_TYPE,
REQ_NAME,
REQ_SOLDIER_CLASS,
REQ_TEAM,
REQ_CIVILIANGROUP,
REQ_CAMO,
REQ_URBANCAMO,
REQ_DESERTCAMO,
REQ_SNOWCAMO,
REQ_BODYTYPE,
REQ_EXPLEVEL,
REQ_STRENGTH,
REQ_LEADERSHIP,
REQ_WISDOM,
REQ_SKILLTRAIT1,
REQ_SKILLTRAIT2,
REQ_FACEINDEX,
REQ_PROFILENAME,
REQ_NICKNAME,
REQ_WEAPON_IN_HAND,
REQ_WEAPON_CLASS,
REQ_WEAPON_TYPE,
REQ_CALIBRE,
REQ_VEST_AMOR_PROTECTION,
REQ_VEST_AMOR_COVERAGE,
REQ_HELMET_AMOR_PROTECTION,
REQ_HELMET_AMOR_COVERAGE,
NUM_REQTYPES,
// 3rd byte is for operator flags
_REQ_BTWN = 0x20000,
_REQ_NOT = 0x40000,
_REQ_EQ = 0x80000,
_REQ_LT = 0x100000,
_REQ_GT = 0x200000,
_REQ_AND = 0x400000,
_REQ_OR = 0x800000,
_REQ_IN = 0x1000000,
// 4th byte is for type flags
_TYPE_STRING = 0x2000000,
_TYPE_INTEGER = 0x4000000,
_TYPE_ENUM = 0x8000000,
_TYPE_LIST = 0x10000000,
_TYPE_PAIR = 0x20000000,
_TYPE_FILTER = 0x40000000,
// TODO rename enumerator _ALL_FLAGS or somesuch
_UNSET_FLAGS = _TYPE_FILTER | _TYPE_PAIR | _TYPE_LIST | _TYPE_ENUM | _TYPE_STRING | _TYPE_INTEGER | _REQ_IN | _REQ_OR | _REQ_AND | _REQ_BTWN | _REQ_NOT | _REQ_EQ | _REQ_LT | _REQ_GT
};
typedef std::pair <INT32, INT32> NumberPair;
typedef std::list <std::wstring> StringList;
typedef std::list <INT32> NumberList;
union criterionVariant {
INT32 number;
std::wstring* string;
NumberPair* numberPair;
StringList* stringList;
NumberList* numberList;
Filter* filter;
} typedef criterionVariant;
typedef std::multimap <UINT32, criterionVariant> CriteriaMap;
public:
Filter(void);
~Filter(void);
void AddCriterion(UINT32 type, std::wstring& value);
void AddCriterion(UINT32 type, STR16 value);
void AddCriterion(UINT32 type, StringList& list);
void AddCriterion(UINT32 type, INT32 value);
void AddCriterion(UINT32 type, INT32 value1, INT32 value2);
void AddCriterion(UINT32 type, NumberList& list);
void AddCriterion(UINT32 type, Filter* filter);
void Dump(std::wstringstream& stream);
bool Match(SOLDIERTYPE* pSoldier);
private:
CriteriaMap criteria;
};
}
#endif
+689
View File
@@ -0,0 +1,689 @@
#include "FilterDB.h"
namespace LogicalBodyTypes {
FilterDB::FilterDB(void) : AbstractXMLLoader(StartElementHandle, EndElementHandle, CharacterDataHandle, MakeParseData) {
RegisterEnumerators();
}
FilterDB::~FilterDB(void) {
for (FilterMap::iterator i = filters.begin(); i != filters.end(); i++) {
delete i->second;
}
}
bool FilterDB::AddFilter(std::string name, Filter* filter) {
iterator i = filters.find(name);
if (i != filters.end()) {
return false;
}
filters[name] = filter;
return true;
}
Filter* FilterDB::FindFilter(std::string name) {
iterator i = filters.find(name);
return (i != filters.end()) ? i->second : NULL;
}
FilterDB::FilterMap::const_iterator FilterDB::begin() {
return filters.begin();
}
FilterDB::FilterMap::const_iterator FilterDB::end() {
return filters.end();
}
AbstractXMLLoader::ParseData* FilterDB::MakeParseData(XML_Parser* parser) {
return new ParseData(parser);
}
void XMLCALL FilterDB::StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts) {
ParseData* data = (ParseData*)userData;
switch (data->state) {
case E_NONE:
if (strcmp(name, "Filters") == 0) {
data->state = E_ELEMENT_FILTERS;
break;
}
case E_ELEMENT_FILTERS:
if (strcmp(name, "Filter") == 0) {
data->state = E_ELEMENT_FILTER;
data->currentFilter = new Filter();
XML_Char const* attrName = GetAttribute("name", atts);
if (attrName == NULL) throw XMLParseException("Mandatory attribute missing!", name, data->pParser);
data->filterName = attrName;
break;
}
case E_ELEMENT_FILTER:
if (strcmp(name, "AND") == 0) {
data->state = E_OPERATION;
data->operationFlags = Filter::_REQ_AND;
break;
}
if (strcmp(name, "OR") == 0) {
data->state = E_OPERATION;
data->operationFlags = Filter::_REQ_OR;
break;
}
case E_OPERATION:
{
data->state = E_CRITERION;
data->criterionType = 0;
int ord;
data->criterionName = name;
std::string enumeratorString = "Filter::REQ_";
enumeratorString += name;
if (EnumeratorDB::Instance().GetEnumeratorByStr("IntegerFilterCriterionTypes", enumeratorString.c_str(), ord)) {
data->criterionType = ord;
data->criterionType |= Filter::_TYPE_INTEGER;
}
else if (EnumeratorDB::Instance().GetEnumeratorByStr("StringFilterCriterionTypes", enumeratorString.c_str(), ord)) {
data->criterionType = ord;
data->criterionType |= Filter::_TYPE_STRING;
}
else if (EnumeratorDB::Instance().GetEnumeratorByStr("EnumFilterCriterionTypes", enumeratorString.c_str(), ord)) {
data->criterionType = ord;
data->criterionType |= Filter::_TYPE_ENUM;
}
else if (strcmp(name, "FILTER") == 0) {
data->criterionType = ord;
data->criterionType |= Filter::_TYPE_FILTER;
}
else throw XMLParseException("Unexpected element (unknown criterion)!", name, data->pParser);
XML_Char const* cmpOp = GetAttribute("op", atts);
if (cmpOp != NULL) {
if (strcmp(cmpOp, "gt") == 0) {
if ((data->criterionType & Filter::_TYPE_FILTER) == Filter::_TYPE_FILTER) {
throw XMLParseException("Greater than operator not supported for filter criterion types!", name, data->pParser);
}
data->criterionType |= Filter::_REQ_GT;
}
else if (strcmp(cmpOp, "lt") == 0) {
if ((data->criterionType & Filter::_TYPE_FILTER) == Filter::_TYPE_FILTER) {
throw XMLParseException("Lesser than operator not supported for filter criterion types!", name, data->pParser);
}
data->criterionType |= Filter::_REQ_LT;
}
else if (strcmp(cmpOp, "eq") == 0) data->criterionType |= Filter::_REQ_EQ;
else if (strcmp(cmpOp, "btwn") == 0) {
if ((data->criterionType & Filter::_TYPE_INTEGER) != Filter::_TYPE_INTEGER) {
// TODO: also allow between for enums
throw XMLParseException("Between operator only handles numerical values!", name, data->pParser);
}
data->criterionType |= Filter::_REQ_BTWN | Filter::_TYPE_PAIR;
}
else if (strcmp(cmpOp, "in") == 0) {
if (data->criterionType & (Filter::_TYPE_INTEGER | Filter::_TYPE_STRING)) {
// TODO: also allow in for enums
data->criterionType |= Filter::_REQ_IN | Filter::_TYPE_LIST;
}
else throw XMLParseException("In operator only handles numerical or string values!", name, data->pParser);
}
else throw XMLParseException("Undefined operator!", name, data->pParser);
}
else {
data->criterionType |= Filter::_REQ_EQ;
}
XML_Char const* not = GetAttribute("not", atts);
if (not != NULL) {
if (strcmp(not, "") != 0) throw XMLParseException("Not attribute must not have a value assigned!", name, data->pParser);
data->criterionType |= Filter::_REQ_NOT;
}
break;
}
default:
throw XMLParseException("Unexpected element!", name, data->pParser);
}
}
void XMLCALL FilterDB::EndElementHandle(void* userData, const XML_Char* name) {
ParseData* data = (ParseData*)userData;
switch (data->state) {
case E_CRITERION:
if (strcmp(name, data->criterionName.c_str()) == 0) {
data->state = E_OPERATION;
break;
}
case E_OPERATION:
if (((data->operationFlags & Filter::_REQ_AND) && strcmp(name, "AND") == 0) || ((data->operationFlags & Filter::_REQ_OR) && strcmp(name, "OR") == 0)) {
data->state = E_ELEMENT_FILTER;
break;
}
case E_ELEMENT_FILTER:
if (strcmp(name, "Filter") == 0) {
data->state = E_ELEMENT_FILTERS;
if (!Instance().AddFilter(data->filterName, data->currentFilter)) {
throw XMLParseException("Filter could not be added. Filter already defined!", name, data->pParser);
}
data->currentFilter = NULL; // in case an exception is raised between here and the start of the next filter element
break;
}
case E_ELEMENT_FILTERS:
if (strcmp(name, "Filters") == 0) {
data->state = E_NONE;
break;
}
default:
throw XMLParseException("Unexpected element! Closing tag missing?", name, data->pParser);
return;
}
}
void XMLCALL FilterDB::CharacterDataHandle(void* userData, const XML_Char* str, int len) {
ParseData* data = (ParseData*)userData;
switch (data->state) {
case E_CRITERION:
// TODO: trim character data!
char* text = new char[len + 1];
strncpy(text, str, len);
text[len] = '\0';
if (data->criterionType & Filter::_TYPE_STRING) {
STR16 wStr = NULL;
int len = MultiByteToWideChar(CP_UTF8, 0, text, -1, wStr, 0);
wStr = (STR16)MemAlloc(len * sizeof(CHAR16));
MultiByteToWideChar(CP_UTF8, 0, text, -1, wStr, len);
if (data->criterionType & Filter::_TYPE_LIST) {
Filter::StringList list;
wchar_t* token = wcstok(wStr, L", ");
while (token != NULL) {
list.push_back(token);
token = wcstok(NULL, L", ");
}
data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, list);
}
else {
data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, wStr);
}
MemFree(wStr);
}
else if (data->criterionType & Filter::_TYPE_INTEGER) {
if ((data->criterionType & Filter::_TYPE_LIST) || (data->criterionType & Filter::_TYPE_PAIR)) {
Filter::NumberList list;
char* token = strtok(text, ", ");
while (token != NULL) {
INT32 val;
if (!ConvertStringToINT32(token, &val)) {
delete text;
throw XMLParseException("Invalid value!", data->criterionName.c_str(), data->pParser);
}
list.push_back(val);
token = strtok(NULL, ", ");
}
if (data->criterionType & Filter::_TYPE_PAIR) {
if (list.size() != 2) {
delete text;
throw XMLParseException("Exactly 2 operands must be specified for 'between' operator!", data->criterionName.c_str(), data->pParser);
}
data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, list.front(), list.back());
}
else if (data->criterionType & Filter::_TYPE_LIST) {
data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, list);
}
}
else {
INT32 val;
if (!ConvertStringToINT32(text, &val)) {
delete text;
throw XMLParseException("Invalid value!", data->criterionName.c_str(), data->pParser);
}
data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, val);
}
}
else if (data->criterionType & Filter::_TYPE_ENUM) {
INT32 ord;
if (EnumeratorDB::Instance().GetEnumeratorByStr(data->criterionName.c_str(), text, ord)) {
// For the filter no enum type exists.
// Since we now know the integer value of the enumerator we treat it like any other integer criterion
data->criterionType &= ~Filter::_TYPE_ENUM;
data->criterionType |= Filter::_TYPE_INTEGER;
data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, ord);
}
else {
delete text;
throw XMLParseException("Can't find specified enumerator!", data->criterionName.c_str(), data->pParser);
}
}
else if (data->criterionType & Filter::_TYPE_FILTER) {
Filter* f = Instance().FindFilter(text);
if (f == NULL) {
throw XMLParseException("Can't find specified filter. Make sure it is defined before the filter that references it!", data->criterionName.c_str(), data->pParser);
}
data->currentFilter->AddCriterion(data->operationFlags | data->criterionType, f);
}
delete text;
break;
}
}
void FilterDB::RegisterEnumerators() {
/*****************************************
Filter string criterion types
******************************************/
LOGBT_ENUMDB_ADD("StringFilterCriterionTypes", 3,
Filter::REQ_NAME,
Filter::REQ_PROFILENAME,
Filter::REQ_NICKNAME
);
/*****************************************
Filter enum criterion types
******************************************/
LOGBT_ENUMDB_ADD("IntegerFilterCriterionTypes", 32,
Filter::REQ_HELMETPOS,
Filter::REQ_VESTPOS,
Filter::REQ_LEGPOS,
Filter::REQ_HEAD1POS,
Filter::REQ_HEAD2POS,
Filter::REQ_HANDPOS,
Filter::REQ_SECONDHANDPOS,
Filter::REQ_VESTPOCKPOS,
Filter::REQ_LTHIGHPOCKPOS,
Filter::REQ_RTHIGHPOCKPOS,
Filter::REQ_CPACKPOCKPOS,
Filter::REQ_BPACKPOCKPOS,
Filter::REQ_GUNSLINGPOCKPOS,
Filter::REQ_KNIFEPOCKPOS,
Filter::REQ_TEAM,
Filter::REQ_CAMO,
Filter::REQ_URBANCAMO,
Filter::REQ_DESERTCAMO,
Filter::REQ_SNOWCAMO,
Filter::REQ_EXPLEVEL,
Filter::REQ_STRENGTH,
Filter::REQ_LEADERSHIP,
Filter::REQ_WISDOM,
Filter::REQ_SKILLTRAIT1,
Filter::REQ_SKILLTRAIT2,
Filter::REQ_FACEINDEX,
Filter::REQ_WEAPON_IN_HAND,
Filter::REQ_CALIBRE,
Filter::REQ_VEST_AMOR_PROTECTION,
Filter::REQ_VEST_AMOR_COVERAGE,
Filter::REQ_HELMET_AMOR_PROTECTION,
Filter::REQ_HELMET_AMOR_COVERAGE
);
/*****************************************
Filter enum criterion types
******************************************/
LOGBT_ENUMDB_ADD("EnumFilterCriterionTypes", 7,
Filter::REQ_SEX,
Filter::REQ_MERC_TYPE,
Filter::REQ_SOLDIER_CLASS,
Filter::REQ_CIVILIANGROUP,
Filter::REQ_BODYTYPE,
Filter::REQ_WEAPON_CLASS,
Filter::REQ_WEAPON_TYPE
);
/*****************************************
MERC_TYPE
******************************************/
LOGBT_ENUMDB_ADD("MERC_TYPE", 7,
MERC_TYPE__PLAYER_CHARACTER,
MERC_TYPE__AIM_MERC,
MERC_TYPE__MERC,
MERC_TYPE__NPC,
MERC_TYPE__EPC,
MERC_TYPE__NPC_WITH_UNEXTENDABLE_CONTRACT,
MERC_TYPE__VEHICLE
);
/*****************************************
SOLDIER_CLASS
******************************************/
LOGBT_ENUMDB_ADD("SOLDIER_CLASS", SOLDIER_CLASS_MAX,
SOLDIER_CLASS_NONE,
SOLDIER_CLASS_ADMINISTRATOR,
SOLDIER_CLASS_ELITE,
SOLDIER_CLASS_ARMY,
SOLDIER_CLASS_GREEN_MILITIA,
SOLDIER_CLASS_REG_MILITIA,
SOLDIER_CLASS_ELITE_MILITIA,
SOLDIER_CLASS_CREATURE,
SOLDIER_CLASS_MINER,
SOLDIER_CLASS_ZOMBIE,
SOLDIER_CLASS_TANK,
SOLDIER_CLASS_JEEP,
SOLDIER_CLASS_BANDIT
);
/*****************************************
Filter enum criterion types
******************************************/
LOGBT_ENUMDB_ADD("SEX", 2,
MALE,
FEMALE
);
/*****************************************
SoldierBodyTypes
******************************************/
LOGBT_ENUMDB_ADD("BODYTYPE", TOTALBODYTYPES,
REGMALE,
BIGMALE,
STOCKYMALE,
REGFEMALE,
ADULTFEMALEMONSTER,
AM_MONSTER,
YAF_MONSTER,
YAM_MONSTER,
LARVAE_MONSTER,
INFANT_MONSTER,
QUEENMONSTER,
FATCIV,
MANCIV,
MINICIV,
DRESSCIV,
HATKIDCIV,
KIDCIV,
CRIPPLECIV,
COW,
CROW,
BLOODCAT,
ROBOTNOWEAPON,
HUMVEE,
TANK_NW,
TANK_NE,
ELDORADO,
ICECREAMTRUCK,
JEEP,
COMBAT_JEEP
);
/*****************************************
Civilian Groups
******************************************/
LOGBT_ENUMDB_ADD("CIVILIANGROUP", NUM_CIV_GROUPS,
NON_CIV_GROUP,
REBEL_CIV_GROUP,
KINGPIN_CIV_GROUP,
SANMONA_ARMS_GROUP,
ANGELS_GROUP,
BEGGARS_CIV_GROUP,
TOURISTS_CIV_GROUP,
ALMA_MILITARY_CIV_GROUP,
DOCTORS_CIV_GROUP,
COUPLE1_CIV_GROUP,
HICKS_CIV_GROUP,
WARDEN_CIV_GROUP,
JUNKYARD_CIV_GROUP,
FACTORY_KIDS_GROUP,
QUEENS_CIV_GROUP,
UNNAMED_CIV_GROUP_15,
UNNAMED_CIV_GROUP_16,
UNNAMED_CIV_GROUP_17,
UNNAMED_CIV_GROUP_18,
UNNAMED_CIV_GROUP_19,
ASSASSIN_CIV_GROUP,
POW_PRISON_CIV_GROUP,
UNNAMED_CIV_GROUP_22,
UNNAMED_CIV_GROUP_23,
VOLUNTEER_CIV_GROUP,
BOUNTYHUNTER_CIV_GROUP,
DOWNEDPILOT_CIV_GROUP,
SCIENTIST_GROUP,
RADAR_TECHNICIAN_GROUP,
AIRPORT_STAFF_GROUP,
BARRACK_STAFF_GROUP,
FACTORY_GROUP,
ADMINISTRATIVE_STAFF_GROUP,
LOYAL_CIV_GROUP,
BLACKMARKET_GROUP,
UNNAMED_CIV_GROUP_35,
UNNAMED_CIV_GROUP_36,
UNNAMED_CIV_GROUP_37,
UNNAMED_CIV_GROUP_38,
UNNAMED_CIV_GROUP_39,
UNNAMED_CIV_GROUP_40,
UNNAMED_CIV_GROUP_41,
UNNAMED_CIV_GROUP_42,
UNNAMED_CIV_GROUP_43,
UNNAMED_CIV_GROUP_44,
UNNAMED_CIV_GROUP_45,
UNNAMED_CIV_GROUP_46,
UNNAMED_CIV_GROUP_47,
UNNAMED_CIV_GROUP_48,
UNNAMED_CIV_GROUP_49,
UNNAMED_CIV_GROUP_50,
UNNAMED_CIV_GROUP_51,
UNNAMED_CIV_GROUP_52,
UNNAMED_CIV_GROUP_53,
UNNAMED_CIV_GROUP_54,
UNNAMED_CIV_GROUP_55,
UNNAMED_CIV_GROUP_56,
UNNAMED_CIV_GROUP_57,
UNNAMED_CIV_GROUP_58,
UNNAMED_CIV_GROUP_59,
UNNAMED_CIV_GROUP_60,
UNNAMED_CIV_GROUP_61,
UNNAMED_CIV_GROUP_62,
UNNAMED_CIV_GROUP_63,
UNNAMED_CIV_GROUP_64,
UNNAMED_CIV_GROUP_65,
UNNAMED_CIV_GROUP_66,
UNNAMED_CIV_GROUP_67,
UNNAMED_CIV_GROUP_68,
UNNAMED_CIV_GROUP_69,
UNNAMED_CIV_GROUP_70,
UNNAMED_CIV_GROUP_71,
UNNAMED_CIV_GROUP_72,
UNNAMED_CIV_GROUP_73,
UNNAMED_CIV_GROUP_74,
UNNAMED_CIV_GROUP_75,
UNNAMED_CIV_GROUP_76,
UNNAMED_CIV_GROUP_77,
UNNAMED_CIV_GROUP_78,
UNNAMED_CIV_GROUP_79,
UNNAMED_CIV_GROUP_80,
UNNAMED_CIV_GROUP_81,
UNNAMED_CIV_GROUP_82,
UNNAMED_CIV_GROUP_83,
UNNAMED_CIV_GROUP_84,
UNNAMED_CIV_GROUP_85,
UNNAMED_CIV_GROUP_86,
UNNAMED_CIV_GROUP_87,
UNNAMED_CIV_GROUP_88,
UNNAMED_CIV_GROUP_89,
UNNAMED_CIV_GROUP_90,
UNNAMED_CIV_GROUP_91,
UNNAMED_CIV_GROUP_92,
UNNAMED_CIV_GROUP_93,
UNNAMED_CIV_GROUP_94,
UNNAMED_CIV_GROUP_95,
UNNAMED_CIV_GROUP_96,
UNNAMED_CIV_GROUP_97,
UNNAMED_CIV_GROUP_98,
UNNAMED_CIV_GROUP_99,
UNNAMED_CIV_GROUP_100,
UNNAMED_CIV_GROUP_101,
UNNAMED_CIV_GROUP_102,
UNNAMED_CIV_GROUP_103,
UNNAMED_CIV_GROUP_104,
UNNAMED_CIV_GROUP_105,
UNNAMED_CIV_GROUP_106,
UNNAMED_CIV_GROUP_107,
UNNAMED_CIV_GROUP_108,
UNNAMED_CIV_GROUP_109,
UNNAMED_CIV_GROUP_110,
UNNAMED_CIV_GROUP_111,
UNNAMED_CIV_GROUP_112,
UNNAMED_CIV_GROUP_113,
UNNAMED_CIV_GROUP_114,
UNNAMED_CIV_GROUP_115,
UNNAMED_CIV_GROUP_116,
UNNAMED_CIV_GROUP_117,
UNNAMED_CIV_GROUP_118,
UNNAMED_CIV_GROUP_119,
UNNAMED_CIV_GROUP_120,
UNNAMED_CIV_GROUP_121,
UNNAMED_CIV_GROUP_122,
UNNAMED_CIV_GROUP_123,
UNNAMED_CIV_GROUP_124,
UNNAMED_CIV_GROUP_125,
UNNAMED_CIV_GROUP_126,
UNNAMED_CIV_GROUP_127,
UNNAMED_CIV_GROUP_128,
UNNAMED_CIV_GROUP_129,
UNNAMED_CIV_GROUP_130,
UNNAMED_CIV_GROUP_131,
UNNAMED_CIV_GROUP_132,
UNNAMED_CIV_GROUP_133,
UNNAMED_CIV_GROUP_134,
UNNAMED_CIV_GROUP_135,
UNNAMED_CIV_GROUP_136,
UNNAMED_CIV_GROUP_137,
UNNAMED_CIV_GROUP_138,
UNNAMED_CIV_GROUP_139,
UNNAMED_CIV_GROUP_140,
UNNAMED_CIV_GROUP_141,
UNNAMED_CIV_GROUP_142,
UNNAMED_CIV_GROUP_143,
UNNAMED_CIV_GROUP_144,
UNNAMED_CIV_GROUP_145,
UNNAMED_CIV_GROUP_146,
UNNAMED_CIV_GROUP_147,
UNNAMED_CIV_GROUP_148,
UNNAMED_CIV_GROUP_149,
UNNAMED_CIV_GROUP_150,
UNNAMED_CIV_GROUP_151,
UNNAMED_CIV_GROUP_152,
UNNAMED_CIV_GROUP_153,
UNNAMED_CIV_GROUP_154,
UNNAMED_CIV_GROUP_155,
UNNAMED_CIV_GROUP_156,
UNNAMED_CIV_GROUP_157,
UNNAMED_CIV_GROUP_158,
UNNAMED_CIV_GROUP_159,
UNNAMED_CIV_GROUP_160,
UNNAMED_CIV_GROUP_161,
UNNAMED_CIV_GROUP_162,
UNNAMED_CIV_GROUP_163,
UNNAMED_CIV_GROUP_164,
UNNAMED_CIV_GROUP_165,
UNNAMED_CIV_GROUP_166,
UNNAMED_CIV_GROUP_167,
UNNAMED_CIV_GROUP_168,
UNNAMED_CIV_GROUP_169,
UNNAMED_CIV_GROUP_170,
UNNAMED_CIV_GROUP_171,
UNNAMED_CIV_GROUP_172,
UNNAMED_CIV_GROUP_173,
UNNAMED_CIV_GROUP_174,
UNNAMED_CIV_GROUP_175,
UNNAMED_CIV_GROUP_176,
UNNAMED_CIV_GROUP_177,
UNNAMED_CIV_GROUP_178,
UNNAMED_CIV_GROUP_179,
UNNAMED_CIV_GROUP_180,
UNNAMED_CIV_GROUP_181,
UNNAMED_CIV_GROUP_182,
UNNAMED_CIV_GROUP_183,
UNNAMED_CIV_GROUP_184,
UNNAMED_CIV_GROUP_185,
UNNAMED_CIV_GROUP_186,
UNNAMED_CIV_GROUP_187,
UNNAMED_CIV_GROUP_188,
UNNAMED_CIV_GROUP_189,
UNNAMED_CIV_GROUP_190,
UNNAMED_CIV_GROUP_191,
UNNAMED_CIV_GROUP_192,
UNNAMED_CIV_GROUP_193,
UNNAMED_CIV_GROUP_194,
UNNAMED_CIV_GROUP_195,
UNNAMED_CIV_GROUP_196,
UNNAMED_CIV_GROUP_197,
UNNAMED_CIV_GROUP_198,
UNNAMED_CIV_GROUP_199,
UNNAMED_CIV_GROUP_200,
UNNAMED_CIV_GROUP_201,
UNNAMED_CIV_GROUP_202,
UNNAMED_CIV_GROUP_203,
UNNAMED_CIV_GROUP_204,
UNNAMED_CIV_GROUP_205,
UNNAMED_CIV_GROUP_206,
UNNAMED_CIV_GROUP_207,
UNNAMED_CIV_GROUP_208,
UNNAMED_CIV_GROUP_209,
UNNAMED_CIV_GROUP_210,
UNNAMED_CIV_GROUP_211,
UNNAMED_CIV_GROUP_212,
UNNAMED_CIV_GROUP_213,
UNNAMED_CIV_GROUP_214,
UNNAMED_CIV_GROUP_215,
UNNAMED_CIV_GROUP_216,
UNNAMED_CIV_GROUP_217,
UNNAMED_CIV_GROUP_218,
UNNAMED_CIV_GROUP_219,
UNNAMED_CIV_GROUP_220,
UNNAMED_CIV_GROUP_221,
UNNAMED_CIV_GROUP_222,
UNNAMED_CIV_GROUP_223,
UNNAMED_CIV_GROUP_224,
UNNAMED_CIV_GROUP_225,
UNNAMED_CIV_GROUP_226,
UNNAMED_CIV_GROUP_227,
UNNAMED_CIV_GROUP_228,
UNNAMED_CIV_GROUP_229,
UNNAMED_CIV_GROUP_230,
UNNAMED_CIV_GROUP_231,
UNNAMED_CIV_GROUP_232,
UNNAMED_CIV_GROUP_233,
UNNAMED_CIV_GROUP_234,
UNNAMED_CIV_GROUP_235,
UNNAMED_CIV_GROUP_236,
UNNAMED_CIV_GROUP_237,
UNNAMED_CIV_GROUP_238,
UNNAMED_CIV_GROUP_239,
UNNAMED_CIV_GROUP_240,
UNNAMED_CIV_GROUP_241,
UNNAMED_CIV_GROUP_242,
UNNAMED_CIV_GROUP_243,
UNNAMED_CIV_GROUP_244,
UNNAMED_CIV_GROUP_245,
UNNAMED_CIV_GROUP_246,
UNNAMED_CIV_GROUP_247,
UNNAMED_CIV_GROUP_248,
UNNAMED_CIV_GROUP_249,
UNNAMED_CIV_GROUP_250,
UNNAMED_CIV_GROUP_251,
UNNAMED_CIV_GROUP_252,
UNNAMED_CIV_GROUP_253,
UNNAMED_CIV_GROUP_254
);
/*****************************************
Weapon Class
******************************************/
LOGBT_ENUMDB_ADD("WEAPON_CLASS", NUM_WEAPON_CLASSES,
NOGUNCLASS,
HANDGUNCLASS,
SMGCLASS,
RIFLECLASS,
MGCLASS,
SHOTGUNCLASS,
KNIFECLASS,
MONSTERCLASS
);
/*****************************************
Weapon Type
******************************************/
LOGBT_ENUMDB_ADD("WEAPON_TYPE", GUN_TYPES_MAX,
NOT_GUN,
GUN_PISTOL,
GUN_M_PISTOL,
GUN_SMG,
GUN_RIFLE,
GUN_SN_RIFLE,
GUN_AS_RIFLE,
GUN_LMG,
GUN_SHOTGUN
);
};
}
+68
View File
@@ -0,0 +1,68 @@
#pragma once
#ifndef _LBT_FILTERDB__H_
#define _LBT_FILTERDB__H_
#include "LogicalBodyTypes/AbstractXMLLoader.h"
#include "Animation Data.h"
#include "Weapons.h"
#include "LogicalBodyTypes/EnumeratorDB.h"
#include "LogicalBodyTypes/Filter.h"
#include <map>
namespace LogicalBodyTypes {
class FilterDB : public AbstractXMLLoader, public Singleton<FilterDB> {
public:
using Singleton <FilterDB>::Instance;
typedef std::map<std::string, Filter*> FilterMap;
typedef FilterMap::const_iterator iterator;
private:
enum ParseState {
E_ELEMENT_FILTERS = FIRST_SUBCLASS_STATE,
E_ELEMENT_FILTER,
E_OPERATION,
E_CRITERION
};
struct ParseData : public AbstractXMLLoader::ParseData { // shadow ParseData type and also extend the ParseData stuct of the base class
ParseData(XML_Parser* parser) : AbstractXMLLoader::ParseData(parser) {
currentFilter = NULL;
operationFlags = 0;
criterionName = "";
criterionType = 0;
};
~ParseData() {
// don't like this one bit, but we have to handle this here in case an exception is thrown
// remember to set the pointer to NULL after the filter object has been added to the DB!
if (currentFilter != NULL) delete currentFilter;
};
Filter* currentFilter;
std::string filterName;
UINT32 operationFlags;
std::string criterionName;
UINT32 criterionType;
} typedef ParseData;
FilterMap filters;
public:
FilterDB(void);
~FilterDB(void);
FilterMap::const_iterator begin();
FilterMap::const_iterator end();
Filter* FindFilter(std::string name);
private:
bool AddFilter(std::string name, Filter* filter);
static void RegisterEnumerators();
static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts);
static void XMLCALL EndElementHandle(void* userData, const XML_Char* name);
static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len);
static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId);
static AbstractXMLLoader::ParseData* MakeParseData(XML_Parser* parser); // shadow factory function for ParseData instances
};
}
#endif
+202
View File
@@ -0,0 +1,202 @@
#include "Layers.h"
#include <iostream>
#include <fstream>
namespace LogicalBodyTypes {
Layers::Layers() : AbstractXMLLoader(StartElementHandle, EndElementHandle, CharacterDataHandle, MakeParseData) {
directionLayerGraphs.resize(NUM_WORLD_DIRECTIONS);
}
Layers::~Layers(void) {
for (LayerPropertiesVector::size_type i = 0; i < layers.size(); i++) {
delete[] layers[i].identifier;
}
}
Layers::LayerGraphIterator Layers::GetIterator(WorldDirections direction) {
return directionLayerGraphs[direction].begin();
}
Layers::LayerGraphIterator Layers::GetIterationEnd(WorldDirections direction) {
return directionLayerGraphs[direction].end();
}
Layers::LayerGraphIterator Layers::GetIterator(INT8 direction) {
return directionLayerGraphs[direction].begin();
}
Layers::LayerGraphIterator Layers::GetIterationEnd(INT8 direction) {
return directionLayerGraphs[direction].end();
}
AbstractXMLLoader::ParseData* Layers::MakeParseData(XML_Parser* parser) {
return new ParseData(parser);
}
void Layers::AddLayerGraphNode(WorldDirections dir, std::string identifier, bool render, bool renderShadows, INT32 zIndex) {
// create layer property object and push it into the layers properties container - if layer not already there
Layers::LayerPropertiesVector::size_type index = GetIndex(identifier);
if (index == -1) {
LayerProperties props;
props.identifier = new char[identifier.size() + 1];
strcpy(props.identifier, identifier.c_str());
props.render = render;
props.renderShadows = renderShadows;
layers.push_back(props);
index = GetIndex(identifier);
}
// create node with zindex and a pointer to the layer properties object
LayerGraphNode node;
node.zIndex = zIndex;
node.index = index;
node.pLayerProperties = NULL; // since the pointers would be invalided once the vector has to be reallocated,
// we set the pointers after the layer configuration is finalized (see UpdateConfiguration)
// add node to direction specific layer graph
LayerGraph::iterator i = directionLayerGraphs[dir].begin();
for (; i != directionLayerGraphs[dir].end(); i++) {
if (i->zIndex > zIndex) break;
}
directionLayerGraphs[dir].insert(i, node);
}
void Layers::UpdateConfiguration() {
for (int d = NORTH; d < NUM_WORLD_DIRECTIONS; ++d) {
WorldDirections dir = static_cast<WorldDirections>(d);
LayerGraph::iterator i = directionLayerGraphs[dir].begin();
for (; i != directionLayerGraphs[dir].end(); i++) {
i->pLayerProperties = &layers[i->index];
}
}
}
Layers::LayerPropertiesVector::size_type Layers::GetCount() {
return layers.size();
}
Layers::LayerPropertiesVector::size_type Layers::GetIndex(std::string& identifier) {
for (LayerPropertiesVector::size_type i = 0; i < layers.size(); i++) {
if (strcmp(layers[i].identifier, identifier.c_str()) == 0) return i;
}
return -1;
}
const Layers::LayerProperties& Layers::GetLayerProperties(LayerPropertiesVector::size_type index) {
return layers[index];
}
void Layers::StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts) {
ParseData* data = (ParseData*)userData;
switch (data->state) {
case E_NONE:
if (strcmp(name, "Layers") == 0) {
data->level = 0;
data->state = E_ELEMENT_LAYERS;
break;
}
case E_ELEMENT_LAYERS:
case E_ELEMENT_LAYER:
if (strcmp(name, "Layer") == 0) {
data->level++;
data->state = E_ELEMENT_LAYER;
XML_Char const* attrName = GetAttribute("name", atts);
XML_Char const* attrRender = GetAttribute("render", atts);
XML_Char const* attrShadow = GetAttribute("shadow", atts);
XML_Char const* attrDirNorth = GetAttribute("zindex_north", atts);
XML_Char const* attrDirNorthEast = GetAttribute("zindex_northeast", atts);
XML_Char const* attrDirEast = GetAttribute("zindex_east", atts);
XML_Char const* attrDirSouthEast = GetAttribute("zindex_southeast", atts);
XML_Char const* attrDirSouth = GetAttribute("zindex_south", atts);
XML_Char const* attrDirSouthWest = GetAttribute("zindex_southwest", atts);
XML_Char const* attrDirWest = GetAttribute("zindex_west", atts);
XML_Char const* attrDirNorthWest = GetAttribute("zindex_northwest", atts);
if (attrName == NULL || attrRender == NULL || attrShadow == NULL) {
throw XMLParseException("Mandatory attribute missing!", name, data->pParser);
}
BOOLEAN fRender;
if (!ConvertStringToBOOLEAN(attrRender, &fRender)) throw XMLParseException("Attribute 'value' doesn't have a valid value!", name, data->pParser);
BOOLEAN fShadow;
if (!ConvertStringToBOOLEAN(attrShadow, &fShadow)) throw XMLParseException("Attribute 'shadow' doesn't have a valid value!", name, data->pParser);
INT32 value;
if (attrDirNorth != NULL) {
if (!ConvertStringToINT32(attrDirNorth, &value)) throw XMLParseException("Attribute 'zindex_north' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[NORTH].push(ZLevelPair(data->level, value));
}
if (attrDirNorthEast != NULL) {
if (!ConvertStringToINT32(attrDirNorthEast, &value)) throw XMLParseException("Attribute 'zindex_northeast' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[NORTHEAST].push(ZLevelPair(data->level, value));
}
if (attrDirEast != NULL) {
if (!ConvertStringToINT32(attrDirEast, &value)) throw XMLParseException("Attribute 'zindex_east' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[EAST].push(ZLevelPair(data->level, value));
}
if (attrDirSouthEast != NULL) {
if (!ConvertStringToINT32(attrDirSouthEast, &value)) throw XMLParseException("Attribute 'zindex_southeast' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[SOUTHEAST].push(ZLevelPair(data->level, value));
}
if (attrDirSouth != NULL) {
if (!ConvertStringToINT32(attrDirSouth, &value)) throw XMLParseException("Attribute 'zindex_south' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[SOUTH].push(ZLevelPair(data->level, value));
}
if (attrDirSouthWest != NULL) {
if (!ConvertStringToINT32(attrDirSouthWest, &value)) throw XMLParseException("Attribute 'zindex_southwest' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[SOUTHWEST].push(ZLevelPair(data->level, value));
}
if (attrDirWest != NULL) {
if (!ConvertStringToINT32(attrDirWest, &value)) throw XMLParseException("Attribute 'zindex_west' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[WEST].push(ZLevelPair(data->level, value));
}
if (attrDirNorthWest != NULL) {
if (!ConvertStringToINT32(attrDirNorthWest, &value)) throw XMLParseException("Attribute 'zindex_northwest' doesn't have a valid value!", name, data->pParser);
data->directionZStacks[NORTHWEST].push(ZLevelPair(data->level, value));
}
for (int d = NORTH; d < NUM_WORLD_DIRECTIONS; ++d) {
WorldDirections dir = static_cast<WorldDirections>(d);
INT32 value = 0;
if (!data->directionZStacks[dir].empty()) {
value = data->directionZStacks[dir].top().second;
}
Instance().AddLayerGraphNode(dir, attrName, fRender == TRUE, fShadow == TRUE, value);
}
break;
}
default:
throw XMLParseException("Unexpected element!", name, data->pParser);
}
}
void Layers::EndElementHandle(void* userData, const XML_Char* name) {
ParseData* data = (ParseData*)userData;
switch (data->state) {
case E_ELEMENT_LAYER:
if (strcmp(name, "Layer") == 0) {
for (int d = NORTH; d < NUM_WORLD_DIRECTIONS; ++d) {
if (!data->directionZStacks[static_cast<WorldDirections>(d)].empty()) {
if (data->directionZStacks[static_cast<WorldDirections>(d)].top().first == data->level) {
data->directionZStacks[d].pop();
}
}
}
if (--data->level == 0) data->state = E_ELEMENT_LAYERS;
break;
}
case E_ELEMENT_LAYERS:
if (strcmp(name, "Layers") == 0) {
data->state = E_NONE;
Instance().UpdateConfiguration();
break;
}
default:
throw XMLParseException("Unexpected element! Closing tag missing?", name, data->pParser);
return;
}
}
void Layers::CharacterDataHandle(void* userData, const XML_Char* str, int len) {
}
}
+74
View File
@@ -0,0 +1,74 @@
#pragma once
#ifndef _LBT_LAYERS__H_
#define _LBT_LAYERS__H_
#include "LogicalBodyTypes/AbstractXMLLoader.h"
#include <stack>
namespace LogicalBodyTypes {
// Layers configuration implemented as singleton and loadable from XML.
class Layers : public AbstractXMLLoader, public Singleton<Layers> {
public:
using Singleton <Layers>::Instance;
struct LayerProperties {
char* identifier;
bool render;
bool renderShadows;
} typedef LayerProperties;
typedef std::vector <LayerProperties> LayerPropertiesVector;
private:
enum ParseState {
E_ELEMENT_LAYERS = FIRST_SUBCLASS_STATE,
E_ELEMENT_LAYER
};
typedef std::pair <UINT32, INT32> ZLevelPair;
typedef std::stack <ZLevelPair> ZStack;
typedef std::vector <ZStack> ZStackVector;
struct ParseData : public AbstractXMLLoader::ParseData { // shadow ParseData type and also extend the ParseData stuct of the base class
ParseData(XML_Parser* parser) : AbstractXMLLoader::ParseData(parser)
{
directionZStacks.resize(NUM_WORLD_DIRECTIONS);
};
ZStackVector directionZStacks;
} typedef ParseData;
struct LayerGraphNode {
INT32 zIndex;
LayerPropertiesVector::size_type index;
LayerProperties* pLayerProperties;
} typedef LayerGraphNode;
typedef std::list <LayerGraphNode> LayerGraph;
typedef std::vector <LayerGraph> LayerGraphsVector;
LayerPropertiesVector layers;
LayerGraphsVector directionLayerGraphs;
public:
typedef LayerGraph::iterator LayerGraphIterator;
public:
Layers(void);
~Layers(void);
LayerPropertiesVector::size_type GetCount();
// returns -1 if layer doesn't exist
LayerPropertiesVector::size_type GetIndex(std::string& identifier);
const Layers::LayerProperties& GetLayerProperties(LayerPropertiesVector::size_type index);
LayerGraphIterator GetIterator(WorldDirections direction);
LayerGraphIterator GetIterationEnd(WorldDirections direction);
LayerGraphIterator GetIterator(INT8 direction);
LayerGraphIterator GetIterationEnd(INT8 direction);
private:
static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts);
static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len);
static void XMLCALL EndElementHandle(void* userData, const XML_Char* name);
void AddLayerGraphNode(WorldDirections dir, std::string identifier, bool render, bool renderShadows, INT32 zIndex);
static AbstractXMLLoader::ParseData* MakeParseData(XML_Parser* parser); // shadow factory function for ParseData instances
void UpdateConfiguration();
};
}
#endif
+167
View File
@@ -0,0 +1,167 @@
#include "PaletteDB.h"
namespace LogicalBodyTypes {
PaletteDB::PaletteDB(void) : AbstractXMLLoader(StartElementHandle, EndElementHandle, CharacterDataHandle) {
}
PaletteDB::~PaletteDB(void) {
PaletteTableMap::iterator i = paletteTables.begin();
for (; i != paletteTables.end(); i++) delete i->second;
}
bool PaletteDB::AddPaletteTable(std::string name, PaletteTable* paletteTable) {
PaletteTableMap::iterator i = paletteTables.find(name);
if (i != paletteTables.end()) return false;
paletteTables[name] = paletteTable;
return true;
}
PaletteTable* PaletteDB::FindPaletteTable(std::string name) {
PaletteTableMap::iterator i = paletteTables.find(name);
if (i == paletteTables.end()) return NULL;
return i->second;
}
void XMLCALL PaletteDB::StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts) {
ParseData* data = (ParseData*)userData;
switch (data->state) {
case E_NONE:
if (strcmp(name, "Palettes") == 0) {
data->state = E_ELEMENT_PALETTES;
break;
}
case E_ELEMENT_PALETTES:
if (strcmp(name, "Palette") == 0) {
data->state = E_ELEMENT_PALETTE;
XML_Char const* aName = GetAttribute("name", atts);
XML_Char const* aFileName = GetAttribute("filename", atts);
if (aFileName == NULL || aName == NULL) throw XMLParseException("Mandatory attribute missing!", name, data->pParser);
PaletteTable* paletteTable = new PaletteTable();
if (!paletteTable->Load(aFileName)) throw XMLParseException("Palette table could not be loaded from the specified file!", name, data->pParser);
Instance().AddPaletteTable(aName, paletteTable);
break;
}
default:
throw XMLParseException("Unexpected element!", name, data->pParser);
}
}
void XMLCALL PaletteDB::EndElementHandle(void* userData, const XML_Char* name) {
ParseData* data = (ParseData*)userData;
switch (data->state) {
case E_ELEMENT_PALETTE:
if (strcmp(name, "Palette") == 0) {
data->state = E_ELEMENT_PALETTES;
break;
}
case E_ELEMENT_PALETTES:
if (strcmp(name, "Palettes") == 0) {
data->state = E_NONE;
break;
}
default:
throw XMLParseException("Unexpected element! Closing tag missing?", name, data->pParser);
return;
}
}
void XMLCALL PaletteDB::CharacterDataHandle(void* userData, const XML_Char* str, int len) {
}
/*
BOOLEAN SOLDIERTYPE::CreateSoldierPalettes( void )
{
CHAR8 zColFilename[100];
INT32 iWhich;
INT32 cnt;
SGPPaletteEntry Temp8BPPPalette[ 256 ];
if (this->p8BPPPalette != NULL) {
MemFree(this->p8BPPPalette);
this->p8BPPPalette = NULL;
}
// Allocate mem for new palette
this->p8BPPPalette = (SGPPaletteEntry *) MemAlloc( sizeof( SGPPaletteEntry ) * 256 );
memset(this->p8BPPPalette, 0, sizeof(SGPPaletteEntry) * 256);
CHECKF(this->p8BPPPalette != NULL);
// Use col file
if (CreateSGPPaletteFromCOLFile(Temp8BPPPalette, zColFilename)) {
// Copy into palette
memcpy(this->p8BPPPalette, Temp8BPPPalette, sizeof( this->p8BPPPalette ) * 256);
} else {
}
if (this->p16BPPPalette != NULL) {
MemFree(this->p16BPPPalette);
this->p16BPPPalette = NULL;
}
// -- BUILD 16BPP Palette from this
this->p16BPPPalette = Create16BPPPalette(this->p8BPPPalette);
for (iWhich = 0; iWhich < NUM_SOLDIER_SHADES; iWhich++) {
if (this->pShades[iWhich] != NULL) {
MemFree(this->pShades[iWhich]);
this->pShades[iWhich] = NULL;
}
}
for (iWhich = 0; iWhich < NUM_SOLDIER_EFFECTSHADES; iWhich++) {
if (this->pEffectShades[iWhich] != NULL) {
MemFree( this->pEffectShades[ iWhich ] );
this->pEffectShades[iWhich] = NULL;
}
}
for (iWhich = 0; iWhich < 20; iWhich++) {
if (this->pGlowShades[iWhich] != NULL) {
MemFree( this->pGlowShades[ iWhich ]);
this->pGlowShades[iWhich] = NULL;
}
}
CreateSoldierPaletteTables( this, HVOBJECT_GLOW_GREEN );
this->pEffectShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE);
this->pEffectShades[1] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 150, 100, TRUE);
// Build shades for glowing visible bad guy
// First do visible guy
this->pGlowShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE);
for (cnt = 1; cnt < 10; cnt++) {
this->pGlowShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 255, FALSE);
}
// Now for gray guy...
this->pGlowShades[10] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE);
for (cnt = 11; cnt < 19; cnt++) {
this->pGlowShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 0, FALSE);
}
this->pGlowShades[19] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[18], 0, FALSE);
// ATE: OK, piggyback on the shades we are not using for 2 colored lighting....
// ORANGE, VISIBLE GUY
this->pShades[20] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE);
for (cnt = 21; cnt < 30; cnt++) {
this->pShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[( cnt - 20 )], gOrangeGlowG[( cnt - 20 )], TRUE);
}
// ORANGE, GREY GUY
this->pShades[30] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE);
for (cnt = 31; cnt < 39; cnt++) {
this->pShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[(cnt - 20)], gOrangeGlowG[(cnt - 20 )], TRUE);
}
this->pShades[39] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[18], gOrangeGlowG[18], TRUE);
return(TRUE);
}
*/
}
+41
View File
@@ -0,0 +1,41 @@
#pragma once
#ifndef _LBT_PALETTEDB__H_
#define _LBT_PALETTEDB__H_
#include <map>
#include "LogicalBodyTypes/Singleton.h"
#include "LogicalBodyTypes/AbstractXMLLoader.h"
#include "LogicalBodyTypes/PaletteTable.h"
namespace LogicalBodyTypes {
class PaletteDB : public AbstractXMLLoader, public Singleton<PaletteDB> {
public:
using Singleton <PaletteDB>::Instance;
typedef std::map<std::string, PaletteTable*> PaletteTableMap;
private:
enum ParseState {
E_ELEMENT_PALETTES = FIRST_SUBCLASS_STATE,
E_ELEMENT_PALETTE
};
PaletteTableMap paletteTables;
public:
PaletteDB(void);
~PaletteDB(void);
bool AddPaletteTable(std::string name, PaletteTable* paletteTable);
PaletteTable* FindPaletteTable(std::string name);
private:
static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts);
static void XMLCALL EndElementHandle(void* userData, const XML_Char* name);
static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len);
static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId);
};
}
#endif
+102
View File
@@ -0,0 +1,102 @@
#include "PaletteTable.h"
namespace LogicalBodyTypes {
PaletteTable::PaletteTable() {
}
PaletteTable::~PaletteTable() {
}
bool PaletteTable::CreateSGPPaletteFromActFile(SGPPaletteEntry *pPalette, std::string fileName) {
HWFILE hFileHandle;
UINT32 cnt;
char* colFileName = new char[fileName.size() + 1];
strcpy(colFileName, fileName.c_str());
if (!FileExists(colFileName)) {
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "Cannot find COL file");
return false;
}
if ((hFileHandle = FileOpen(colFileName, FILE_ACCESS_READ, FALSE)) == 0) {
DebugMsg(TOPIC_JA2, DBG_LEVEL_3, "Cannot open COL file");
return false;
}
for (cnt = 0; cnt < 256; cnt++) {
FileRead(hFileHandle, &pPalette[cnt].peRed, sizeof(UINT8), NULL);
FileRead(hFileHandle, &pPalette[cnt].peGreen, sizeof(UINT8), NULL);
FileRead(hFileHandle, &pPalette[cnt].peBlue, sizeof(UINT8), NULL);
}
FileClose(hFileHandle);
delete[] colFileName;
return true;
}
bool PaletteTable::Load(std::string fileName) {
INT32 iWhich;
INT32 cnt;
SGPPaletteEntry Temp8BPPPalette[256];
if (this->p8BPPPalette != NULL) {
MemFree(this->p8BPPPalette);
this->p8BPPPalette = NULL;
}
this->p8BPPPalette = (SGPPaletteEntry*)MemAlloc(sizeof(SGPPaletteEntry) * 256);
memset(this->p8BPPPalette, 0, sizeof(SGPPaletteEntry) * 256);
if (CreateSGPPaletteFromActFile(Temp8BPPPalette, (CHAR8*)fileName.c_str())) {
memcpy(this->p8BPPPalette, Temp8BPPPalette, sizeof(this->p8BPPPalette) * 256);
} else {
return false;
}
if (this->p16BPPPalette != NULL ) {
MemFree(this->p16BPPPalette);
this->p16BPPPalette = NULL;
}
this->p16BPPPalette = Create16BPPPalette(this->p8BPPPalette);
for (iWhich = 0; iWhich < NUM_SOLDIER_SHADES; iWhich++) {
if (this->pShades[ iWhich ] != NULL) {
MemFree(this->pShades[iWhich]);
this->pShades[ iWhich ] = NULL;
}
}
for (iWhich = 0; iWhich < NUM_SOLDIER_EFFECTSHADES; iWhich++) {
if (this->pEffectShades[iWhich] != NULL) {
MemFree(this->pEffectShades[iWhich]);
this->pEffectShades[iWhich] = NULL;
}
}
for (iWhich = 0; iWhich < 20; iWhich++) {
if (this->pGlowShades[iWhich] != NULL) {
MemFree(this->pGlowShades[iWhich]);
this->pGlowShades[iWhich] = NULL;
}
}
CreateSoldierPaletteTables(this, HVOBJECT_GLOW_GREEN);
this->pEffectShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE);
this->pEffectShades[1] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 150, 100, TRUE);
this->pGlowShades[0] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE);
for (cnt = 1; cnt < 10; cnt++) {
this->pGlowShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 255, FALSE);
}
this->pGlowShades[10] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE);
for (cnt = 11; cnt < 19; cnt++) {
this->pGlowShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[cnt], 0, FALSE);
}
this->pGlowShades[19] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gRedGlowR[18], 0, FALSE);
this->pShades[20] = Create16BPPPaletteShaded(this->p8BPPPalette, 255, 255, 255, FALSE);
for (cnt = 21; cnt < 30; cnt++) {
this->pShades[cnt] = CreateEnemyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[(cnt - 20)], gOrangeGlowG[(cnt - 20)], TRUE);
}
this->pShades[30] = Create16BPPPaletteShaded(this->p8BPPPalette, 100, 100, 100, TRUE);
for (cnt = 31; cnt < 39; cnt++) {
this->pShades[cnt] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[( cnt - 20)], gOrangeGlowG[(cnt - 20)], TRUE);
}
this->pShades[39] = CreateEnemyGreyGlow16BPPPalette(this->p8BPPPalette, gOrangeGlowR[18], gOrangeGlowG[18], TRUE);
return true;
}
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
#ifndef _LBT_PALETTETABLE__H_
#define _LBT_PALETTETABLE__H_
#include "soldier control.h"
#include "Utilities.h"
#include "lighting.h"
extern UINT8 gRedGlowR[];
extern UINT8 gOrangeGlowR[];
extern UINT8 gOrangeGlowG[];
extern UINT16* CreateEnemyGlow16BPPPalette(SGPPaletteEntry* pPalette, UINT32 rscale, UINT32 gscale, BOOLEAN fAdjustGreen);
extern UINT16* CreateEnemyGreyGlow16BPPPalette(SGPPaletteEntry* pPalette, UINT32 rscale, UINT32 gscale, BOOLEAN fAdjustGreen);
namespace LogicalBodyTypes {
class PaletteTable : public SOLDIERTYPE {
public:
PaletteTable();
~PaletteTable(void);
bool Load(std::string fileName);
private:
bool CreateSGPPaletteFromActFile(SGPPaletteEntry *pPalette, std::string fileName);
};
}
#endif
+79
View File
@@ -0,0 +1,79 @@
#pragma once
#ifndef _LBT_SINGLETON__H_
#define _LBT_SINGLETON__H_
#include <cassert>
/*
Not thread safe. Copied from the codeproject (Author: Lai Shiaw San Kent)
*/
template<typename T> class ISingleton {
public :
static T& Instance();
};
template<typename T> class Singleton : public ISingleton<T> {
public :
static T& Instance();
static void Destroy();
protected :
inline explicit Singleton() {
assert(Singleton::instance_ == 0);
Singleton::instance_ = static_cast<T*>(this);
}
inline ~Singleton() {
Singleton::instance_ = 0;
}
private :
static T* CreateInstance();
static void ScheduleForDestruction(void (*)());
static void DestroyInstance(T*);
private :
static T* instance_;
private :
inline explicit Singleton(Singleton const&) {}
inline Singleton& operator=(Singleton const&) { return *this; }
};
template<typename T> typename T& Singleton<T>::Instance() {
if (Singleton::instance_ == 0) {
Singleton::instance_ = CreateInstance();
ScheduleForDestruction(Singleton::Destroy);
}
return *(Singleton::instance_);
}
template<typename T>
void Singleton<T>::Destroy() {
if (Singleton::instance_ != 0) {
DestroyInstance(Singleton::instance_);
Singleton::instance_ = 0;
}
}
template<typename T>
inline typename T* Singleton<T>::CreateInstance() {
return new T();
}
template<typename T>
inline void Singleton<T>::ScheduleForDestruction(void (*pFun)()) {
std::atexit(pFun);
}
template<typename T>
inline void Singleton<T>::DestroyInstance(T* p) {
delete p;
}
template<typename T>
typename T* Singleton<T>::instance_ = 0;
#endif
+145
View File
@@ -0,0 +1,145 @@
#include "SurfaceCache.h"
namespace LogicalBodyTypes {
SurfaceCache::SurfaceCache(UINT32 size) {
loadedElementsMax = size;
loadedElements = 0;
oldest = newest = NULL;
};
SurfaceCache::~SurfaceCache() {
for (UINT32 i = 0; i < surfaceVector.size(); i++) {
delete surfaceVector[i];
}
}
AnimationSurfaceType* SurfaceCache::GetLoadedSurface(UINT32 idx) {
if (idx >= surfaceVector.size()) {
// TODO more sensible handling of errors
SET_ERROR("Error: surface index out of range!");
return NULL;
}
CacheEntry* node = surfaceVector[idx];
if (node == newest) {
return node->surface; // nothing to be done here...
}
if (loadedElements < loadedElementsMax) {
if (!oldest) oldest = node;
if (!node->loaded) {
node->loaded = LoadSurface(node->surface, node->structFile);
// TODO more sensible handling of errors
if (!node->loaded) {
SET_ERROR("Error: a surface could not be laoded!");
return NULL;
}
loadedElements++;
} else {
if (node->next) node->next->prev = node->prev;
if (node->prev) node->prev->next = node->next;
}
if (newest) {
newest->next = node;
node->prev = newest;
}
newest = node;
} else {
if (node->loaded) {
if (node == oldest) {
oldest = oldest->next;
}
if (node->next) node->next->prev = node->prev;
if (node->prev) node->prev->next = node->next;
} else {
CacheEntry* oldNext = oldest->next;
while (node == oldNext) {
oldNext = oldNext->next;
}
oldest->prev = NULL;
oldest->next = NULL;
oldest->loaded = !UnloadSurface(oldest->surface);
oldest = oldNext;
node->loaded = LoadSurface(node->surface, node->structFile);
// TODO more sensible handling of errors
if (!node->loaded) {
SET_ERROR("Error: a surface could not be laoded!");
return NULL;
}
}
newest->next = node;
node->prev = newest;
newest = node;
}
return node->surface;
}
UINT32 SurfaceCache::AddSurface(AnimationSurfaceType* surface, STRUCTURE_FILE_REF* pStructFile) {
surface->hVideoObject = NULL;
CacheEntry* node = new CacheEntry(surface, pStructFile);
surfaceVector.push_back(node);
return surfaceVector.size() - 1;
}
bool SurfaceCache::UnloadSurface(AnimationSurfaceType* animSurfaceType) {
if (animSurfaceType->hVideoObject != NULL) {
DeleteVideoObject(animSurfaceType->hVideoObject);
animSurfaceType->hVideoObject = NULL;
}
return true;
}
bool SurfaceCache::LoadSurface(AnimationSurfaceType* animSurfaceType, STRUCTURE_FILE_REF* pStructureFileRef) {
AuxObjectData *pAuxData;
AnimDebugMsg("SurfaceCache::LoadSurface");
// Load into memory
VOBJECT_DESC VObjectDesc;
HVOBJECT hVObject;
HIMAGE hImage;
CHAR8 sFilename[48];
// Create video object
FilenameForBPP(animSurfaceType->Filename, sFilename);
hImage = CreateImage(sFilename, IMAGE_ALLDATA);
if (hImage == NULL) return TRUE == SET_ERROR("Error: Could not load animation file %s", sFilename);
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMHIMAGE;
VObjectDesc.hImage = hImage;
hVObject = CreateVideoObject( &VObjectDesc );
if ( hVObject == NULL ) {
SET_ERROR("Error: Could not load animation file: %s", sFilename);
// Video Object will set error conition.
DestroyImage( hImage );
return false;
}
// Get aux data
if (hImage->uiAppDataSize == hVObject->usNumberOfObjects * sizeof(AuxObjectData)) {
// Valid auxiliary data, so get # od frames from data
pAuxData = (AuxObjectData*) hImage->pAppData;
animSurfaceType->uiNumFramesPerDir = pAuxData->ubNumberOfFrames;
}
else {
SET_ERROR("Invalid # of animations given");
DestroyImage(hImage);
return false;
}
if (pStructureFileRef != NULL) {
INT16 sStartFrame = 0;
// removed exception coding. Do we even need the next block without that? See original global function
if (AddZStripInfoToVObject(hVObject, pStructureFileRef, TRUE, sStartFrame) == FALSE) {
DestroyImage(hImage);
DeleteVideoObject(hVObject);
SET_ERROR("Animation structure ZStrip creation error: %s", sFilename);
return false;
}
}
// the hImage is no longer needed
DestroyImage(hImage);
// Set video object index
animSurfaceType->hVideoObject = hVObject;
// Determine if we have a problem with #frames + directions ( ie mismatch )
if ((animSurfaceType->uiNumDirections * animSurfaceType->uiNumFramesPerDir ) != animSurfaceType->hVideoObject->usNumberOfObjects) {
AnimDebugMsg(String("Surface Database: WARNING!!! Surface %d has #frames mismatch.", usSurfaceIndex));
}
return true;
}
}
+49
View File
@@ -0,0 +1,49 @@
#pragma once
#ifndef _LBT_SURFACECACHE__H_
#define _LBT_SURFACECACHE__H_
#include "Animation Data.h"
#include "Utilities.h"
#include "Sys Globals.h"
#include "Debug Control.h"
namespace LogicalBodyTypes {
class SurfaceCache {
private:
struct CacheEntry {
CacheEntry(AnimationSurfaceType* animSurface, STRUCTURE_FILE_REF* pStructFile) {
surface = animSurface;
structFile = pStructFile;
loaded = false;
prev = next = NULL;
}
bool loaded;
AnimationSurfaceType* surface;
STRUCTURE_FILE_REF* structFile;
CacheEntry* prev;
CacheEntry* next;
} typedef CacheEntry;
typedef std::vector<CacheEntry*> SurfaceVector;
public:
SurfaceCache(UINT32 size);
~SurfaceCache();
AnimationSurfaceType* GetLoadedSurface(UINT32 idx);
UINT32 AddSurface(AnimationSurfaceType* surface, STRUCTURE_FILE_REF* pStructFile);
private:
UINT32 loadedElementsMax;
UINT32 loadedElements;
CacheEntry* newest;
CacheEntry* oldest;
SurfaceVector surfaceVector;
static bool LoadSurface(AnimationSurfaceType* animSurfaceType, STRUCTURE_FILE_REF* pStructureFileRef);
static bool SurfaceCache::UnloadSurface(AnimationSurfaceType* animSurfaceType);
};
}
#endif
Binary file not shown.
+55
View File
@@ -0,0 +1,55 @@
#ifndef _LBT_SURFACE__H_
#define _LBT_SURFACE__H_
#pragma once
#include "LogicalBodyTypes/AbstractXMLLoader.h"
#include "Animation Data.h"
#include "Utilities.h"
#include "Sys Globals.h"
#include "structure.h"
extern void FreeStructureFileRef(STRUCTURE_FILE_REF* pFileRef);
namespace LogicalBodyTypes {
// Singleton serving as container for AnimationSurfaceType instances.
// Implements loading said instances from an XML files.
class SurfaceDB : public AbstractXMLLoader, public Singleton<SurfaceDB> {
public:
using Singleton <SurfaceDB>::Instance;
typedef std::map <std::string, AnimationSurfaceType*> AnimSurfaceTypeMap;
typedef std::map <std::string, STRUCTURE_FILE_REF*> StructTypeFileMap;
typedef std::map <AnimationSurfaceType*, STRUCTURE_FILE_REF*> Surface2StructMap;
typedef AnimSurfaceTypeMap::const_iterator iterator;
private:
enum ParseState {
E_ELEMENT_ANIMSURFACES = FIRST_SUBCLASS_STATE,
E_ELEMENT_ANIMSURFACE
};
AnimSurfaceTypeMap animSurfaceTypes;
StructTypeFileMap structTypeFiles;
Surface2StructMap surfaceStructs;
public:
SurfaceDB(void);
~SurfaceDB(void);
AnimSurfaceTypeMap::const_iterator begin();
AnimSurfaceTypeMap::const_iterator end();
AnimationSurfaceType* GetAnimSurfaceType(std::string name);
STRUCTURE_FILE_REF* GetStructFile(AnimationSurfaceType* animSurfaceType);
private:
static void XMLCALL StartElementHandle(void* userData, const XML_Char* name, const XML_Char** atts);
static void XMLCALL EndElementHandle(void* userData, const XML_Char* name);
static void XMLCALL CharacterDataHandle(void* userData, const XML_Char* str, int len);
static void XMLCALL ExternalEntityHandler(XML_Parser parser, const XML_Char* context, const XML_Char* base, const XML_Char* systemId, const XML_Char* publicId);
bool AddAnimSurfaceType(std::string name, AnimationSurfaceType* animSurfaceType, STRUCTURE_FILE_REF* pStructFile);
STRUCTURE_FILE_REF* LoadStructFile(STR fileName);
};
}
#endif
@@ -0,0 +1,18 @@
#include "XMLParseException.h"
XMLParseException::XMLParseException(const char* text, const char* function, int line, const char* file) : std::exception(), message(text), _LINE(line) {
}
XMLParseException::XMLParseException(const char* text, const XML_Char* name, XML_Parser* parser) : std::exception(), message(text), _LINE(0) {
message = text;
if (parser != NULL) {
_LINE = XML_GetCurrentLineNumber(*parser);
}
}
XMLParseException::~XMLParseException(void) {
}
const char* XMLParseException::what() const throw() {
return message.c_str();
}
@@ -0,0 +1,26 @@
#pragma once
#ifndef _LBT_XMLPARSEEXCEPTION__H_
#define _LBT_XMLPARSEEXCEPTION__H_
#include "LogicalBodyTypes/XMLParseException.h"
#include "expat.h"
#include <exception>
#include <string>
class XMLParseException : public std::exception {
public:
XMLParseException(const char* text, const char* function, int line, const char* file);
XMLParseException(const char* text, const XML_Char* name, XML_Parser* parser = NULL);
const char* what() const throw();
~XMLParseException(void);
public:
int _LINE;
std::string message;
std::string _FILE;
std::string _FUNCTION;
std::string _time;
};
#endif
+3 -1
View File
@@ -1526,7 +1526,9 @@ BOOLEAN RenderShopKeeperInterface()
sCenX, sCenY,
pSoldier->usAniFrame,
&rect,
pSoldier->pShades[pSoldier->ubFadeLevel] );
pSoldier->pShades[pSoldier->ubFadeLevel],
TRUE
);
UnLockVideoSurface( FRAME_BUFFER );
}
+26 -1
View File
@@ -66,6 +66,19 @@
<ClInclude Include="Items.h" />
<ClInclude Include="Ja25_Tactical.h" />
<ClInclude Include="Keys.h" />
<ClInclude Include="LogicalBodyTypes\AbstractXMLLoader.h" />
<ClInclude Include="LogicalBodyTypes\BodyType.h" />
<ClInclude Include="LogicalBodyTypes\BodyTypeDB.h" />
<ClInclude Include="LogicalBodyTypes\EnumeratorDB.h" />
<ClInclude Include="LogicalBodyTypes\Filter.h" />
<ClInclude Include="LogicalBodyTypes\FilterDB.h" />
<ClInclude Include="LogicalBodyTypes\Layers.h" />
<ClInclude Include="LogicalBodyTypes\PaletteDB.h" />
<ClInclude Include="LogicalBodyTypes\PaletteTable.h" />
<ClInclude Include="LogicalBodyTypes\Singleton.h" />
<ClInclude Include="LogicalBodyTypes\SurfaceCache.h" />
<ClInclude Include="LogicalBodyTypes\SurfaceDB.h" />
<ClInclude Include="LogicalBodyTypes\XMLParseException.h" />
<ClInclude Include="LOS.h" />
<ClInclude Include="Map Information.h" />
<ClInclude Include="merc entering.h" />
@@ -155,13 +168,25 @@
<ClCompile Include="Items.cpp" />
<ClCompile Include="Ja25_Tactical.cpp" />
<ClCompile Include="Keys.cpp" />
<ClCompile Include="LogicalBodyTypes\AbstractXMLLoader.cpp" />
<ClCompile Include="LogicalBodyTypes\BodyType.cpp" />
<ClCompile Include="LogicalBodyTypes\BodyTypeDB.cpp" />
<ClCompile Include="LogicalBodyTypes\EnumeratorDB.cpp" />
<ClCompile Include="LogicalBodyTypes\Filter.cpp" />
<ClCompile Include="LogicalBodyTypes\FilterDB.cpp" />
<ClCompile Include="LogicalBodyTypes\Layers.cpp" />
<ClCompile Include="LogicalBodyTypes\PaletteDB.cpp" />
<ClCompile Include="LogicalBodyTypes\PaletteTable.cpp" />
<ClCompile Include="LogicalBodyTypes\SurfaceCache.cpp" />
<ClCompile Include="LogicalBodyTypes\SurfaceDB.cpp" />
<ClCompile Include="LogicalBodyTypes\XMLParseException.cpp" />
<ClCompile Include="LOS.cpp" />
<ClCompile Include="Map Information.cpp" />
<ClCompile Include="Merc Entering.cpp" />
<ClCompile Include="Merc Hiring.cpp" />
<ClCompile Include="Militia Control.cpp" />
<ClCompile Include="MiniGame.cpp" />
<ClCompile Include="Morale.cpp" />
<ClCompile Include="Morale.cpp" />
<ClCompile Include="opplist.cpp" />
<ClCompile Include="Overhead.cpp" />
<ClCompile Include="PATHAI.cpp" />
+79 -1
View File
@@ -7,6 +7,9 @@
<Filter Include="Source Files">
<UniqueIdentifier>{c1880088-a976-405e-919e-9f1e97ad6701}</UniqueIdentifier>
</Filter>
<Filter Include="Logical Bodytypes">
<UniqueIdentifier>{7ccf82e9-8713-4351-af1f-218106a69555}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Action Items.h">
@@ -147,7 +150,7 @@
<ClInclude Include="MiniGame.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Morale.h">
<ClInclude Include="Morale.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="opplist.h">
@@ -276,6 +279,45 @@
<ClInclude Include="DynamicDialogue.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\AbstractXMLLoader.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\BodyType.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\BodyTypeDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\EnumeratorDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Filter.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\FilterDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Layers.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\PaletteDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\PaletteTable.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Singleton.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\SurfaceCache.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\SurfaceDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\XMLParseException.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Air Raid.cpp">
@@ -704,5 +746,41 @@
<ClCompile Include="XML_StructureConstruct.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\AbstractXMLLoader.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\BodyType.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\BodyTypeDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\EnumeratorDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\Filter.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\FilterDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\Layers.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\PaletteDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\PaletteTable.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\SurfaceCache.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\SurfaceDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\XMLParseException.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
</ItemGroup>
</Project>
+25
View File
@@ -66,6 +66,19 @@
<ClInclude Include="Items.h" />
<ClInclude Include="Ja25_Tactical.h" />
<ClInclude Include="Keys.h" />
<ClInclude Include="LogicalBodyTypes\AbstractXMLLoader.h" />
<ClInclude Include="LogicalBodyTypes\BodyType.h" />
<ClInclude Include="LogicalBodyTypes\BodyTypeDB.h" />
<ClInclude Include="LogicalBodyTypes\EnumeratorDB.h" />
<ClInclude Include="LogicalBodyTypes\Filter.h" />
<ClInclude Include="LogicalBodyTypes\FilterDB.h" />
<ClInclude Include="LogicalBodyTypes\Layers.h" />
<ClInclude Include="LogicalBodyTypes\PaletteDB.h" />
<ClInclude Include="LogicalBodyTypes\PaletteTable.h" />
<ClInclude Include="LogicalBodyTypes\Singleton.h" />
<ClInclude Include="LogicalBodyTypes\SurfaceCache.h" />
<ClInclude Include="LogicalBodyTypes\SurfaceDB.h" />
<ClInclude Include="LogicalBodyTypes\XMLParseException.h" />
<ClInclude Include="LOS.h" />
<ClInclude Include="Map Information.h" />
<ClInclude Include="merc entering.h" />
@@ -156,6 +169,18 @@
<ClCompile Include="Items.cpp" />
<ClCompile Include="Ja25_Tactical.cpp" />
<ClCompile Include="Keys.cpp" />
<ClCompile Include="LogicalBodyTypes\AbstractXMLLoader.cpp" />
<ClCompile Include="LogicalBodyTypes\BodyType.cpp" />
<ClCompile Include="LogicalBodyTypes\BodyTypeDB.cpp" />
<ClCompile Include="LogicalBodyTypes\EnumeratorDB.cpp" />
<ClCompile Include="LogicalBodyTypes\Filter.cpp" />
<ClCompile Include="LogicalBodyTypes\FilterDB.cpp" />
<ClCompile Include="LogicalBodyTypes\Layers.cpp" />
<ClCompile Include="LogicalBodyTypes\PaletteDB.cpp" />
<ClCompile Include="LogicalBodyTypes\PaletteTable.cpp" />
<ClCompile Include="LogicalBodyTypes\SurfaceCache.cpp" />
<ClCompile Include="LogicalBodyTypes\SurfaceDB.cpp" />
<ClCompile Include="LogicalBodyTypes\XMLParseException.cpp" />
<ClCompile Include="LOS.cpp" />
<ClCompile Include="Map Information.cpp" />
<ClCompile Include="Merc Entering.cpp" />
+78
View File
@@ -7,6 +7,9 @@
<Filter Include="Source Files">
<UniqueIdentifier>{c1880088-a976-405e-919e-9f1e97ad6701}</UniqueIdentifier>
</Filter>
<Filter Include="Logical Bodytypes">
<UniqueIdentifier>{7ccf82e9-8713-4351-af1f-218106a69555}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Action Items.h">
@@ -279,6 +282,45 @@
<ClInclude Include="MiniGame.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\AbstractXMLLoader.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\BodyType.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\BodyTypeDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\EnumeratorDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Filter.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\FilterDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Layers.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\PaletteDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\PaletteTable.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Singleton.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\SurfaceCache.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\SurfaceDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\XMLParseException.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Air Raid.cpp">
@@ -707,5 +749,41 @@
<ClCompile Include="Minigame.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\AbstractXMLLoader.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\BodyType.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\BodyTypeDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\EnumeratorDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\Filter.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\FilterDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\Layers.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\PaletteDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\PaletteTable.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\SurfaceCache.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\SurfaceDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\XMLParseException.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
</ItemGroup>
</Project>
+25
View File
@@ -66,6 +66,19 @@
<ClInclude Include="Items.h" />
<ClInclude Include="Ja25_Tactical.h" />
<ClInclude Include="Keys.h" />
<ClInclude Include="LogicalBodyTypes\AbstractXMLLoader.h" />
<ClInclude Include="LogicalBodyTypes\BodyType.h" />
<ClInclude Include="LogicalBodyTypes\BodyTypeDB.h" />
<ClInclude Include="LogicalBodyTypes\EnumeratorDB.h" />
<ClInclude Include="LogicalBodyTypes\Filter.h" />
<ClInclude Include="LogicalBodyTypes\FilterDB.h" />
<ClInclude Include="LogicalBodyTypes\Layers.h" />
<ClInclude Include="LogicalBodyTypes\PaletteDB.h" />
<ClInclude Include="LogicalBodyTypes\PaletteTable.h" />
<ClInclude Include="LogicalBodyTypes\Singleton.h" />
<ClInclude Include="LogicalBodyTypes\SurfaceCache.h" />
<ClInclude Include="LogicalBodyTypes\SurfaceDB.h" />
<ClInclude Include="LogicalBodyTypes\XMLParseException.h" />
<ClInclude Include="LOS.h" />
<ClInclude Include="Map Information.h" />
<ClInclude Include="merc entering.h" />
@@ -156,6 +169,18 @@
<ClCompile Include="Items.cpp" />
<ClCompile Include="Ja25_Tactical.cpp" />
<ClCompile Include="Keys.cpp" />
<ClCompile Include="LogicalBodyTypes\AbstractXMLLoader.cpp" />
<ClCompile Include="LogicalBodyTypes\BodyType.cpp" />
<ClCompile Include="LogicalBodyTypes\BodyTypeDB.cpp" />
<ClCompile Include="LogicalBodyTypes\EnumeratorDB.cpp" />
<ClCompile Include="LogicalBodyTypes\Filter.cpp" />
<ClCompile Include="LogicalBodyTypes\FilterDB.cpp" />
<ClCompile Include="LogicalBodyTypes\Layers.cpp" />
<ClCompile Include="LogicalBodyTypes\PaletteDB.cpp" />
<ClCompile Include="LogicalBodyTypes\PaletteTable.cpp" />
<ClCompile Include="LogicalBodyTypes\SurfaceCache.cpp" />
<ClCompile Include="LogicalBodyTypes\SurfaceDB.cpp" />
<ClCompile Include="LogicalBodyTypes\XMLParseException.cpp" />
<ClCompile Include="LOS.cpp" />
<ClCompile Include="Map Information.cpp" />
<ClCompile Include="Merc Entering.cpp" />
+78
View File
@@ -7,6 +7,9 @@
<Filter Include="Source Files">
<UniqueIdentifier>{c1880088-a976-405e-919e-9f1e97ad6701}</UniqueIdentifier>
</Filter>
<Filter Include="Logical Bodytypes">
<UniqueIdentifier>{7ccf82e9-8713-4351-af1f-218106a69555}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Action Items.h">
@@ -279,6 +282,45 @@
<ClInclude Include="MiniGame.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\AbstractXMLLoader.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\BodyType.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\BodyTypeDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\EnumeratorDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Filter.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\FilterDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Layers.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\PaletteDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\PaletteTable.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\Singleton.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\SurfaceCache.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\SurfaceDB.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
<ClInclude Include="LogicalBodyTypes\XMLParseException.h">
<Filter>Logical Bodytypes</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Air Raid.cpp">
@@ -707,5 +749,41 @@
<ClCompile Include="Minigame.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\AbstractXMLLoader.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\BodyType.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\BodyTypeDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\EnumeratorDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\Filter.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\FilterDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\Layers.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\PaletteDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\PaletteTable.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\SurfaceCache.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\SurfaceDB.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
<ClCompile Include="LogicalBodyTypes\XMLParseException.cpp">
<Filter>Logical Bodytypes</Filter>
</ClCompile>
</ItemGroup>
</Project>
+6
View File
@@ -256,6 +256,12 @@ typedef PARSE_STAGE;
#define DIFFICULTYFILENAME "DifficultySettings.xml"
#define LBT_LAYERSFILENAME "LogicalBodyTypes/Layers.xml"
#define LBT_PALETTESFILENAME "LogicalBodyTypes/Palettes.xml"
#define LBT_ANIMSURFACESFILENAME "LogicalBodyTypes/AnimationSurfaces.xml"
#define LBT_FILTERSFILENAME "LogicalBodyTypes/Filters.xml"
#define LBT_BODYTYPESFILENAME "LogicalBodyTypes/LogicalBodyTypes.xml"
extern BOOLEAN ReadInItemStats(STR fileName, BOOLEAN localizedVersion);
extern BOOLEAN WriteItemStats();