#include "munga.h"
#pragma hdrstop

#include "renderer.h"
#include "rndorgn.h"
#include "explode.h"
#include "app.h"
#include "objstrm.h"
#include "hostmgr.h"
#include "subsystm.h"

//#############################################################################
//############################    Renderer    #################################
//#############################################################################

const RendererRate DefaultRendererRate = 30.0f;
const RendererComplexity MaxRendererComplexity = 3.0f;
const RendererComplexity MinRendererComplexity = 0.0f;
const RendererFrameBudget DefaultRendererFrameBudget = 0.14f; //0.12f; // 0.16f;

//#############################################################################
// Message Support
//
const Receiver::HandlerEntry
	Renderer::MessageHandlerEntries[]=
{
	{
		Renderer::NotifyOfNewInterestingEntityMessageID,
		"NotifyOfNewInterestingEntity",
		(Renderer::Handler)&Renderer::NotifyOfNewInterestingEntityMessageHandler
	},
	{
		Renderer::NotifyOfBecomingUninterestingEntityMessageID,
		"NotifyOfBecomingUninterestingEntity",
		(Renderer::Handler)&Renderer::NotifyOfBecomingUninterestingEntityMessageHandler
	},
	{
		Renderer::StartEntityEffectMessageID,
		"StartEntityEffect",
		(Renderer::Handler)&Renderer::StartEntityEffectMessageHandler
	},
	{
		Renderer::StopAllEntityEffectsMessageID,
		"StopAllEntityEffects",
		(Renderer::Handler)&Renderer::StopAllEntityEffectsMessageHandler
	},
	{
		Renderer::StartEntityAlarmMessageID,
		"StartEntityAlarm",
		(Renderer::Handler)&Renderer::StartEntityAlarmMessageHandler
	},
	{
		Renderer::StopEntityAlarmMessageID,
		"StopEntityAlarm",
		(Renderer::Handler)&Renderer::StopEntityAlarmMessageHandler
	}
};

Renderer::MessageHandlerSet& Renderer::GetMessageHandlers()
{
	static Renderer::MessageHandlerSet messageHandlers(ELEMENTS(Renderer::MessageHandlerEntries), Renderer::MessageHandlerEntries, Receiver::GetMessageHandlers());
	return messageHandlers;
}

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

Renderer::SharedData
	Renderer::DefaultData(
		Renderer::GetClassDerivations(),
		Renderer::GetMessageHandlers()
	);

//
//#############################################################################
// Renderer
//#############################################################################
//
Renderer::Renderer(
	RendererRate calibration_rate,
	RendererComplexity calibration_complexity,
	RendererPriority calibration_priority,
	InterestType interest_type,
	InterestDepth depth_calibration,
	ClassID class_ID,
	SharedData &virtual_data
):
	Receiver(class_ID, virtual_data),
	rendererOriginSocket(NULL),
	entitySocket(NULL)
{
	rendererStatus = InactiveRendererStatus;

	calibrationRate = calibration_rate;
	calibrationFrameDuration = 1.0f / calibration_rate;
	nextRenderTime = 0.0f;

	Verify(MinRendererComplexity < calibration_complexity);
	Verify(calibration_complexity <= MaxRendererComplexity);
	calibrationComplexity = calibration_complexity;

	calibrationPriority = calibration_priority;
	interestType = interest_type;
	depthCalibration = depth_calibration;
	framePercentBudget = DefaultRendererFrameBudget;
	Check_Fpu();
}

//
//#############################################################################
// ~Renderer
//#############################################################################
//
Renderer::~Renderer()
{
	UnlinkFromEntity();
	Check_Fpu();
}

//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
	Renderer::TestInstance() const
{
	if (!IsDerivedFrom(*GetClassDerivations()))
	{
		return False;
	}
	Check(&rendererOriginSocket);
	Check(&entitySocket);
   return True;
}

