#include "munga.h"
#pragma hdrstop

#include "cultural.h"
#include "terrain.h"
#include "fileutil.h"
#include "boxtree.h"
#include "boxsolid.h"
#include "scnrole.h"
#include "mission.h"
#include "explode.h"
#include "app.h"
#include "interest.h"
#include "hostmgr.h"
#include "nttmgr.h"
#include "namelist.h"
#include "console.h"

//##########################################################################
//#####################    Class CulturalIcon     ##########################
//##########################################################################

//#############################################################################
// Shared Data Support
//
Derivation* CulturalIcon::GetClassDerivations()
{	static Derivation classDerivations(UnscalableTerrain::GetClassDerivations(), "CulturalIcon");
	return &classDerivations;
}


CulturalIcon::SharedData
	CulturalIcon::DefaultData(
		CulturalIcon::GetClassDerivations(),
		CulturalIcon::GetMessageHandlers(),
		CulturalIcon::GetAttributeIndex(),
		CulturalIcon::StateCount,
		(UnscalableTerrain::MakeHandler)CulturalIcon::Make
	);
//#############################################################################
// Message Support
//
const Receiver::HandlerEntry
	CulturalIcon::MessageHandlerEntries[]=
{
	MESSAGE_ENTRY(CulturalIcon, TakeDamage),
	MESSAGE_ENTRY(CulturalIcon, SetBurningState)
};

