Пример #1
0
bool addSingleCustomBuildingConfig( TiXmlElement* elemRoot,  vector<BuildingConfiguration>* knownBuildings ){
	const char* strName = elemRoot->Attribute("name");
	const char* strGameID = elemRoot->Attribute("gameID");

	if (strName == NULL || strGameID == NULL || strName[0] == 0 || strGameID[0] == 0)
	{
		contentError("<building> node must have name and gameID attributes",elemRoot);
		return false;
	}

	int gameID = TranslateBuildingName(strGameID, contentLoader.custom_workshop_types );

	if (gameID == INVALID_INDEX) {
		return false;
	}

	BuildingConfiguration building(strName, gameID );
	RootBlock* spriteroot = new RootBlock();
	building.sprites = spriteroot;
	if (!parseSpriteNode(spriteroot,elemRoot))
	{
		delete(spriteroot);
		return false;
	}

	//add a copy of 'building' to known buildings
	knownBuildings->push_back( building );
	return true;
}
Пример #2
0
bool parseSpriteNode(SpriteNode* node, TiXmlElement* elemParent)
{
	//TODO: there is a leak here somewhere.
	SpriteBlock* oldSibling = NULL;
	TiXmlElement* elemNode =  elemParent->FirstChildElement();
	const char* strParent = elemParent->Value();
	if (elemNode == NULL)
	{
		contentError("Empty SpriteNode Element",elemParent);
		return false;		
	}
	if ( strcmp(strParent,"building") != 0 && strcmp(strParent,"custom_workshop") != 0 && strcmp(strParent,"rotate") != 0)
	{
		//flag to allow else statements to be empty, rather than needing an "always" tag
		bool allowBlank = (strcmp(strParent,"else") == 0 || elemParent->Attribute("else"));
		// cast should be safe, because only spriteblocks
		// should get here
		int retvalue =parseConditionNode((SpriteBlock *)node,elemNode,allowBlank);
		if (retvalue == 0)
			return false;
		if (retvalue > 0)
			elemNode = elemNode->NextSiblingElement();
	}
	while (elemNode)
	{ 
		if (!readNode(node, elemNode, elemParent, oldSibling))
			return false;
		elemNode = elemNode->NextSiblingElement();
	}
	return true;
}
Пример #3
0
void CPage::loadContentError(ConnectionPtr connection)
{
	Trace("loadContentError()", "", 0);

	std::string strQuery;

	try
	{
		Mutex::Lock lock(m_contentErrorListLock);

		// get all of the pages for this customer to test
		strQuery = Format(SQL_WTT_CONTENT_ERRORS);
		if (ResultPtr result = connection->Query(strQuery))
		{
			while (result->Next())
			{
				RowPtr row = result->GetCurrentRow();

				StringIDList::value_type contentError(row->GetFieldString(1), row->GetFieldLong(2));
				contentError.first = " " + contentError.first + " ";

				Trace("loadContentError() - loading string", contentError.first.c_str(), contentError.second);
				m_contentError.push_back(contentError);
			}
		}
	}
	catch (const std::exception& e)
	{
		LogError("Exception Caught:", e.what(), 0);
	}
}
bool includeFile(SpriteNode* node, TiXmlElement* includeNode, SpriteBlock* &oldSibling)
{
    // get path... ugly
    char configfilepath[FILENAME_BUFFERSIZE] = {0};
    const char* documentRef = getDocument(includeNode);

    if (!getLocalFilename(configfilepath,includeNode->Attribute("file"),documentRef))
    {
        return false;
    }
    ALLEGRO_PATH * incpath = al_create_path(configfilepath);
    al_append_path_component(incpath, "include");
    TiXmlDocument doc( al_path_cstr(incpath, ALLEGRO_NATIVE_PATH_SEP) );
    al_destroy_path(incpath);
	bool loadOkay = doc.LoadFile();
	TiXmlHandle hDoc(&doc);
	TiXmlElement* elemParent;
	if(!loadOkay)
	{
		contentError("Include failed",includeNode);
        WriteErr("File load failed: %s\n",configfilepath);
		WriteErr("Line %d: %s\n",doc.ErrorRow(),doc.ErrorDesc());
		return false;
	}
	elemParent = hDoc.FirstChildElement("include").Element();
	if( elemParent == NULL)
	{
		contentError("Main <include> node not present",&doc);
		return false;
	}
	TiXmlElement* elemNode =  elemParent->FirstChildElement();
	if (elemNode == NULL)
	{
		contentError("Empty include",elemParent);
		return false;
	}
	while (elemNode)
	{ 
		if (!readNode(node, elemNode, elemParent, oldSibling))
			return false;
		elemNode = elemNode->NextSiblingElement();
	}
	return true;
}
bool addSingleVegetationConfig( TiXmlElement* elemRoot,  vector<VegetationConfiguration>* vegetationConfigs, vector<t_matgloss>& plantNames )
{
  const char* sheetIndexStr;
  t_SpriteWithOffset sprite;
  int basefile = -1;
  sprite.fileIndex=basefile;
  sprite.x=0;
  sprite.y=0;
  sprite.animFrames=ALL_FRAMES;
 
  const char* filename = elemRoot->Attribute("file");
	if (filename != NULL && filename[0] != 0)
	{
	  	basefile = loadConfigImgFile((char*)filename, elemRoot);
	}
	
	//kinda round about- looking to needing to shift the lot into the plant elem
	sprite.fileIndex=basefile;
	
  TiXmlElement* elemTree;
  for (elemTree = elemRoot->FirstChildElement("plant");
  	elemTree; elemTree = elemTree->NextSiblingElement("plant") ){
	const char* idstr = elemTree->Attribute("gameID");
  	int gameID = INVALID_INDEX;
  	if (idstr && idstr[0])
  	{
	  	gameID = lookupIndexedType(idstr,plantNames);
  		if (gameID == INVALID_INDEX)
  		{
	  		contentError("No matching plant type",elemTree);
	  		continue;
  		}
	}
    const char* deadstr = elemTree->Attribute("dead");
    bool dead = (deadstr && deadstr[0]);
    const char* saplingstr = elemTree->Attribute("sapling");
    bool sapling = (saplingstr && saplingstr[0]);
    sheetIndexStr = elemTree->Attribute("sheetIndex");
    /* No animated trees.
    	But we may repurpose it later to make a xyz variance?
    sprite.animFrames = getAnimFrames(elemProfession->Attribute("frames"));
	if (sprite.animFrames == 0)
		sprite.animFrames = ALL_FRAMES;*/
    
    //create profession config
    sprite.sheetIndex=atoi(sheetIndexStr);
    VegetationConfiguration vegetationConfiguration(gameID, sprite, !dead, !sapling);
    //add a copy to known creatures
    vegetationConfigs->push_back( vegetationConfiguration );
  }

  return true;
}
Пример #6
0
bool includeFile(SpriteNode* node, TiXmlElement* includeNode, SpriteBlock* &oldSibling)
{
	string filenameStr("buildings/include/");
	filenameStr.append(includeNode->Attribute("file"));

	TiXmlDocument doc( filenameStr.c_str() );
	bool loadOkay = doc.LoadFile();
	TiXmlHandle hDoc(&doc);
	TiXmlElement* elemParent;
	if(!loadOkay)
	{
		contentError("Include failed",includeNode);
		WriteErr("File load failed: %s\n",filenameStr.c_str());
		WriteErr("Line %d: %s\n",doc.ErrorRow(),doc.ErrorDesc());
		return false;
	}
	elemParent = hDoc.FirstChildElement("include").Element();
	if( elemParent == NULL)
	{
		contentError("Main <include> node not present",&doc);
		return false;
	}
	TiXmlElement* elemNode =  elemParent->FirstChildElement();
	if (elemNode == NULL)
	{
		contentError("Empty include",elemParent);
		return false;
	}
	while (elemNode)
	{ 
		if (!readNode(node, elemNode, elemParent, oldSibling))
			return false;
		elemNode = elemNode->NextSiblingElement();
	}
	return true;
}
bool addCreaturesConfig( TiXmlElement* elemRoot, vector<vector<CreatureConfiguration>*>& knownCreatures ){
  int basefile = -1;
  const char* filename = elemRoot->Attribute("file");
  if (filename != NULL && filename[0] != 0)
  {
	basefile = loadConfigImgFile((char*)filename,elemRoot);
  } 
  TiXmlElement* elemCreature = elemRoot->FirstChildElement("creature");
  if (elemCreature == NULL)
  {
     contentError("No creatures found",elemRoot);
     return false;
  }
  while( elemCreature ){
	addSingleCreatureConfig(elemCreature,knownCreatures,basefile );
	elemCreature = elemCreature->NextSiblingElement("creature");
  }
  return true;
}
bool addSingleBuildingConfig( TiXmlElement* elemRoot,  vector<BuildingConfiguration>* knownBuildings ){
    const char* strName = elemRoot->Attribute("name");
    const char* strGameID = elemRoot->Attribute("game_type");
    const char* strGameSub = elemRoot->Attribute("game_subtype");
    const char* strGameCustom = elemRoot->Attribute("game_custom");

    if (strName == NULL || strGameID == NULL || strName[0] == 0 || strGameID[0] == 0)
    {
        contentError("<building> node must have name and game_type attributes",elemRoot);
        return false;
    }
    building_type::building_type main_type = (building_type::building_type) INVALID_INDEX;
    int subtype = INVALID_INDEX;
    string game_type_s;
    FOR_ENUM_ITEMS(building_type,i)
    {
        game_type_s = strGameID;
        if (game_type_s == ENUM_KEY_STR(building_type,i))
        {
            main_type = i;
            break;
        }
    }
void parseWallFloorSpriteElement( TiXmlElement* elemWallFloorSprite, vector<TerrainConfiguration*>& configTable ,int basefile)
{
	const char* spriteIndexStr = elemWallFloorSprite->Attribute("sprite");
	if (spriteIndexStr == NULL || spriteIndexStr[0] == 0)
	{
		contentError("Invalid or missing sprite attribute",elemWallFloorSprite);
		return; //nothing to work with
	}
	// make a base sprite
	t_SpriteWithOffset sprite;
	sprite.sheetIndex=atoi(spriteIndexStr);
	sprite.fileIndex=basefile;
	sprite.x=0;
	sprite.y=0;
	sprite.animFrames=ALL_FRAMES; //augh! no animated terrains! please!
	// check for local file definitions
	const char* filename = elemWallFloorSprite->Attribute("file");
	if (filename != NULL && filename[0] != 0)
	{
		sprite.fileIndex = loadConfigImgFile((char*)filename,elemWallFloorSprite);
	}
	
	vector<int> lookupKeys;
	
	// look through terrain elements
	TiXmlElement* elemTerrain = elemWallFloorSprite->FirstChildElement("terrain");
	for(TiXmlElement* elemTerrain = elemWallFloorSprite->FirstChildElement("terrain");
		 elemTerrain;
		 elemTerrain = elemTerrain->NextSiblingElement("terrain"))
	{
		//get a terrain type 
		int targetElem=INVALID_INDEX;
		const char* gameIDstr = elemTerrain->Attribute("value");
		if (gameIDstr == NULL || gameIDstr[0] == 0)
		{
			contentError("Invalid or missing value attribute",elemTerrain);
			continue;
		}
		targetElem = atoi (gameIDstr);
		//add it to the lookup vector
		lookupKeys.push_back(targetElem);
		if (configTable.size() <= (uint32_t)targetElem)
		{
			//increase size if needed
			configTable.resize(targetElem+1,NULL);
		}
		if (configTable[targetElem]==NULL)
		{
			// cleaned up in flushTerrainConfig
			configTable[targetElem] = new TerrainConfiguration();
		}
	}
	
	// check we have some terrain types set
	int elems = (int)lookupKeys.size();
	if (elems == 0)
		return; //nothing to link to
	
	// parse material elements
	TiXmlElement* elemMaterial = elemWallFloorSprite->FirstChildElement("material");
	if (elemMaterial == NULL)
	{
		// if none, set default terrain sprites for each terrain type
		for (int i=0 ; i < elems; i++ )
		{
			TerrainConfiguration *tConfig = configTable[lookupKeys[i]];
			// if that was null we have *really* screwed up earlier
			// only update if not by previous configs
			if (tConfig->defaultSprite.sheetIndex == UNCONFIGURED_INDEX)
			{
				tConfig->defaultSprite = sprite;
			}
		}
	}
	for( ;elemMaterial;elemMaterial = elemMaterial->NextSiblingElement("material"))
	{
		// get material type
		int elemIndex = lookupMaterialType(elemMaterial->Attribute("value"));
		if (elemIndex == INVALID_INDEX)
		{
			contentError("Invalid or missing value attribute",elemMaterial);
			continue;				
		}
		
		// parse subtype elements
		TiXmlElement* elemSubtype = elemMaterial->FirstChildElement("subtype");
		if (elemSubtype == NULL)
		{
			// if none, set material default for each terrain type
			for (int i=0 ; i < elems; i++ )
			{
				TerrainConfiguration *tConfig = configTable[lookupKeys[i]];
				// if that was null we have *really* screwed up earlier
				// create a new TerrainMaterialConfiguration if required
					// make sure we have room for it first
				if (tConfig->terrainMaterials.size() <= (uint32_t)elemIndex)
				{
					// dont make a full size vector in advance- most of the time
					// we will only need the first few
					tConfig->terrainMaterials.resize(elemIndex+1,NULL);
				}
				if (tConfig->terrainMaterials[elemIndex] == NULL)
				{
					tConfig->terrainMaterials[elemIndex] = new TerrainMaterialConfiguration();
				}
				// only update if not set by earlier configs
				if (tConfig->terrainMaterials[elemIndex]->defaultSprite.sheetIndex == UNCONFIGURED_INDEX)
				{
					tConfig->terrainMaterials[elemIndex]->defaultSprite = sprite;
				}
			} 	
		}
		for (;elemSubtype; elemSubtype = elemSubtype ->NextSiblingElement("subtype"))
		{
			// get subtype
			int subtypeId = lookupMaterialIndex(elemIndex,elemSubtype->Attribute("value"));
			if (subtypeId == INVALID_INDEX)
			{
				contentError("Invalid or missing value attribute",elemSubtype);
				continue;				
			}
			
			// set subtype sprite for each terrain type
			for (int i=0 ; i < elems; i++ )
			{
				TerrainConfiguration *tConfig = configTable[lookupKeys[i]];
				//if that was null we have *really* screwed up earlier
				//create a new TerrainMaterialConfiguration if required
					//make sure we have room for it first
				if (tConfig->terrainMaterials.size() <= (uint32_t)elemIndex)
				{
					//dont make a full size vector in advance- we wont need it except
					//for those who insist on Soap Fortresses
					tConfig->terrainMaterials.resize(elemIndex+1,NULL);
				}
				if (tConfig->terrainMaterials[elemIndex] == NULL)
				{
					tConfig->terrainMaterials[elemIndex] = new TerrainMaterialConfiguration();
				}
				// add to map (if not already present)
				map<int,t_SpriteWithOffset>::iterator it = tConfig->terrainMaterials[elemIndex]->overridingMaterials.find(subtypeId);
				if (it == tConfig->terrainMaterials[elemIndex]->overridingMaterials.end())
				{
					tConfig->terrainMaterials[elemIndex]->overridingMaterials[subtypeId]=sprite;
				}			
			} 			
		}
	}
}
Пример #10
0
int parseConditionNode(ConditionalNode* node, TiXmlElement* elemCondition, bool silent){
	const char* strType = elemCondition->Value();
	BlockCondition* cond = NULL;	
	if( strcmp(strType, "NeighbourWall") == 0){
		cond = new NeighbourWallCondition( elemCondition->Attribute("dir") );
	}

	else if( strcmp(strType, "PositionIndex") == 0){
		cond = new PositionIndexCondition( elemCondition->Attribute("value") );
	} 

	else if( strcmp(strType, "MaterialType") == 0){
		cond = new MaterialTypeCondition( elemCondition->Attribute("value") , elemCondition->Attribute("subtype"));
	}   

	else if( strcmp(strType, "always") == 0){
		cond = new AlwaysCondition();
	} 

	else if( strcmp(strType, "never") == 0){
		cond = new NeverCondition();
	}     

	else if( strcmp(strType, "BuildingOccupancy") == 0){
		cond = new BuildingOccupancyCondition( elemCondition->Attribute("value") );
	} 

	else if( strcmp(strType, "NeighbourSameBuilding") == 0){
		cond = new NeighbourSameBuildingCondition( elemCondition->Attribute("dir") );
	}     

	else if( strcmp(strType, "NeighbourSameType") == 0){
		cond = new NeighbourSameTypeCondition( elemCondition->Attribute("dir") );
	}

	else if( strcmp(strType, "NeighbourOfType") == 0){
		cond = new NeighbourOfTypeCondition( elemCondition->Attribute("dir") , elemCondition->Attribute("value") );
	}

	else if( strcmp(strType, "NeighbourIdentical") == 0){
		cond = new NeighbourIdenticalCondition( elemCondition->Attribute("dir") );
	}     

	else if( strcmp(strType, "AnimationFrame") == 0){
		cond = new AnimationFrameCondition( elemCondition->Attribute("value") );
	}  

	else if( strcmp(strType, "FluidBelow") == 0){
		cond = new FluidBelowCondition( elemCondition->Attribute("value") );
	}  

	else if( strcmp(strType, "HaveFloor") == 0){
		cond = new HaveFloorCondition();
	}

	else if( strcmp(strType, "and") == 0){
		AndConditionalNode* andNode = new AndConditionalNode();
		cond = andNode;
		if (!parseRecursiveNodes(andNode, elemCondition))
		{
			delete(andNode);
			return 0;
		}
	}

	else if( strcmp(strType, "or") == 0){
		OrConditionalNode* orNode = new OrConditionalNode();
		cond = orNode;
		if (!parseRecursiveNodes(orNode, elemCondition))
		{
			delete(orNode);
			return 0;
		}
	}

	else if( strcmp(strType, "not") == 0){
		NotConditionalNode* notNode = new NotConditionalNode();
		cond = notNode;
		if (!parseRecursiveNodes(notNode, elemCondition))
		{
			delete(notNode);
			return 0;
		}
	}

	if (cond != NULL)
	{ 
		if (!node->addCondition( cond ))
		{
			contentError("Unable to add subcondition",elemCondition);
			delete(cond);
			return 0;	
		}
		return 1;
	}
	else if (!silent)
	{
		contentError("Misplaced or invalid element in Condition",elemCondition);
		return 0;		  
	}
	return -1;
}
Пример #11
0
inline bool readNode(SpriteNode* node, TiXmlElement* elemNode, TiXmlElement* elemParent, SpriteBlock* &oldSibling)
{
	const char* strType = elemNode->Value();
	if (strcmp(strType, "if") == 0 || strcmp(strType, "else") == 0)
	{
		SpriteBlock* block = new SpriteBlock();
		if (!elemNode->Attribute("file") && elemParent->Attribute("file"))
		{
			elemNode->SetAttribute("file", elemParent->Attribute("file"));
		}
		if (!parseSpriteNode(block,elemNode))
		{
			delete(block);
			return false;
		}
		if (elemNode->Attribute("else") || strcmp(strType, "else") == 0)
		{
			if (!oldSibling)
			{
				contentError("Misplaced or invalid element in SpriteNode",elemNode);
				return false;						
			}
			oldSibling->addElse(block);	
		}
		else
		{
			node->addChild(block);
		}
		oldSibling = block;
	}
	else if (strcmp(strType, "rotate") == 0)
	{
		RotationBlock* block = new RotationBlock();
		if (!elemNode->Attribute("file") && elemParent->Attribute("file"))
		{
			elemNode->SetAttribute("file",elemParent->Attribute("file"));
		}
		if (!parseSpriteNode(block,elemNode))
		{
			delete(block);
			return false;
		}
		else
		{
			node->addChild(block);
		}
		oldSibling = NULL;
	}
	else if ((strcmp(strType, "sprite") == 0) || (strcmp(strType, "empty") == 0))
	{
		int fileindex = 0;
		const char* pfilename = elemParent->Attribute("file");
		if (pfilename != NULL && pfilename[0] != 0)
		{
			fileindex = loadConfigImgFile((char*)pfilename,elemNode);
		}
		SpriteElement* sprite = new SpriteElement();
		sprite->sprite.set_by_xml(elemNode, fileindex);
		node->addChild(sprite);
	}
	else if (strcmp(strType, "include") == 0)
	{
		if (!includeFile(node,elemNode,oldSibling))
		{
			return false;
		}
	}
	else
	{
		contentError("Misplaced or invalid element in SpriteNode",elemNode);
		return false;
	}		
	return true;
}
Пример #12
0
void parseColorElement( TiXmlElement* elemColor, vector<ColorConfiguration> & configTable)
{
	const char* colorRedStr = elemColor->Attribute("red");
	if(colorRedStr == NULL || colorRedStr[0] == 0)
	{
		contentError("Invalid or missing color attribute",elemColor);
		return; //nothing to work with
	}
	const char* colorGreenStr = elemColor->Attribute("green");
	if(colorGreenStr == NULL || colorGreenStr[0] == 0)
	{
		contentError("Invalid or missing color attribute",elemColor);
		return; //nothing to work with
	}
	const char* colorBlueStr = elemColor->Attribute("blue");
	if(colorBlueStr == NULL || colorBlueStr[0] == 0)
	{
		contentError("Invalid or missing color attribute",elemColor);
		return; //nothing to work with
	}
	int red = atoi(colorRedStr);
	int green = atoi(colorGreenStr);
	int blue = atoi(colorBlueStr);
	ALLEGRO_COLOR color = al_map_rgb(red, green, blue);

	

	//parse material elements
	TiXmlElement* elemMaterial = elemColor->FirstChildElement("material");
	if(elemMaterial == NULL)
	{
		//if none, there's nothing to be done with this color.
		contentError("Invalid or missing material attribute",elemColor);
		return;
	}
	for( ;elemMaterial;elemMaterial = elemMaterial->NextSiblingElement("material"))
	{
		// get material type
		int elemIndex = lookupMaterialType(elemMaterial->Attribute("value"));
		if (elemIndex == INVALID_INDEX)
		{
			contentError("Invalid or missing value attribute",elemMaterial);
			continue;				
		}

		// parse subtype elements
		TiXmlElement* elemSubtype = elemMaterial->FirstChildElement("subtype");
		if (elemSubtype == NULL)
		{
			// add the configurations
			if (configTable.size() <= (uint32_t)elemIndex)
			{
				//increase size if needed
				configTable.resize(elemIndex+1);
			}
			if(configTable.at(elemIndex).colorSet == false)
			{
			configTable.at(elemIndex).color = color;
			configTable.at(elemIndex).colorSet = true;
			}
			return;
		}
		for ( ;elemSubtype; elemSubtype = elemSubtype ->NextSiblingElement("subtype"))
		{
			// get subtype
			int subtypeId = lookupMaterialIndex( elemIndex,elemSubtype->Attribute("value"));
			if (subtypeId == INVALID_INDEX)
			{
				contentError("Invalid or missing value attribute",elemSubtype);
				continue;
			}
			
			// add the configurations
			if (configTable.size() <= (uint32_t)elemIndex)
			{
				//increase size if needed
				configTable.resize(elemIndex+1);
			}

			if (configTable.at(elemIndex).colorMaterials.size() <= (uint32_t)subtypeId)
			{
				//increase size if needed
				configTable.at(elemIndex).colorMaterials.resize(subtypeId+1);
			}
			if (configTable.at(elemIndex).colorMaterials.at(subtypeId).colorSet == false)
			{
				configTable.at(elemIndex).colorMaterials.at(subtypeId).color = color;
				configTable.at(elemIndex).colorMaterials.at(subtypeId).colorSet = true;
			}
		}
	}
}
Пример #13
0
inline bool readNode(SpriteNode* node, TiXmlElement* elemNode, TiXmlElement* elemParent, SpriteBlock* &oldSibling)
{
	const char* strType = elemNode->Value();
	if (strcmp(strType, "if") == 0 || strcmp(strType, "else") == 0)
	{
		SpriteBlock* block = new SpriteBlock();
		if (!elemNode->Attribute("file") && elemParent->Attribute("file"))
		{
			elemNode->SetAttribute("file", elemParent->Attribute("file"));
		}
		if (!parseSpriteNode(block,elemNode))
		{
			delete(block);
			return false;
		}
		if (elemNode->Attribute("else") || strcmp(strType, "else") == 0)
		{
			if (!oldSibling)
			{
				contentError("Misplaced or invalid element in SpriteNode",elemNode);
				return false;						
			}
			oldSibling->addElse(block);	
		}
		else
		{
			node->addChild(block);
		}
		oldSibling = block;
	}
	else if (strcmp(strType, "rotate") == 0)
	{
		RotationBlock* block = new RotationBlock();
		if (!elemNode->Attribute("file") && elemParent->Attribute("file"))
		{
			elemNode->SetAttribute("file",elemParent->Attribute("file"));
		}
		if (!parseSpriteNode(block,elemNode))
		{
			delete(block);
			return false;
		}
		else
		{
			node->addChild(block);
		}
		oldSibling = NULL;
	}
	else if ((strcmp(strType, "sprite") == 0) || (strcmp(strType, "empty") == 0))
	{
		SpriteElement* sprite = new SpriteElement();
		const char* strSheetIndex = elemNode->Attribute("index");
		const char* strOffsetX = elemNode->Attribute("offsetx");
		const char* strOffsetY = elemNode->Attribute("offsety");
		const char* filename = elemNode->Attribute("file");
		getAnimFrames(elemNode->Attribute("frames"));
		sprite->sprite.animFrames = getAnimFrames(elemNode->Attribute("frames"));
		if (sprite->sprite.animFrames == 0)
			sprite->sprite.animFrames = ALL_FRAMES;

		sprite->sprite.sheetIndex = (strSheetIndex != 0 ? atoi(strSheetIndex) : -1);
		sprite->sprite.x    = (strOffsetX    != 0 ? atoi(strOffsetX)    : 0);
		sprite->sprite.y   = (strOffsetY    != 0 ? atoi(strOffsetY)    : 0);
		sprite->sprite.fileIndex = -1;
		if (filename != NULL && filename[0] != 0)
		{
		  	sprite->sprite.fileIndex = loadConfigImgFile((char*)filename,elemNode);
		}
		else
		{
		  const char* pfilename = elemParent->Attribute("file");
	      if (pfilename != NULL && pfilename[0] != 0)
	      {
		      sprite->sprite.fileIndex = loadConfigImgFile((char*)pfilename,elemNode);
	      }
		}
		node->addChild(sprite);
	}
	else if (strcmp(strType, "include") == 0)
	{
		if (!includeFile(node,elemNode,oldSibling))
		{
			return false;
		}
	}
	else
	{
		contentError("Misplaced or invalid element in SpriteNode",elemNode);
		return false;
	}		
	return true;
}
void parseWallFloorSpriteElement( TiXmlElement* elemWallFloorSprite, vector<TerrainConfiguration*>& configTable ,int basefile, bool floor)
{
	const char* spriteSheetIndexStr = elemWallFloorSprite->Attribute("sheetIndex");
	const char* spriteSpriteStr = elemWallFloorSprite->Attribute("sprite");
	const char* spriteIndexStr = elemWallFloorSprite->Attribute("index");
	if ((spriteSheetIndexStr == NULL || spriteSheetIndexStr[0] == 0) && (spriteSpriteStr == NULL || spriteSpriteStr[0] == 0) && (spriteIndexStr == NULL || spriteIndexStr[0] == 0))
	{
		contentError("Invalid or missing sprite attribute",elemWallFloorSprite);
		return; //nothing to work with
	}
	// make a base sprite
	c_sprite sprite;
	if(floor)
	{
		sprite.set_size(SPRITEWIDTH, (TILEHEIGHT + FLOORHEIGHT));
		sprite.set_offset(0, (WALLHEIGHT));
	}
	sprite.set_needoutline(1);
	sprite.set_by_xml(elemWallFloorSprite, basefile);

	vector<int> lookupKeys;

	// look through terrain elements
	TiXmlElement* elemTerrain = elemWallFloorSprite->FirstChildElement("terrain");
	for(TiXmlElement* elemTerrain = elemWallFloorSprite->FirstChildElement("terrain");
		elemTerrain;
		elemTerrain = elemTerrain->NextSiblingElement("terrain"))
	{
		//get a terrain type 
		int targetElem=INVALID_INDEX;
		const char* gameIDstr = elemTerrain->Attribute("value");
		if (gameIDstr == NULL || gameIDstr[0] == 0)
		{
			contentError("Invalid or missing value attribute",elemTerrain);
			continue;
		}
		targetElem = atoi (gameIDstr);
		//add it to the lookup vector
		lookupKeys.push_back(targetElem);
		if (configTable.size() <= (uint32_t)targetElem)
		{
			//increase size if needed
			configTable.resize(targetElem+1,NULL);
		}
		if (configTable[targetElem]==NULL)
		{
			// cleaned up in flushTerrainConfig
			configTable[targetElem] = new TerrainConfiguration();
		}
	}

	// check we have some terrain types set
	int elems = (int)lookupKeys.size();
	if (elems == 0)
		return; //nothing to link to

	vector<bool> formToggle;
	formToggle.resize(NUM_FORMS);
	// parse weather tile is for a block, log, etc
	TiXmlElement* elemForm = elemWallFloorSprite->FirstChildElement("form");
	if(elemForm == NULL)
	{
		formToggle[0] = true;
	}
	for( ;elemForm;elemForm = elemForm->NextSiblingElement("form"))
	{
		const char * strForm = elemForm->Attribute("value");

		if( strcmp(strForm, "bar") == 0)
			formToggle[FORM_BAR] = true;
		if( strcmp(strForm, "block") == 0)
			formToggle[FORM_BLOCK] = true;
		if( strcmp(strForm, "boulder") == 0)
			formToggle[FORM_BOULDER] = true;
		if( strcmp(strForm, "log") == 0)
			formToggle[FORM_LOG] = true;
	}
	// parse material elements
	TiXmlElement* elemMaterial = elemWallFloorSprite->FirstChildElement("material");
	if (elemMaterial == NULL)
	{
		// if none, set default terrain sprites for each terrain type
		for (int i=0 ; i < elems; i++ )
		{
			TerrainConfiguration *tConfig = configTable[lookupKeys[i]];
			// if that was null we have *really* screwed up earlier
			// only update if not by previous configs
			for( int i = 0; i < NUM_FORMS; i++)
			{
				if(formToggle[i])
					if (tConfig->defaultSprite[i].get_sheetindex() == UNCONFIGURED_INDEX)
					{
						tConfig->defaultSprite[i] = sprite;
					}
			}
		}
	}
	for( ;elemMaterial;elemMaterial = elemMaterial->NextSiblingElement("material"))
	{
		// get material type
		int elemIndex = lookupMaterialType(elemMaterial->Attribute("value"));
		if (elemIndex == INVALID_INDEX)
		{
			contentError("Invalid or missing value attribute",elemMaterial);
			continue;				
		}

		// parse subtype elements
		TiXmlElement* elemSubtype = elemMaterial->FirstChildElement("subtype");
		if (elemSubtype == NULL)
		{
			// if none, set material default for each terrain type
			for (int i=0 ; i < elems; i++ )
			{
				TerrainConfiguration *tConfig = configTable[lookupKeys[i]];
				// if that was null we have *really* screwed up earlier
				// create a new TerrainMaterialConfiguration if required
				// make sure we have room for it first
				if (tConfig->terrainMaterials.size() <= (uint32_t)elemIndex)
				{
					// dont make a full size vector in advance- most of the time
					// we will only need the first few
					tConfig->terrainMaterials.resize(elemIndex+1,NULL);
				}
				if (tConfig->terrainMaterials[elemIndex] == NULL)
				{
					tConfig->terrainMaterials[elemIndex] = new TerrainMaterialConfiguration();
				}
				// only update if not set by earlier configs
				for( int i = 0; i < NUM_FORMS; i++)
				{
					if(formToggle[i])
						if (tConfig->terrainMaterials[elemIndex]->defaultSprite[i].get_sheetindex() == UNCONFIGURED_INDEX)
						{
							tConfig->terrainMaterials[elemIndex]->defaultSprite[i] = sprite;
						}
				}
			} 	
		}
		for (;elemSubtype; elemSubtype = elemSubtype ->NextSiblingElement("subtype"))
		{
			// get subtype
			int subtypeId = lookupMaterialIndex(elemIndex,elemSubtype->Attribute("value"));
			if (subtypeId == INVALID_INDEX)
			{
				contentError("Invalid or missing value attribute",elemSubtype);
				continue;				
			}

			// set subtype sprite for each terrain type
			for (int i=0 ; i < elems; i++ )
			{
				TerrainConfiguration *tConfig = configTable[lookupKeys[i]];
				//if that was null we have *really* screwed up earlier
				//create a new TerrainMaterialConfiguration if required
				//make sure we have room for it first
				if (tConfig->terrainMaterials.size() <= (uint32_t)elemIndex)
				{
					//dont make a full size vector in advance- we wont need it except
					//for those who insist on Soap Fortresses
					tConfig->terrainMaterials.resize(elemIndex+1,NULL);
				}
				if (tConfig->terrainMaterials[elemIndex] == NULL)
				{
					tConfig->terrainMaterials[elemIndex] = new TerrainMaterialConfiguration();
				}
				// add to map (if not already present)
				for( int i = 0; i < NUM_FORMS; i++)
				{
					if(formToggle[i])
					{
						map<int,c_sprite>::iterator it = tConfig->terrainMaterials[elemIndex]->overridingMaterials[i].find(subtypeId);
						if (it == tConfig->terrainMaterials[elemIndex]->overridingMaterials[i].end())
						{
							tConfig->terrainMaterials[elemIndex]->overridingMaterials[i][subtypeId]=sprite;
						}	
					}
				}
			} 			
		}
	}
}