//
//#############################################################################
// LinkToEntity
//#############################################################################
//
void
	Renderer::LinkToEntity(Entity *entity)
{
	Check(this);
	Check(entity);

	//
	//--------------------------------------------------------------------------
	// Unlink from current entity and add new entity
	//--------------------------------------------------------------------------
	//
	UnlinkFromEntity();
	entitySocket.Add(entity);

	//
	//--------------------------------------------------------------------------
	// Make an interest origin for the given entity
	//--------------------------------------------------------------------------
	//
	RendererOrigin *rendererOrigin;

	rendererOrigin =
		new RendererOrigin(
			this,
			entity,
			interestType,
			depthCalibration
		);
	Register_Object(rendererOrigin);

	Check(application);
	application->GetInterestManager()->AdoptInterestOrigin(rendererOrigin);
	rendererOriginSocket.Add(rendererOrigin);
	Check_Fpu();
}

//
//#############################################################################
// UnlinkFromEntity
//#############################################################################
//
void
	Renderer::UnlinkFromEntity()
{
	Check(this);

	//
	//--------------------------------------------------------------------------
	// Delete current interest origin
	//--------------------------------------------------------------------------
	//
	RendererOrigin *rendererOrigin;

	if ((rendererOrigin = rendererOriginSocket.GetCurrent()) != NULL)
	{
		Check(rendererOrigin);

		//
		// Remove entity from socket
		//
		entitySocket.Remove();

		//
		// Delete the interest origin
		//
		Check(application);
		Check(application->GetInterestManager());
		application->GetInterestManager()->OrphanInterestOrigin(rendererOrigin);
		Unregister_Object(rendererOrigin);
		delete rendererOrigin;
	}
	Check_Fpu();
}

//
//#############################################################################
// LoadMission
//#############################################################################
//
void
	Renderer::LoadMission(Mission *mission)
{
	Check(this);

	Verify(rendererStatus == InactiveRendererStatus);
	rendererStatus = LoadingRendererStatus;
	nextRenderTime = Now();

	Check(application);
	application->GetRendererManager()->StartRenderer(this);
	LoadMissionImplementation(mission);
	Check_Fpu();
}

//
//#############################################################################
// Shutdown
//#############################################################################
//
void
	Renderer::Shutdown()
{
	Check(this);

	//
	//-------------------------------------------------
	// Shutdown and unhook the renderer if it is active
	//-------------------------------------------------
	//
	if (rendererStatus == InactiveRendererStatus)
	{
		return;
	}

	rendererStatus = InactiveRendererStatus;
	Check(application);
	application->GetRendererManager()->StopRenderer(this);

	ShutdownImplementation();
	Check_Fpu();
}

//
//#############################################################################
// SetRendererStatusToRunning
//#############################################################################
//
void
	Renderer::SetRendererStatusToRunning()
{
	Verify(rendererStatus == LoadingRendererStatus);
	rendererStatus = RunningRendererStatus;
	Check_Fpu();
}

//
//#############################################################################
// UpdateRendererOrigin
//#############################################################################
//
void
	Renderer::UpdateInterestOrigin(Time target_render_time)
{
	Check(this);

	//
	//--------------------------------------------------------------------------
	// If the renderer is inactive, skip it
	//--------------------------------------------------------------------------
	//
	if (rendererStatus == InactiveRendererStatus)
		return;

	//
	//--------------------------------------------------------------------------
	// Does the renderer need to run this frame to meet its frame rate?
	//--------------------------------------------------------------------------
	//
	if (nextRenderTime > target_render_time)
		return;

	//
	//--------------------------------------------------------------------------
	// Update the interest origin
	//--------------------------------------------------------------------------
	//
   Entity *entity;
	RendererOrigin *rendererOrigin;

   entity = entitySocket.GetCurrent();
   Check(entity);
	rendererOrigin = rendererOriginSocket.GetCurrent();
	Check(rendererOrigin);
	rendererOrigin->Update(entity->GetInterestZoneID());
	Check_Fpu();
}