CulturalIcon::MessageHandlerSet& CulturalIcon::GetMessageHandlers()
{
	static CulturalIcon::MessageHandlerSet messageHandlers(ELEMENTS(CulturalIcon::MessageHandlerEntries), CulturalIcon::MessageHandlerEntries, UnscalableTerrain::GetMessageHandlers());
	return messageHandlers;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//


void
	CulturalIcon::SetBurningStateMessageHandler(Message * /*burning_message*/)
{

	SetSimulationState(CulturalIcon::BurningState);
	ForceUpdate(DefaultUpdateModelFlag);
	AlwaysExecute();

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CulturalIcon::TakeDamageMessageHandler(TakeDamageMessage *damage_message)
{
	Check(damage_message);


	if (damage_message->damageZone == -1 )
	{
		damage_message->damageZone = 0;
	}

	if (GetSimulationState() == CulturalIcon::DefaultState)
	{
		//
		//~~~~~~~~~~~~~~~~~~
		// Update Replicants
		//~~~~~~~~~~~~~~~~~~
		//
		if (GetInstance() != ReplicantInstance)
		{
			ForceUpdate(DamageZoneUpdateModelFlag | DefaultUpdateModelFlag);
			AlwaysExecute();
		}
		//
		//~~~~~~~~~~~~~~~~~~~~~
		// Call Derived Classes
		//~~~~~~~~~~~~~~~~~~~~~
		//
		UnscalableTerrain::TakeDamageMessageHandler(damage_message);

		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Update Collision Volumes if we died
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//

		for(int ii=0;ii<damageZoneCount;++ii)
		{
			if(damageZones[ii]->GetDamageZoneState() == DamageZone::BurningState)
			{
				//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
				// Create the explosion
				//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
				//
				Origin	explode_origin = localOrigin;

			ResourceDescription::ResourceID explosion_ID;

			if ((damage_message->damageData.damageType == Damage::CollisionDamageType )&&
				(crunchExplosionResourceID != -1))
			{
				explosion_ID = crunchExplosionResourceID;
			}
			else
			{
				explosion_ID = explosionResourceID;
			}

			Explosion::MakeMessage exp_message(
					Explosion::MakeMessageID,
					sizeof(Explosion::MakeMessage),
					RegisteredClass::ExplosionClassID,
					EntityID::Null,
					explosion_ID,
					Explosion::DefaultFlags,
					explode_origin,
					GetEntityID(),
					GetEntityID()
				);

			#if (DEBUG_LEVEL > 0)
				Explosion *new_exp =
			#endif
				Explosion::Make(&exp_message);
				Register_Object(new_exp);

				Message dummy_message(SetBurningStateMessageID, sizeof(Message));
				Check(application);
				Time now = Now();
				now += timeDelay;
				application->Post(CreationEventPriority, this, &dummy_message, now);

				SetSimulationState(WaitingToBurn);

				UpdateCollisionVolumes();
				break;
			}
		}
	}
	Check_Fpu();
}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	CulturalIcon::UpdateCollisionVolumes()
{
	Check(this);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Get the Tree for these Collision Volumes
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	InterestManager *interest_mgr =
		application->GetInterestManager();
	Check(interest_mgr);
	InterestZone *zone =
		interest_mgr->GetInterestZone(interestZoneID);
	Check(zone);
	BoxedSolidTree* tree = zone->GetCollisionRoot();
	Check(tree);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Update Volumes based on RemoveVolume Flag
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	BoxedSolid *box = collisionVolumes;
	while (box)
	{
		BoxedSolid *next_box = box->GetNextSolid();
		if (RemoveCollisionVolumeOnDeath())
		{
			//
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			// Delete the Collision Volume
			//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
			//
			tree->Remove(box);
			Unregister_Object(box);
			delete box;
		}
		else
		{
			//
			//~~~~~~~~~~~~~~~~~~~~~~
			// Move Collision Volume
			//~~~~~~~~~~~~~~~~~~~~~~
			//
			box->minY += destroyedYTranslation;
			box->maxY += destroyedYTranslation;
		}
		box = next_box;
	}
	collisionVolumes = NULL;
	Check_Fpu();
}

//#############################################################################
// Attribute Support
//
const CulturalIcon::IndexEntry
	CulturalIcon::AttributePointers[]=
{
	ATTRIBUTE_ENTRY(CulturalIcon, TeamName, teamName)
};

CulturalIcon::AttributeIndexSet& CulturalIcon::GetAttributeIndex()
{
	static CulturalIcon::AttributeIndexSet attributeIndex(ELEMENTS(CulturalIcon::AttributePointers),
		CulturalIcon::AttributePointers,
		UnscalableTerrain::GetAttributeIndex()
	);
	return attributeIndex;
}
//#############################################################################
// Construction and Destruction
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CulturalIcon::CulturalIcon(
	MakeMessage *creation_message,
	SharedData	&shared_data
) :
	UnscalableTerrain(creation_message, shared_data)
{

	Str_Copy(teamName, "Defualt", sizeof(teamName));
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Read in the ModelResource Information
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	ResourceDescription *res =
		application->GetResourceFile()->SearchList(
			resourceID,
			ResourceDescription::GameModelResourceType
		);
	Check(res);
	res->Lock();
	ModelResource* model_resource = (ModelResource*)res->resourceAddress;
	Check_Pointer(model_resource);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  Determine if we move or Destroy the
	// Collision volume in Death of the map entity
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	if (model_resource->sinkCollisionVolume)
	{
		destroyedYTranslation = model_resource->destroyedYTranslation;
	}
	else
	{
		destroyedYTranslation = 0.0f;
		SetRemoveCollisionVolumeFlag();
	}

	timeDelay = model_resource->timeDelay;

	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Is Stopping Collision Volume ?
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	if (model_resource->stoppingCollisionVolume)
	{
		SetStoppingCollisionVolumeFlag();
	}

	explosionResourceID = model_resource->explosionResourceID;
	crunchExplosionResourceID = model_resource->crunchExplosionResourceID;
	res->Unlock();

	//DEBUG_STREAM <<  model_resource->crunchExplosionResourceID << std::endl << std::flush;

	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Read in DamageZone Information from the Resource
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	ResourceDescription *dmg_res =
		application->GetResourceFile()->SearchList(
			resourceID,
			ResourceDescription::DamageZoneStreamResourceType
		);
	Check(dmg_res);
	dmg_res->Lock();
	DynamicMemoryStream damage_stream (
		dmg_res->resourceAddress,
		dmg_res->resourceSize
	);
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~
	// skip over DamageZoneCount
	//~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	damage_stream.AdvancePointer(sizeof(damageZoneCount));
	//
	//~~~~~~~~~~~~~~~~~~~~~~~
	// Create the DamageZones
	//~~~~~~~~~~~~~~~~~~~~~~~
	//
	for(int ii=0;ii<damageZoneCount;++ii)
	{
		damageZones[ii] = new DamageZone(
			this,
			ii,
			&damage_stream
		);
		Register_Object(damageZones[ii]);
	}
	SetValidFlag();
	dmg_res->Unlock();
	Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//



void
	CulturalIcon::ReadUpdateRecord(Simulation::UpdateRecord *message)
{
	Check(this);
	Check_Pointer(message);

	UnscalableTerrain::ReadUpdateRecord(message);

	if (simulationState.GetOldState() != GetSimulationState() && (GetSimulationState() == BurningState))
	{
		UpdateCollisionVolumes();
	}
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

Logical
	CulturalIcon::CreateMakeMessage(
		MakeMessage 					*creation_message,
		NotationFile 					*model_file,
		const ResourceDirectories	*directories
)
{
	Check(creation_message);
	Check(model_file);

	if (!UnscalableTerrain::CreateMakeMessage(creation_message, model_file, directories))
	{
		return False;
	}

	creation_message->messageLength = sizeof(MakeMessage);
	creation_message->classToCreate = CulturalIconClassID;
	creation_message->instanceFlags = MasterInstance|DynamicFlag|MapFlag|TrappedFlag;
	return True;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CulturalIcon*
	CulturalIcon::Make(MakeMessage *creation_message)
{
	Check_Fpu();
	return new CulturalIcon(creation_message);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
CulturalIcon::~CulturalIcon()
{

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	CulturalIcon::CreateModelResource(
	#if DEBUG_LEVEL>0
		ResourceFile *resource_file,
		const char *model_name,
		NotationFile *model_file,
		const ResourceDirectories *directories,
		ModelResource* model
	#else
		ResourceFile *resource_file,
		const char *model_name,
		NotationFile *model_file,
		const ResourceDirectories *,
		ModelResource* model
	#endif
)
{
	Check(resource_file);
	Check_Pointer(model_name);
	Check(model_file);
	Check_Pointer(directories);

	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Allocate memory for the resource
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	ModelResource *local_model = model;
	if (!local_model)
	{
		local_model = new ModelResource;
		Register_Pointer(local_model);
	}
	if (
		!model_file->GetEntry(
			"gamedata",
			"DestroyedYTranslation",
			&local_model->destroyedYTranslation
		)
	)
	{
		local_model->sinkCollisionVolume = False;
		local_model->destroyedYTranslation = 0.0f;
	}
	else
	{
		local_model->sinkCollisionVolume = True;
	}

	if (!model_file->GetLogicalEntry(
			"gamedata",
			"StoppingCollisionVolume",
			&local_model->stoppingCollisionVolume
		)
	)
	{
		local_model->stoppingCollisionVolume = False;
	}

	if (
		!model_file->GetEntry(
			"gamedata",
			"TimeDelay",
			&local_model->timeDelay
		)
	)
	{
		DEBUG_STREAM << model_name << " TimeDelay is missing " << std::endl << std::flush;
		PostQuitMessage(AbortExitCodeID);
	}


	//
	//----------------------------------------------------------------------
	//	Read in the Model Filename of the Explosion renderable, then find its
	// resource ID in the resource file
	//----------------------------------------------------------------------
	//
	const char *explosion = "Unspecified";
	if (
		!model_file->GetEntry(
			"gamedata",
			"ExplosionModelFile",
			&explosion
		)
	)
	{
		std::cout << model_name <<  " missing ExplosionModelFile!\n";
		Check_Fpu();
		return False;
	}


	ResourceDescription *res = NULL;

	if (strcmp(explosion,"Unspecified"))
	{
		res = resource_file->FindResourceDescription(
			explosion,
			ResourceDescription::ModelListResourceType
		);
	}
	if (!res)
	{
		std::cout << model_name <<  " cannot find " << explosion
		 << " in resource file!\n";
		Check_Fpu();
		return False;
	}
	if (res)
	{
		local_model->explosionResourceID = res->resourceID;
	}



	const char *crunch_explosion = "Unspecified";

	model_file->GetEntry(
			"gamedata",
			"CrunchExplosionModelFile",
			&crunch_explosion
		);


	local_model->crunchExplosionResourceID = -1;

	if (strcmp(crunch_explosion,"Unspecified"))
	{
		//res = NULL;
		res = resource_file->FindResourceDescription(
			crunch_explosion,
			ResourceDescription::ModelListResourceType
		);

		if (!res)
		{
			std::cout << model_name <<  " cannot find " << crunch_explosion
			 << " in resource file!\n";
			Check_Fpu();
			return False;
		}
		else
		{
			local_model->crunchExplosionResourceID = res->resourceID;
		}


	}

	//DEBUG_STREAM << ":" << local_model->crunchExplosionResourceID << std::endl << std::flush;


	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Write the model to the resource
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	if (!model)
	{
		ResourceDescription *new_res =
			resource_file->AddResource(
				model_name,
				ResourceDescription::GameModelResourceType,
				1,
				ResourceDescription::Preload,
				local_model,
				sizeof(*local_model)
			);
		Unregister_Pointer(local_model);
		delete local_model;
		Check(new_res);
		Check_Fpu();
		return new_res->resourceID;
	}
	else
	{
		Check_Fpu();
		return 0;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	CulturalIcon::CreateDamageZoneStream(
		ResourceFile *resource_file,
		const char *model_name,
		NotationFile *model_file,
		const ResourceDirectories *directories
	)
{
	Check(resource_file);
	Check_Pointer(model_name);
	Check(model_file);
	Check_Pointer(directories);

	//
	//-------------------
	// Find the .dmg file
	//-------------------
	//
	const char* dmg_file_cname;
	if (
		!model_file->GetEntry(
			"gamedata",
			"DamageZones",
			&dmg_file_cname
		)
	)
	{
		std::cerr << model_name << " is missing .dmg file specification!\n";
		return -1;
	}

	CString dmg_filename =
		MakePathedFilename(directories->modelDirectory, dmg_file_cname);

	NotationFile *dmg_file = new NotationFile(dmg_filename);
	Register_Object(dmg_file);
	int page_count = dmg_file->PageCount();
	if (!page_count)
	{
		std::cerr << dmg_filename << " is empty or missing!\n";
		Unregister_Object(dmg_file);
		delete dmg_file;
		return -1;
	}

	DynamicMemoryStream damage_stream;

	damage_stream << page_count;
	NameList *dmg_namelist = dmg_file->MakePageList();
	Register_Object(dmg_namelist);

	NameList::Entry *dmg_entry = dmg_namelist->GetFirstEntry();

	CString	dmg_page_name;
	while(dmg_entry)
	{
		dmg_page_name = dmg_entry->GetName();
		DamageZone::CreateStreamedDamageZone(
			model_file,
			model_name,
			NULL,
			dmg_page_name,
			&damage_stream,
			dmg_file,
			directories
		);
		dmg_entry = dmg_entry->GetNextEntry();
	}

	//
	//~~~~~~~~~~~~~~~~~~~~~~~
	// Add Stream to Resource
	//~~~~~~~~~~~~~~~~~~~~~~~
	//
	ResourceDescription *new_res =
		resource_file->AddResourceMemoryStream(
			model_name,
			ResourceDescription::DamageZoneStreamResourceType,
			1,
			ResourceDescription::Preload,
			&damage_stream
		);
	Check(new_res);

	Unregister_Object(dmg_file);
	delete dmg_file;
	Unregister_Object(dmg_namelist);
	delete dmg_namelist;

	return  new_res->resourceID;
}

//##########################################################################
//####################    Class Landmark   ##########################
//##########################################################################

//#############################################################################
// Shared Data Support
//
Derivation* Landmark::GetClassDerivations()
{	static Derivation classDerivations(CulturalIcon::GetClassDerivations(), "Landmark");
	return &classDerivations;
}


Landmark::SharedData
	Landmark::DefaultData(
		Landmark::GetClassDerivations(),
		Landmark::MessageHandlers,
		Landmark::GetAttributeIndex(),
		Landmark::StateCount,
		(Landmark::MakeHandler)Landmark::Make
	);
//#############################################################################
// Message Support
//
const Receiver::HandlerEntry
	Landmark::MessageHandlerEntries[]=
{
	MESSAGE_ENTRY(Landmark, TakeDamage)
};

Landmark::MessageHandlerSet
	Landmark::MessageHandlers(
		ELEMENTS(Landmark::MessageHandlerEntries),
		Landmark::MessageHandlerEntries,
		CulturalIcon::GetMessageHandlers()
	);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	Landmark::TakeDamageMessageHandler(TakeDamageMessage *damage_message)
{
	Check(damage_message);

	if (owningTeam == NULL)
	{
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Initialize the owning team pointer
		// with the Teams entity Group
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		Check(application);
		EntityManager *entity_manager = application->GetEntityManager();
		Check(entity_manager);
		EntityGroup *team_group = entity_manager->UseGroup("Teams");
		if (team_group)
		{
			ChainIteratorOf<Node*> team_iterator(team_group->groupMembers);
			Team *current_team;
			while((current_team = (Team*) team_iterator.ReadAndNext() ) != NULL)
			{
				if (!strcmp(current_team->teamName, teamName))
				{
					owningTeam = current_team;
					break;
				}
			}
		}
	}



	if (owningTeam == NULL)
	{
		DEBUG_STREAM << "TEAM : '" <<  teamName << "' was never found! " << std::endl << std::flush;
		exit (-1);
	}


	if (GetSimulationState() != BurningState)
	{
		CulturalIcon::TakeDamageMessageHandler(damage_message);

		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Calculate the Score Loss based
		// on the Scenario Data
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		Check(scenarioRole);
		#if 0
		Logical landmark_destroyed = GetSimulationState() == BurningState;
		Scalar score_loss = scenarioRole->CalcDamageReceivedScore(
			damage_message->damageData.damageAmount
		);

		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Tell the Console about the Damage
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		Check(application);
		HostManager *host_manager = application->GetHostManager();
		Check(host_manager);
		Host *console_host = host_manager->GetConsoleHost();

		if (console_host)
		{
			Check(console_host);
			ConsoleLandmarkDamagedMessage landmark_damaged_message(
				damage_message->inflictingEntity.GetHostID(),
				landmarkID,
				damage_message->damageData.damageAmount,
				landmark_destroyed,
				score_loss
				);

			application->SendMessage(
				console_host->GetHostID(),
				NetworkClient::ConsoleClientID,
				&landmark_damaged_message
			);
		}
		#endif
	}
}

Logical
	CulturalIcon::TestInstance() const
{
	return IsDerivedFrom(*GetClassDerivations());
}

//#############################################################################
// Construction and Destruction
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Landmark::Landmark(
	MakeMessage	*creation_message,
	SharedData &shared_data
) :
	CulturalIcon ( creation_message, shared_data)
{
	scenarioRole = NULL;
	owningTeam = NULL;
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Initialize the owning team pointer
	// with the Teams entity Group
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	Check(application);
	EntityManager *entity_manager = application->GetEntityManager();
	Check(entity_manager);
	EntityGroup *team_group = entity_manager->UseGroup("Teams");
	if (team_group)
	{
		ChainIteratorOf<Node*> team_iterator(team_group->groupMembers);
		Team *current_team;
		while((current_team = (Team*) team_iterator.ReadAndNext() ) != NULL)
		{
			if (!strcmp(current_team->teamName, creation_message->teamName))
			{
				owningTeam = current_team;
				break;
			}
		}
	}

	//
	// If the team is null, that's ok.  It will either show up over the network
   // or be a free for all
	//


	Str_Copy(teamName, creation_message->teamName, sizeof(teamName));


	Check(application->GetCurrentMission());
	scenarioRole =
		application->GetCurrentMission()->GetScenarioRole(creation_message->roleName);
	if (!scenarioRole)
	{

		scenarioRole = new ScenarioRole("Role::MapAssigned",creation_message->roleName);
		Register_Object(scenarioRole);
		application->GetCurrentMission()->AddScenarioRole(scenarioRole);
	}
	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Add this landmark to the Landmark Entity Group
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	EntityGroup *landmark_group = entity_manager->UseGroup("Landmarks");
	Check(landmark_group);
	landmark_group->Add(this);

	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Landmark::~Landmark()
{

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	Landmark::CreateMakeMessage(
		MakeMessage 					*creation_message,
		NotationFile 					*model_file,
		const ResourceDirectories	*directories
)
{
	Check(creation_message);
	Check(model_file);

	if (!CulturalIcon::CreateMakeMessage(creation_message, model_file, directories))
	{
		return False;
	}

	creation_message->messageLength = sizeof(MakeMessage);
	creation_message->classToCreate = LandmarkClassID;

	char *p;

	//
	//----------------------------
	//  landmarkID allocated
	//  by map stream creation
	//----------------------------
	//

	//
	//~~~~~~~~~~~~~~~
	// Get the teamName
	//~~~~~~~~~~~~~~~
	//
	if ((p = strtok(NULL, ",")) == NULL)
	{
		std::cerr << "teamName missing!\n";
		return False;
	}
	Str_Copy(creation_message->teamName,p, sizeof(creation_message->teamName));


	//
	//~~~~~~~~~~~~~~~~~
	// Get the roleName
	//~~~~~~~~~~~~~~~~~
	//
	if ((p = strtok(NULL, ",")) == NULL)
	{
		std::cerr << "roleName missing!\n";
		return False;
	}
	Str_Copy(creation_message->roleName,p, sizeof(creation_message->roleName));


	//
	//~~~~~~~~~~~~~~~~~~~~~~
	// Get the Landmark Name
	//~~~~~~~~~~~~~~~~~~~~~~
	//
	if ((p = strtok(NULL, ",")) == NULL)
	{
		std::cerr << "Landmark Name missing!\n";
		return False;
	}
	Str_Copy(creation_message->landmarkName,p, sizeof(creation_message->landmarkName));


	return True;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Landmark*
	Landmark::Make(MakeMessage *creation_message)
{
	Check_Fpu();
	return new Landmark(creation_message);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
int
	Landmark::CreateModelResource(
		ResourceFile *resource_file,
		const char *model_name,
		NotationFile *model_file,
		const ResourceDirectories *directories,
		ModelResource* model
)
{
	Check(resource_file);
	Check_Pointer(model_name);
	Check(model_file);
	Check_Pointer(directories);


	CulturalIcon::CreateModelResource(resource_file, model_name, model_file, directories, model);

	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Allocate memory for the resource
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	ModelResource *local_model = model;
	if (!local_model)
	{
		local_model = new ModelResource;
		Register_Pointer(local_model);
	}

#if 0
	const char *role_model_file;
	if (!model_file->GetEntry(
			"gamedata",
			"RoleModelFile",
			&role_model_file
		)
	)
	{
		std::cerr<<model_name<<" missing RoleModelFile ! \n"<<std::endl;
Dump_And_Die:
		if (local_model)
		{
			Unregister_Pointer(local_model);
			delete local_model;
		}
		return -1;
	}
	else
	{
		//
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Hunt for Model file in ResourceFile
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//
		ResourceDescription *res;

		res = resource_file->FindResourceDescription(
			role_model_file,
			ResourceDescription::ModelListResourceType
		);
		if (!res)
		{
			std::cout << model_name <<  " cannot find " << role_model_file
			 << " in resource file!\n";
			goto Dump_And_Die;
		}
		local_model->roleResourceID = res->resourceID;
	}
#endif


	//
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Write the model to the resource
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	if (!model)
	{
		ResourceDescription *new_res =
			resource_file->AddResource(
				model_name,
				ResourceDescription::GameModelResourceType,
				1,
				ResourceDescription::Preload,
				local_model,
				sizeof(*local_model)
			);
		Unregister_Pointer(local_model);
		delete local_model;
		Check(new_res);
		Check_Fpu();
		return new_res->resourceID;
	}
	else
	{
		Check_Fpu();
		return 0;
	}
}

Logical
	Landmark::TestInstance() const
{
	return IsDerivedFrom(*GetClassDerivations());
}
