/*
	BinMaker program
	Copyright 2007 Jonathan Wilson
	Portions lifted from BinOpener copyright 2007 booto (temptemp91 at hotmail dot com)

	This file is part of binmaker.

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	binmaker is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/
#include <stdio.h>
#include "tinyxml.h"
#include "manifestitem.h"
#include "gamemap.h"
GameMap::GameMap(TiXmlNode *node)
{
	const char *id = node->ToElement()->Attribute("id");
	char *stream = new char[strlen(id)+9];
	StreamSize = sizeof(GameMapHeader);
	offset = 0;
	currentimport = 0;
	EnvData environment;
	environment.cloud_imp.filehash1 = 0;
	environment.cloud_imp.filehash2 = 0;
	environment.envir_imp.filehash1 = 0;
	environment.envir_imp.filehash2 = 0;
	environment.noise_imp.filehash1 = 0;
	environment.noise_imp.filehash2 = 0;
	std::vector<GameMapWaypoint *> waypoints;
	std::vector<Thing *> structures;
	std::vector<Thing *> units;
	std::vector<Thing *> props;
	std::vector<Audio *> audio;
	std::vector<Audio *> unknown;
	std::vector<ExtraEntry *> roads;
	std::vector<ExtraEntry *> posteffects;
	std::vector< Property<unsigned int> *> bool_props;
	std::vector< Property<unsigned int> *> int_props;
	std::vector< Property<float> *> real_props;
	std::vector< Property<const char *> *> string_props;
	std::vector< Property<ExtraEntry> *> asset_props;
	sprintf(stream,"GameMap:%s",id);
	StreamName = stream;
	SourceName = _strdup("DATA:map.xml");
	_strlwr((char *)id);
	Header.filenamehash1 = 0xd51ae5e1;
	Header.filenamehash2 = hash_function(id,strlen(id));
	Header.filenamehash3 = 0x3ec9c79b;
	Header.filenamehash4 = Header.filenamehash2;
	for (TiXmlNode *child = node->FirstChild(); child; child = child->NextSibling())
	{
		if (child->Type() != TiXmlNode::ELEMENT)
		{
			continue;
		}
		if (child->ValueStr() == "Waypoint")
		{
			GameMapWaypoint *wp = new GameMapWaypoint;
			StreamSize += sizeof(GameMapWaypoint);
			waypoints.push_back(wp);
			wp->import = 0;
			wp->z1 = 0;
			wp->z2 = 0;
			const char *id2 = child->ToElement()->Attribute("id");
			_strlwr((char *)id2);
			wp->id_hash = hash_function(id2,strlen(id2));
			for (TiXmlNode *child2 = child->FirstChild(); child2; child2 = child2->NextSibling())
			{
				if (child2->Type() != TiXmlNode::ELEMENT)
				{
					continue;
				}
				if (child2->ValueStr() == "Position")
				{
					child2->ToElement()->Attribute("x",&(wp->x));
					child2->ToElement()->Attribute("y",&(wp->y));
					child2->ToElement()->Attribute("z",&(wp->z));
				}
			}
		}
		if (child->ValueStr() == "Structure")
		{
			Thing *th = ParseThing(child);
			structures.push_back(th);
		}
		if (child->ValueStr() == "Unit")
		{
			Thing *th = ParseThing(child);
			units.push_back(th);
		}
		if (child->ValueStr() == "Prop")
		{
			Thing *th = ParseThing(child);
			props.push_back(th);
		}
		if (child->ValueStr() == "Audio")
		{
			Audio *aud = new Audio;
			audio.push_back(aud);
			StreamSize += sizeof(GameMapAudio);
			const char *id2 = child->ToElement()->Attribute("id");
			_strlwr((char *)id2);
			aud->id_hash = hash_function(id2,strlen(id2));
			const char *obj = child->ToElement()->Attribute("ThingTemplate");
			_strlwr((char *)obj);
			aud->import.filehash1 = 0x942fff2d;
			aud->import.filehash2 = hash_function(obj,strlen(obj));
			for (TiXmlNode *child2 = child->FirstChild(); child2; child2 = child2->NextSibling())
			{
				if (child2->Type() != TiXmlNode::ELEMENT)
				{
					continue;
				}
				if (child2->ValueStr() == "Position")
				{
					child2->ToElement()->Attribute("x",&(aud->x));
					child2->ToElement()->Attribute("y",&(aud->y));
					child2->ToElement()->Attribute("z",&(aud->z));
				}
			}
		}
		if (child->ValueStr() == "Unknown")
		{
			Audio *aud = new Audio;
			unknown.push_back(aud);
			StreamSize += sizeof(GameMapAudio);
			const char *id2 = child->ToElement()->Attribute("id");
			_strlwr((char *)id2);
			aud->id_hash = hash_function(id2,strlen(id2));
			const char *obj = child->ToElement()->Attribute("ThingTemplate");
			_strlwr((char *)obj);
			aud->import.filehash1 = 0x942fff2d;
			aud->import.filehash2 = hash_function(obj,strlen(obj));
			for (TiXmlNode *child2 = child->FirstChild(); child2; child2 = child2->NextSibling())
			{
				if (child2->Type() != TiXmlNode::ELEMENT)
				{
					continue;
				}
				if (child2->ValueStr() == "Position")
				{
					child2->ToElement()->Attribute("x",&(aud->x));
					child2->ToElement()->Attribute("y",&(aud->y));
					child2->ToElement()->Attribute("z",&(aud->z));
				}
			}
		}
		if (child->ValueStr() == "Road")
		{
			StreamSize += 4;
			const char *id2 = child->ToElement()->Attribute("id");
			_strlwr((char *)id2);
			ExtraEntry *import = new ExtraEntry;
			import->filehash1 = 0xd19d90c6;
			import->filehash2 = hash_function(id2,strlen(id2));
			roads.push_back(import);
		}
		if (child->ValueStr() == "EnvironmentData")
		{
			StreamSize += sizeof(GameMapEnvData);
			const char *cloud = child->ToElement()->Attribute("Cloud");
			_strlwr((char *)cloud);
			environment.cloud_imp.filehash1 = 0x21e727da;
			environment.cloud_imp.filehash2 = hash_function(cloud,strlen(cloud));
			const char *envir = child->ToElement()->Attribute("Environment");
			_strlwr((char *)envir);
			environment.envir_imp.filehash1 = 0x21e727da;
			environment.envir_imp.filehash2 = hash_function(envir,strlen(envir));
			const char *noise = child->ToElement()->Attribute("Macro");
			_strlwr((char *)noise);
			environment.noise_imp.filehash1 = 0x21e727da;
			environment.noise_imp.filehash2 = hash_function(noise,strlen(noise));
		}
		if (child->ValueStr() == "WorldDict")
		{
			StreamSize += sizeof(GameMapWorldDict);
			for (TiXmlNode *child2 = child->FirstChild(); child2; child2 = child2->NextSibling())
			{
				if (child2->Type() != TiXmlNode::ELEMENT)
				{
					continue;
				}
				if (child2->ValueStr() == "RealProperty")
				{
					StreamSize += sizeof(GameMapProperty<float>);
					Property<float> *prop = new Property<float>;
					prop->name = child2->ToElement()->Attribute("Key");
					int len = strlen(prop->name);
					StreamSize += (len + (4 - (len % 4)));
					child2->ToElement()->Attribute("Value",&(prop->value));
					real_props.push_back(prop);
				}
				if (child2->ValueStr() == "IntProperty")
				{
					StreamSize += sizeof(GameMapProperty<unsigned int>);
					Property<unsigned int> *prop = new Property<unsigned int>;
					prop->name = child2->ToElement()->Attribute("Key");
					int len = strlen(prop->name);
					StreamSize += (len + (4 - (len % 4)));
					child2->ToElement()->Attribute("Value",&(prop->value));
					int_props.push_back(prop);
				}
				if (child2->ValueStr() == "StringProperty")
				{
					StreamSize += sizeof(GameMapProperty<list_lo>);
					Property<const char *> *prop = new Property<const char *>;
					prop->name = child2->ToElement()->Attribute("Key");
					int len = strlen(prop->name);
					StreamSize += (len + (4 - (len % 4)));
					prop->value = child2->ToElement()->Attribute("Value");
					len = strlen(prop->value);
					StreamSize += (len + (4 - (len % 4)));
					string_props.push_back(prop);
				}
				if (child2->ValueStr() == "AssetIdProperty")
				{
					StreamSize += sizeof(GameMapProperty<unsigned int>);
					Property<ExtraEntry> *prop = new Property<ExtraEntry>;
					prop->name = child2->ToElement()->Attribute("Key");
					int len = strlen(prop->name);
					StreamSize += (len + (4 - (len % 4)));
					const char *asset = child2->ToElement()->Attribute("Value");
					_strlwr((char *)asset);
					prop->value.filehash1 = 0x8f7dc19b;
					prop->value.filehash2 = hash_function(asset,strlen(asset));
					asset_props.push_back(prop);
				}
				if (child2->ValueStr() == "BoolProperty")
				{
					StreamSize += sizeof(GameMapProperty<unsigned int>);
					Property<unsigned int> *prop = new Property<unsigned int>;
					prop->name = child2->ToElement()->Attribute("Key");
					int len = strlen(prop->name);
					StreamSize += (len + (4 - (len % 4)));
					const char *b = child2->ToElement()->Attribute("Value");
					if (!_stricmp(b,"false"))
					{
						prop->value = false;
					}
					else
					{
						prop->value = true;
					}
					bool_props.push_back(prop);
				}
			}
		}
		if (child->ValueStr() == "PostEffect")
		{
			StreamSize += 4;
			ExtraEntry *e = new ExtraEntry;
			posteffects.push_back(e);
			const char *effect = child->ToElement()->Attribute("Effect");
			_strlwr((char *)effect);
			e->filehash1 = 0x21e727da;
			e->filehash2 = hash_function(effect,strlen(effect));
		}
	}
	StreamData = new char[StreamSize];
	memset(StreamData,0,StreamSize);
	GameMapHeader *gm = (GameMapHeader *)(StreamData+offset);
	offset += sizeof(GameMapHeader);
	gm->zeroes = 0;
	if (waypoints.size())
	{
		gm->waypoints.length = waypoints.size();
		gm->waypoints.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->waypoints.offset)) - StreamData);
		offset += (sizeof(GameMapWaypoint) * waypoints.size());
	}
	else
	{
		gm->waypoints.length = 0;
		gm->waypoints.offset = 0;
	}
	GameMapWaypoint *wp = (GameMapWaypoint *)(StreamData+gm->waypoints.offset);
	for (unsigned int i = 0;i < waypoints.size();i++)
	{
		wp[i].id_hash = waypoints[i]->id_hash;
		wp[i].import = 0;
		wp[i].x = waypoints[i]->x;
		wp[i].y = waypoints[i]->y;
		wp[i].z = waypoints[i]->z;
		wp[i].z1 = 0;
		wp[i].z2 = 0;
	}
	if (structures.size())
	{
		gm->structures.length = structures.size();
		gm->structures.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->structures.offset)) - StreamData);
		offset += (sizeof(GameMapThing) * structures.size());
	}
	else
	{
		gm->structures.length = 0;
		gm->structures.offset = 0;
	}
	GameMapThing *str = (GameMapThing *)(StreamData+gm->structures.offset);
	for (unsigned int i = 0;i < structures.size();i++)
	{
		StoreThing(&(str[i]),structures[i]);
	}
	if (units.size())
	{
		gm->units.length = units.size();
		gm->units.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->units.offset)) - StreamData);
		offset += (sizeof(GameMapThing) * units.size());
	}
	else
	{
		gm->units.length = 0;
		gm->units.offset = 0;
	}
	GameMapThing *unit = (GameMapThing *)(StreamData+gm->units.offset);
	for (unsigned int i = 0;i < units.size();i++)
	{
		StoreThing(&(unit[i]),units[i]);
	}
	if (props.size())
	{
		gm->props.length = props.size();
		gm->props.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->props.offset)) - StreamData);
		offset += (sizeof(GameMapThing) * props.size());
	}
	else
	{
		gm->props.length = 0;
		gm->props.offset = 0;
	}
	GameMapThing *prop = (GameMapThing *)(StreamData+gm->props.offset);
	for (unsigned int i = 0;i < props.size();i++)
	{
		StoreThing(&(prop[i]),props[i]);
	}
	if (audio.size())
	{
		gm->audio.length = audio.size();
		gm->audio.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->audio.offset)) - StreamData);
		offset += (sizeof(GameMapAudio) * audio.size());
	}
	else
	{
		gm->audio.length = 0;
		gm->audio.offset = 0;
	}
	GameMapAudio *aud = (GameMapAudio *)(StreamData+gm->audio.offset);
	for (unsigned int i = 0;i < audio.size();i++)
	{
		aud[i].id_hash = audio[i]->id_hash;
		aud[i].x = audio[i]->x;
		aud[i].y = audio[i]->y;
		aud[i].z = audio[i]->z;
		aud[i].z1 = 0;
		aud[i].z2 = 0;
		aud[i].import = currentimport;
		currentimport++;
		unsigned int imp = ((char *)(&(aud[i].import)) - StreamData);
		unsigned int hash1 = audio[i]->import.filehash1;
		unsigned int hash2 = audio[i]->import.filehash2;
		AddImport(hash1,hash2,imp);
	}
	if (unknown.size())
	{
		gm->unknown.length = unknown.size();
		gm->unknown.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->unknown.offset)) - StreamData);
		offset += (sizeof(GameMapAudio) * unknown.size());
	}
	else
	{
		gm->unknown.length = 0;
		gm->unknown.offset = 0;
	}
	GameMapAudio *unk = (GameMapAudio *)(StreamData+gm->unknown.offset);
	for (unsigned int i = 0;i < unknown.size();i++)
	{
		unk[i].id_hash = unknown[i]->id_hash;
		unk[i].x = unknown[i]->x;
		unk[i].y = unknown[i]->y;
		unk[i].z = unknown[i]->z;
		unk[i].z1 = 0;
		unk[i].z2 = 0;
		unk[i].import = currentimport;
		currentimport++;
		unsigned int imp = ((char *)(&(unk[i].import)) - StreamData);
		unsigned int hash1 = unknown[i]->import.filehash1;
		unsigned int hash2 = unknown[i]->import.filehash2;
		AddImport(hash1,hash2,imp);
	}
	if (roads.size())
	{
		gm->roads.length = roads.size();
		gm->roads.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->roads.offset)) - StreamData);
		offset += (4 * roads.size());
	}
	else
	{
		gm->roads.length = 0;
		gm->roads.offset = 0;
	}
	unsigned int *road = (unsigned int *)(StreamData+gm->roads.offset);
	for (unsigned int i = 0;i < roads.size();i++)
	{
		road[i] = currentimport;
		currentimport++;
		unsigned int imp = ((char *)(&road[i]) - StreamData);
		unsigned int hash1 = roads[i]->filehash1;
		unsigned int hash2 = roads[i]->filehash2;
		AddImport(hash1,hash2,imp);
	}
	gm->env.offset = offset;
	RelocationEntries.push_back((char *)(&(gm->env.offset)) - StreamData);
	offset += sizeof(GameMapEnvData);
	GameMapEnvData *env = (GameMapEnvData *)(StreamData+gm->env.offset);
	env->cloud_imp = currentimport;
	currentimport++;
	unsigned int imp = ((char *)(&(env->cloud_imp)) - StreamData);
	unsigned int hash1 = environment.cloud_imp.filehash1;
	unsigned int hash2 = environment.cloud_imp.filehash2;
	AddImport(hash1,hash2,imp);
	env->envir_imp = currentimport;
	currentimport++;
	imp = ((char *)(&(env->envir_imp)) - StreamData);
	hash1 = environment.envir_imp.filehash1;
	hash2 = environment.envir_imp.filehash2;
	AddImport(hash1,hash2,imp);
	env->noise_imp = currentimport;
	currentimport++;
	imp = ((char *)(&(env->noise_imp)) - StreamData);
	hash1 = environment.noise_imp.filehash1;
	hash2 = environment.noise_imp.filehash2;
	AddImport(hash1,hash2,imp);
	gm->dict.offset = offset;
	RelocationEntries.push_back((char *)(&(gm->dict.offset)) - StreamData);
	offset += sizeof(GameMapWorldDict);
	GameMapWorldDict *dict = (GameMapWorldDict *)(StreamData+gm->dict.offset);
	if (bool_props.size())
	{
		dict->bool_prop.length = bool_props.size();
		dict->bool_prop.offset = offset;
		RelocationEntries.push_back((char *)(&(dict->bool_prop.offset)) - StreamData);
		offset += (sizeof(GameMapProperty<unsigned int>) * bool_props.size());
	}
	else
	{
		dict->bool_prop.length = 0;
		dict->bool_prop.offset = 0;
	}
	GameMapProperty<unsigned int> *bool_prop = (GameMapProperty<unsigned int> *)(StreamData+dict->bool_prop.offset);
	for (unsigned int i = 0;i < bool_props.size();i++)
	{
		bool_prop[i].value = bool_props[i]->value;
		bool_prop[i].name.length = strlen(bool_props[i]->name);
		bool_prop[i].name.offset = offset;
		RelocationEntries.push_back((char *)(&(bool_prop[i].name.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),bool_props[i]->name);
		int len = strlen(bool_props[i]->name);
		offset += (len + (4 - (len % 4)));
	}
	if (int_props.size())
	{
		dict->int_prop.length = int_props.size();
		dict->int_prop.offset = offset;
		RelocationEntries.push_back((char *)(&(dict->int_prop.offset)) - StreamData);
		offset += (sizeof(GameMapProperty<unsigned int>) * int_props.size());
	}
	else
	{
		dict->int_prop.length = 0;
		dict->int_prop.offset = 0;
	}
	GameMapProperty<unsigned int> *int_prop = (GameMapProperty<unsigned int> *)(StreamData+dict->int_prop.offset);
	for (unsigned int i = 0;i < int_props.size();i++)
	{
		int_prop[i].value = int_props[i]->value;
		int_prop[i].name.length = strlen(int_props[i]->name);
		int_prop[i].name.offset = offset;
		RelocationEntries.push_back((char *)(&(int_prop[i].name.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),int_props[i]->name);
		int len = strlen(int_props[i]->name);
		offset += (len + (4 - (len % 4)));
	}
	if (real_props.size())
	{
		dict->real_prop.length = real_props.size();
		dict->real_prop.offset = offset;
		RelocationEntries.push_back((char *)(&(dict->real_prop.offset)) - StreamData);
		offset += (sizeof(GameMapProperty<float>) * real_props.size());
	}
	else
	{
		dict->real_prop.length = 0;
		dict->real_prop.offset = 0;
	}
	GameMapProperty<float> *real_prop = (GameMapProperty<float> *)(StreamData+dict->real_prop.offset);
	for (unsigned int i = 0;i < real_props.size();i++)
	{
		real_prop[i].value = real_props[i]->value;
		real_prop[i].name.length = strlen(real_props[i]->name);
		real_prop[i].name.offset = offset;
		RelocationEntries.push_back((char *)(&(real_prop[i].name.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),real_props[i]->name);
		int len = strlen(real_props[i]->name);
		offset += (len + (4 - (len % 4)));
	}
	if (string_props.size())
	{
		dict->string_prop.length = string_props.size();
		dict->string_prop.offset = offset;
		RelocationEntries.push_back((char *)(&(dict->string_prop.offset)) - StreamData);
		offset += (sizeof(GameMapProperty<list_lo>) * string_props.size());
	}
	else
	{
		dict->string_prop.length = 0;
		dict->string_prop.offset = 0;
	}
	GameMapProperty<list_lo> *string_prop = (GameMapProperty<list_lo> *)(StreamData+dict->string_prop.offset);
	for (unsigned int i = 0;i < string_props.size();i++)
	{
		string_prop[i].name.length = strlen(string_props[i]->name);
		string_prop[i].name.offset = offset;
		RelocationEntries.push_back((char *)(&(string_prop[i].name.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),string_props[i]->name);
		int len = strlen(string_props[i]->name);
		offset += (len + (4 - (len % 4)));
		string_prop[i].value.length = strlen(string_props[i]->value);
		string_prop[i].value.offset = offset;
		RelocationEntries.push_back((char *)(&(string_prop[i].value.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),string_props[i]->value);
		len = strlen(string_props[i]->value);
		offset += (len + (4 - (len % 4)));
	}
	if (asset_props.size())
	{
		dict->asset_prop.length = asset_props.size();
		dict->asset_prop.offset = offset;
		RelocationEntries.push_back((char *)(&(dict->asset_prop.offset)) - StreamData);
		offset += (sizeof(GameMapProperty<unsigned int>) * asset_props.size());
	}
	else
	{
		dict->asset_prop.length = 0;
		dict->asset_prop.offset = 0;
	}
	GameMapProperty<unsigned int> *asset_prop = (GameMapProperty<unsigned int> *)(StreamData+dict->asset_prop.offset);
	for (unsigned int i = 0;i < asset_props.size();i++)
	{
		asset_prop[i].name.length = strlen(asset_props[i]->name);
		asset_prop[i].name.offset = offset;
		RelocationEntries.push_back((char *)(&(asset_prop[i].name.offset)) - StreamData);
		strcpy((char *)(StreamData+offset),asset_props[i]->name);
		int len = strlen(asset_props[i]->name);
		offset += (len + (4 - (len % 4)));
		asset_prop[i].value = currentimport;
		currentimport++;
		unsigned int imp = ((char *)(&(asset_prop[i].value)) - StreamData);
		unsigned int hash1 = asset_props[i]->value.filehash1;
		unsigned int hash2 = asset_props[i]->value.filehash2;
		AddImport(hash1,hash2,imp);
	}
	dict->unicodestring_prop.length = 0;
	dict->unicodestring_prop.offset = 0;
	dict->assetlist_prop.length = 0;
	dict->assetlist_prop.offset = 0;
	if (posteffects.size())
	{
		gm->posteffects.length = posteffects.size();
		gm->posteffects.offset = offset;
		RelocationEntries.push_back((char *)(&(gm->posteffects.offset)) - StreamData);
		offset += (4 * posteffects.size());
	}
	else
	{
		gm->posteffects.length = 0;
		gm->posteffects.offset = 0;
	}
	unsigned int *posteffect = (unsigned int *)(StreamData+gm->posteffects.offset);
	for (unsigned int i = 0;i < posteffects.size();i++)
	{
		posteffect[i] = currentimport;
		currentimport++;
		unsigned int imp = ((char *)(&posteffect[i]) - StreamData);
		unsigned int hash1 = posteffects[i]->filehash1;
		unsigned int hash2 = posteffects[i]->filehash2;
		AddImport(hash1,hash2,imp);
	}
}

Thing *GameMap::ParseThing(TiXmlNode *child)
{
	Thing *th = new Thing;
	StreamSize += sizeof(GameMapThing);
	StreamSize += 4;
	child->ToElement()->Attribute("Angle",&(th->angle));
	th->faction = child->ToElement()->Attribute("Faction");
	int len = strlen(th->faction);
	StreamSize += (len + (4 - (len % 4)));
	th->team = child->ToElement()->Attribute("Team");
	len = strlen(th->team);
	StreamSize += (len + (4 - (len % 4)));
	child->ToElement()->Attribute("Health",&(th->health));
	const char *id2 = child->ToElement()->Attribute("id");
	_strlwr((char *)id2);
	th->id_hash = hash_function(id2,strlen(id2));
	const char *obj = child->ToElement()->Attribute("ThingTemplate");
	_strlwr((char *)obj);
	th->import.filehash1 = 0x942fff2d;
	th->import.filehash2 = hash_function(obj,strlen(obj));
	for (TiXmlNode *child2 = child->FirstChild(); child2; child2 = child2->NextSibling())
	{
		if (child2->Type() != TiXmlNode::ELEMENT)
		{
			continue;
		}
		if (child2->ValueStr() == "Position")
		{
			child2->ToElement()->Attribute("x",&(th->x));
			child2->ToElement()->Attribute("y",&(th->y));
			child2->ToElement()->Attribute("z",&(th->z));
		}
	}
	return th;
}

void GameMap::StoreThing(GameMapThing *th,Thing *th2)
{
	th->angle = th2->angle;
	th->faction.length = strlen(th2->faction);
	th->faction.offset = offset;
	RelocationEntries.push_back((char *)(&(th->faction.offset)) - StreamData);
	strcpy((char *)(StreamData+offset),th2->faction);
	int len = strlen(th2->faction);
	offset += (len + (4 - (len % 4)));
	th->health = th2->health;
	th->id_hash = th2->id_hash;
	th->import = currentimport;
	currentimport++;
	unsigned int imp = ((char *)(&(th->import)) - StreamData);
	unsigned int hash1 = th2->import.filehash1;
	unsigned int hash2 = th2->import.filehash2;
	AddImport(hash1,hash2,imp);
	th->team.length = strlen(th2->team);
	th->team.offset = offset;
	RelocationEntries.push_back((char *)(&(th->team.offset)) - StreamData);
	strcpy((char *)(StreamData+offset),th2->team);
	len = strlen(th2->team);
	offset += (len + (4 - (len % 4)));
	th->event_list.length = 0;
	th->event_list.offset = offset;
	RelocationEntries.push_back((char *)(&(th->event_list.offset)) - StreamData);
	*((unsigned int *)(StreamData+offset)) = 0;
	offset += 4;
	th->x = th2->x;
	th->y = th2->y;
	th->z = th2->z;
	th->zero = 0;
}