//
//#############################################################################
// Execute
//#############################################################################
//
void
	Renderer::Execute(
		Time target_render_time,
		RendererComplexity complexity_update
	)
{
	Check(this);

	mTargetRenderTime = target_render_time;

	//
	//--------------------------------------------------------------------------
	// If the renderer is suspended, skip it
	//--------------------------------------------------------------------------
	//
	if (rendererStatus == InactiveRendererStatus)
		return;

	//
	//--------------------------------------------------------------------------
	// Does the renderer need to run this frame to meet its frame rate?
	//--------------------------------------------------------------------------
	//
//	if (nextRenderTime > target_render_time)
//		return;
	// nextRenderTime += calibrationFrameDuration;
   nextRenderTime = Now();
   nextRenderTime += calibrationFrameDuration;

	//
	//--------------------------------------------------------------------------
	// Keep track of renderers frame budget
	//--------------------------------------------------------------------------
	//
	RendererFrameBudget start_percent;
	RendererFrameBudget end_percent;

	start_percent = Get_Frame_Percent_Used();
	end_percent = start_percent + framePercentBudget;
   Clamp(end_percent, 0.0f, 1.0f);

	//
	//--------------------------------------------------------------------------
	// Get interest orign
	//--------------------------------------------------------------------------
	//
	RendererOrigin *rendererOrigin;

	rendererOrigin = rendererOriginSocket.GetCurrent();
	Check(rendererOrigin);

	//
	//--------------------------------------------------------------------------
	// Get iterators for the renderers interest origin and execute
	// renderer
	//--------------------------------------------------------------------------
	//
	RendererOrigin::InterestingEntityIterator
		interesting_entity_iterator(rendererOrigin);

	Check(&interesting_entity_iterator);

Time startImplementation = Now();
	ExecuteImplementation(
		complexity_update,
		&interesting_entity_iterator
	);
Time endImplementation = Now();

	//
	//--------------------------------------------------------------------------
	// If the renderer is under budget then run background if available
	//--------------------------------------------------------------------------
	//
	RendererFrameBudget current_frame_use;
	/*for (
		current_frame_use = Get_Frame_Percent_Used();
		(start_percent < current_frame_use) && (current_frame_use < end_percent);
		current_frame_use = Get_Frame_Percent_Used()
	)
	{
		if (!ExecuteBackground())
			break;
	}*/

	Check_Fpu();
}

//
//#############################################################################
// NotifyOfNewInterestingEntityMessageHandler
//#############################################################################
//
void
	Renderer::NotifyOfNewInterestingEntityMessageHandler(
		NotifyOfNewInterestingEntityMessage *message
	)
{
	Check(this);
	Check(message);
	Verify(message->messageID == NotifyOfNewInterestingEntityMessageID);

	Entity *entity;

	if ((entity = message->GetInterestingEntity()) != NULL)
	{
		Check(entity);
		NotifyOfNewInterestingEntity(entity);
	}
	Check_Fpu();
}

//
//#############################################################################
// NotifyOfBecomingUninterestingEntityMessageHandler
//#############################################################################
//
void
	Renderer::NotifyOfBecomingUninterestingEntityMessageHandler(
		NotifyOfBecomingUninterestingEntityMessage *message
	)
{
	Check(this);
	Check(message);
	Verify(message->messageID == NotifyOfBecomingUninterestingEntityMessageID);

	NotifyOfBecomingUninterestingEntity(message->GetUninterestingEntity());
	Check_Fpu();
}

//
//#############################################################################
// StartEntityEffectMessageHandler
//#############################################################################
//
void
	Renderer::StartEntityEffectMessageHandler(
		StartEntityEffectMessage *message
	)
{
	Check(this);
	Check(message);
	Verify(message->messageID == StartEntityEffectMessageID);

	//
	//--------------------------------------------------------------------------
	// If the entity does not exists then return
	//--------------------------------------------------------------------------
	//
	Entity *entity;
	if ((entity = message->GetEntity()) == NULL)
   	return;
	Check(entity);

	//
	//--------------------------------------------------------------------------
	// Get the effect model resource
	//--------------------------------------------------------------------------
	//
	ResourceDescription::ResourceID effect_resource_ID;
	ResourceDescription *resource_description;
	Explosion::ModelResource *model_resource;

	effect_resource_ID = message->GetResourceID();
	Check(application);
	Check(application->GetResourceFile());
	resource_description =
		application->GetResourceFile()->SearchList(
			effect_resource_ID,
			ResourceDescription::GameModelResourceType
		);
	Check(resource_description);
	resource_description->Lock();
	model_resource =
		(Explosion::ModelResource*)resource_description->resourceAddress;
	Check_Pointer(model_resource);

	//
	//--------------------------------------------------------------------------
	// If an explosion resource table is being used then use it to set
	// the resource
	//--------------------------------------------------------------------------
	//
	if (model_resource->resourceTableObjectID != NullObjectID)
	{
		//
		// Get resource table pointer,
		// Then set the appropriate resource ID
		//
		Plug *plug;
		ExplosionResourceTable *resource_table;
		ResourceDescription::ResourceID new_resource_ID;

		plug = PlugStreamManager::FindPlug(model_resource->resourceTableObjectID);
		resource_table = Cast_Object(ExplosionResourceTable*, plug);
		Check(resource_table);
		new_resource_ID = resource_table->FindResourceID(entity);
		if (new_resource_ID != ResourceDescription::NullResourceID)
		{
			effect_resource_ID = new_resource_ID;
		}
	}

	//
	//--------------------------------------------------------------------------
	// Call the start effect implementation
	//--------------------------------------------------------------------------
	//
	StartEntityEffectImplementation(
		entity,
		message->GetDamageZone(),
		effect_resource_ID
	);
	resource_description->Unlock();
}

//
//#############################################################################
// StopAllEntityEffectsMessageHandler
//#############################################################################
//
void
	Renderer::StopAllEntityEffectsMessageHandler(
		StopAllEntityEffectsMessage *message
	)
{
	Check(this);
	Check(message);
	Verify(message->messageID == StopAllEntityEffectsMessageID);

	Entity *entity;
	if ((entity = message->GetEntity()) != NULL)
	{
		Check(entity);
		StopAllEntityEffectsImplementation(entity);
	}
}

//
//#############################################################################
// StartEntityAlarmMessageHandler
//#############################################################################
//
void
	Renderer::StartEntityAlarmMessageHandler(
		StartEntityAlarmMessage *message
	)
{
	Check(this);
	Check(message);
	Verify(message->messageID == StartEntityAlarmMessageID);

	Entity *entity;
	if ((entity = message->GetEntity()) != NULL)
	{
		Check(entity);
		StartEntityAlarmImplementation(
			entity,
			message->GetSubsystem(),
			message->GetCondition(),
			message->GetResourceID()
		);
	}
}

//
//#############################################################################
// StopEntityAlarmMessageHandler
//#############################################################################
//
void
	Renderer::StopEntityAlarmMessageHandler(
		StopEntityAlarmMessage *message
	)
{
	Check(this);
	Check(message);
	Verify(message->messageID == StopEntityAlarmMessageID);

	Entity *entity;
	if ((entity = message->GetEntity()) != NULL)
	{
		Check(entity);
		StopEntityAlarmImplementation(
			entity,
			message->GetSubsystem(),
			message->GetCondition()
		);
	}
}

//
//#############################################################################
// ExecuteImplementation
//#############################################################################
//
void
	Renderer::ExecuteImplementation(
		RendererComplexity,
		RendererOrigin::InterestingEntityIterator*
	)
{
	Fail("Renderer::ExecuteImplementation - Should never reach here");
}

//
//#############################################################################
// LoadMissionImplementation
//#############################################################################
//
void
	Renderer::LoadMissionImplementation(Mission*)
{
	Fail("Renderer::LoadMissionImplementation - Should never reach here");
}

//
//#############################################################################
// ShutdownImplementation
//#############################################################################
//
void
	Renderer::ShutdownImplementation()
{
	Fail("Renderer::ShutdownImplementation - Should never reach here");
}

//#############################################################################
//#########################    RendererManager    #############################
//#############################################################################

//
//#############################################################################
// RendererManager
//#############################################################################
//
RendererManager::RendererManager():
	Receiver(RendererManagerClassID, DefaultData),
	renderers(NULL)
{
}

//
//#############################################################################
// ~RendererManager
//#############################################################################
//
RendererManager::~RendererManager()
{
}

//
//#############################################################################
// TestInstance
//#############################################################################
//
Logical
	RendererManager::TestInstance() const
{
	Receiver::TestInstance();
	Check(&renderers);
	Check_Fpu();
	return True;
}

//
//#############################################################################
// StartRenderer
//#############################################################################
//
void
	RendererManager::StartRenderer(Renderer *renderer)
{
	Check(this);
	Check(renderer);

	#if DEBUG_LEVEL>0
		SChainIterator iterator(&renderers);
		Verify(iterator.IsPlugMember(renderer) == False);
	#endif

	renderers.Add(renderer);
	Check_Fpu();
}

//
//#############################################################################
// StopRenderer
//#############################################################################
//
void
	RendererManager::StopRenderer(Renderer *renderer)
{
	Check(this);
	Check(renderer);

	#if DEBUG_LEVEL>0
	{
		SChainIteratorOf<Renderer*> iterator(&renderers);
		Verify(iterator.IsPlugMember(renderer) == True);
	}
	#endif

	SChainIteratorOf<Renderer*> iterator(&renderers);
	iterator.RemovePlug(renderer);
	Check_Fpu();
}

//
//#############################################################################
// AreRenderersRunning
//#############################################################################
//
Logical
	RendererManager::AreRenderersRunning()
{
	Check(this);

	Renderer
		*renderer;
	SChainIteratorOf<Renderer*>
		renderers_iterator(&renderers);

	if (renderers_iterator.GetCurrent() == NULL)
		return False;

	while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
	{
		Check(renderer);
		if (renderer->GetRendererStatus() != RunningRendererStatus)
			return False;
	}
	Check_Fpu();
	return True;
}

//
//#############################################################################
// UpdateInterestOrigins
//#############################################################################
//
void
	RendererManager::UpdateInterestOrigins(Time target_render_time)
{
	Check(this);

	//
	// HACK - under construction, does not include complexity or priorities
	//
	Renderer
		*renderer;
	SChainIteratorOf<Renderer*>
		renderers_iterator(&renderers);

	while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
	{
		Check(renderer);
		renderer->UpdateInterestOrigin(target_render_time);
	}
	Check_Fpu();
}

//
//#############################################################################
// Execute
//#############################################################################
//
void
	RendererManager::Execute(
		Time target_render_time,
		Time,
		Time
	)
{
	Check(this);

	//
	// HACK - under construction, does not include complexity or priorities
	//
	Renderer *renderer;
	RendererComplexity complexity_update;
	SChainIteratorOf<Renderer*> renderers_iterator(&renderers);
Time startRender = Now();
   int renderItem = 0;
	while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
	{
		Check(renderer);

		// Calculate current complexity
		// HACK - use calibration complexity for now
Time startComplexity = Now();
		complexity_update = renderer->GetCalibrationComplexity();
Time endComplexity = Now();

		renderer->Execute(target_render_time, complexity_update);
      renderItem++;
	}
Time endRender = Now();
endRender = endRender;
	Check_Fpu();
}

//
//#############################################################################
// ExecuteIdle
//#############################################################################
//
void RendererManager::ExecuteIdle()
{
	Renderer *renderer;
	SChainIteratorOf<Renderer*> renderers_iterator(&renderers);

	while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
	{
		Check(renderer);

		renderer->ExecuteIdle();
	}
	Check_Fpu();
}

//
//#############################################################################
// PostRendererEvent
//#############################################################################
//
void
	RendererManager::PostRendererEvent(
		Entity *entity,
		Receiver::Message *message
	)
{
	Check(this);
	Check(entity);
	Check(message);

	Renderer
		*renderer;
	SChainIteratorOf<Renderer*>
		renderers_iterator(&renderers);

	while ((renderer = renderers_iterator.ReadAndNext()) != NULL)
	{
		Check(renderer);
		Check(application);
		Check(application->GetInterestManager());
		application->GetInterestManager()->PostRendererEvent(
			entity,
			renderer,
			message
		);
	}
}

//~~~~~~~~~~~~~~~~~ Renderer__NotifyOfNewInterestingEntityMessage ~~~~~~~~~~~~~

Renderer__NotifyOfNewInterestingEntityMessage::
	Renderer__NotifyOfNewInterestingEntityMessage(
		Entity *interesting_entity
	):
		Receiver::Message(
			Renderer::NotifyOfNewInterestingEntityMessageID,
			sizeof(Renderer__NotifyOfNewInterestingEntityMessage)
		)
{
	Check(interesting_entity);
	entityID = interesting_entity->GetEntityID();
	Check_Fpu();
}

Entity*
	Renderer__NotifyOfNewInterestingEntityMessage::GetInterestingEntity()
{
	Check(this);
	Check(application);
	Check(application->GetHostManager());

	Check_Fpu();
	return application->GetHostManager()->GetEntityPointer(entityID);
}

//~~~~~~~~~~~~~~ Renderer__NotifyOfBecomingUninterestingEntityMessage ~~~~~~~~~

Renderer__NotifyOfBecomingUninterestingEntityMessage::
	Renderer__NotifyOfBecomingUninterestingEntityMessage(
		Entity *uninteresting_entity
	):
		Receiver::Message(
			Renderer::NotifyOfBecomingUninterestingEntityMessageID,
			sizeof(Renderer__NotifyOfBecomingUninterestingEntityMessage)
		)
{
	uninterestingEntity = uninteresting_entity;
	Check_Fpu();
}

//~~~~~~~~~~~~~~~~~~~~~~~ Renderer__EntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Renderer__EntityMessage::Renderer__EntityMessage(
	Receiver::MessageID message_ID,
	size_t message_size,
	Entity *entity
):
	Receiver::Message(
		message_ID,
		message_size
	)
{
	Check(entity);
	entityID = entity->GetEntityID();
}

Entity*
	Renderer__EntityMessage::GetEntity()
{
	Check(this);
	Check(application);
	Check(application->GetHostManager());
	return application->GetHostManager()->GetEntityPointer(entityID);
}

//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityEffectMessage ~~~~~~~~~~~~~~~~~~~~~~~

Renderer__StartEntityEffectMessage::Renderer__StartEntityEffectMessage(
	Entity *entity,
	DamageZone *damage_zone,
	ResourceDescription::ResourceID resource_ID
):
	Renderer__EntityMessage(
		Renderer::StartEntityEffectMessageID,
		sizeof(Renderer__StartEntityEffectMessage),
		entity
	)
{
	Check(damage_zone);
	Verify(resource_ID != ResourceDescription::NullResourceID);
	damageZone = damage_zone;
	resourceID = resource_ID;
}

//~~~~~~~~~~~~~~~~~~ Renderer__StopAllEntityEffectsMessage ~~~~~~~~~~~~~~~~~~~~

Renderer__StopAllEntityEffectsMessage::Renderer__StopAllEntityEffectsMessage(
	Entity *entity
):
	Renderer__EntityMessage(
		Renderer::StopAllEntityEffectsMessageID,
		sizeof(Renderer__StopAllEntityEffectsMessage),
		entity
	)
{
}

//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~

Renderer__StartEntityAlarmMessage::Renderer__StartEntityAlarmMessage(
	Entity *entity,
	Subsystem *alarm_subsystem,
	Enumeration alarm_condition,
	ResourceDescription::ResourceID resource_ID
):
	Renderer__EntityMessage(
		Renderer::StartEntityAlarmMessageID,
		sizeof(Renderer__StartEntityAlarmMessage),
		entity
	)
{
	Check(alarm_subsystem);
	#if DEBUG_LEVEL>0
		if (resource_ID == ResourceDescription::NullResourceID)
		{
			Dump(alarm_subsystem->GetClassID());
			Dump(alarm_condition);
		}
	#endif
	Warn(resource_ID == ResourceDescription::NullResourceID); // HACK - ECH Why is this sometimes NULL?
	subsystem = alarm_subsystem;
	condition = alarm_condition;
	resourceID = resource_ID;
}

//~~~~~~~~~~~~~~~~~~ Renderer__StopEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~~

Renderer__StopEntityAlarmMessage::Renderer__StopEntityAlarmMessage(
	Entity *entity,
	Subsystem *alarm_subsystem,
	Enumeration alarm_condition
):
	Renderer__EntityMessage(
		Renderer::StopEntityAlarmMessageID,
		sizeof(Renderer__StopEntityAlarmMessage),
		entity
	)
{
	Check(alarm_subsystem);
	subsystem = alarm_subsystem;
	condition = alarm_condition;
}

#ifdef TEST_CLASS
#	include "renderer.tcp"
#endif
