
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_CorpseCollection.cpp
// Author : Andy Tate
// Date   : 19-Jan-2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "Entity/PhysicalObject/AVP_CorpseCollection.h"

// Asura independent header-files...

// Asura platform header-files...

// Game independent header-files...
#include "Actor/AVP_Actor_AnimationHandler.h"
#include "Entity/PhysicalObject/Actor/AVP_ClientEntity_Actor.h"
#include "Entity/PhysicalObject/Actor/AVP_ServerEntity_Actor.h"

// Game platform header-files...

// Tools header-files...


////////////////////////////////////////////////////////////////////////////////
// Constant declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Static variable declarations...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Private functions...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_CorpseCollection::ApplyConnection
// Author       : Andy Tate
// Date         : 31-Jan-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_CorpseCollection::ApplyConnection(const bool bServer,
										   const Asura_Guid uGuid,
										   const Asura_Hash_ID uMarkerPointHash,
										   const u_int uBoneID,
										   const Asura_Vector_3& xPosition)
{
	if(bServer)
	{
		AVP_ServerEntity_PhysicalObject*	pxServer	= AVP_ServerEntity_PhysicalObject::FindEntity(uGuid);

		if(pxServer == NULL)
		{
			Asura_Assertf(false, ("Cannot find corpse server-entity to attach (GUID = %d)", uGuid));
			return(false);
		}
		else if(pxServer->LinkToParent(m_uMyGuid, uMarkerPointHash, uBoneID, xPosition))
		{
			return(true);
		}
		else
		{
			Asura_Assertf(false, ("Failed to link corpse server-entity to parent (GUID = %d, Parent = %d)", uGuid, m_uMyGuid));
			return(false);
		}
	}
	else
	{
		AVP_ClientEntity_PhysicalObject*	pxClient	= AVP_ClientEntity_PhysicalObject::FindEntity(uGuid);

		if(pxClient == NULL)
		{
			Asura_Assertf(false, ("Cannot find corpse client-entity to attach (GUID = %d)", uGuid));
			return(false);
		}
		else
		{
			return(true);
		}
	}
}

/// End of function 'AVP_CorpseCollection::ApplyConnection'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_CorpseCollection::ApplyDisconnection
// Author       : Andy Tate
// Date         : 31-Jan-2007
////////////////////////////////////////////////////////////////////////////////

bool AVP_CorpseCollection::ApplyDisconnection(const bool bServer,
											  const Asura_Guid uGuid)
{
	// Client OR server?
	if(bServer)
	{
		AVP_ServerEntity_Actor*	pxServer	= AVP_ServerEntity_Actor::FindEntity(uGuid);

		// Unlink from the parent...
		if(pxServer == NULL)
		{
			Asura_Assertf(false, ("Cannot find corpse server-entity to detach (GUID = %d)", uGuid));
			return(false);
		}
		else if(pxServer->UnlinkFromParent())
		{
			pxServer->SetPhysicsObjectIgnore(true);
			return(true);
		}
		else
		{
			Asura_Assertf(false, ("Failed to unlink corpse server-entity from parent (GUID = %d)", uGuid));
			return(false);
		}
	}
	else
	{
		AVP_ClientEntity_Actor*	pxClient	= AVP_ClientEntity_Actor::FindEntity(uGuid);

		// Turn into a ragdoll...
		if(pxClient == NULL)
		{
			Asura_Assertf(false, ("Cannot find corpse client-entity to detach (GUID = %d)", uGuid));
			return(false);
		}
		else
		{
			return(pxClient->MakeRagdoll());
		}
	}
}

/// End of function 'AVP_CorpseCollection::ApplyDisconnection'. ///



////////////////////////////////////////////////////////////////////////////////
// Protected functions...
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Public functions...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_CorpseCollection::AVP_CorpseCollection
// Author       : Andy Tate
// Date         : 19-Jan-2007
////////////////////////////////////////////////////////////////////////////////

AVP_CorpseCollection::AVP_CorpseCollection(const Asura_Guid uMyGuid,
										   const u_int uMaxCorpses)
: m_uFlags(0)
, m_uMyGuid(uMyGuid)
{
	m_uMaxCorpses	= uMaxCorpses;
	m_puCorpseGuids	= new Asura_Guid [uMaxCorpses];
}

/// End of function 'AVP_CorpseCollection::AVP_CorpseCollection'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_CorpseCollection::~AVP_CorpseCollection
// Author       : Andy Tate
// Date         : 19-Jan-2007
////////////////////////////////////////////////////////////////////////////////

AVP_CorpseCollection::~AVP_CorpseCollection()
{
	delete[](m_puCorpseGuids);
}

/// End of function 'AVP_CorpseCollection::~AVP_CorpseCollection'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_CorpseCollection::AddCorpse
// Author       : Andy Tate
// Date         : 17-Nov-2006
////////////////////////////////////////////////////////////////////////////////

bool AVP_CorpseCollection::AddCorpse(const bool bServer,
									 const Asura_Guid uGuid,
									 const Asura_Hash_ID uMarkerPointHash,
									 const u_int uBoneID,
									 const Asura_Vector_3& xPosition)
{
	if(m_uNumCorpses < m_uMaxCorpses)
	{
		// Connect this corpse...
		if(ApplyConnection(bServer, uGuid, uMarkerPointHash, uBoneID, xPosition))
		{
			m_puCorpseGuids[m_uNumCorpses++]	= uGuid;
			return(true);
		}
		else
		{
			return(false);
		}
	}
	else
	{
		Asura_Assert(false, "Too many corpses have been collected by this spear.");
		return(false);
	}
}

/// End of function 'AVP_CorpseCollection::AddCorpse'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_CorpseCollection::RemoveCorpse
// Author       : Andy Tate
// Date         : 7-Nov-2006
////////////////////////////////////////////////////////////////////////////////

bool AVP_CorpseCollection::RemoveCorpse(const bool bServer,
										const Asura_Guid uGuid)
{
	for(u_int u = 0; u < m_uNumCorpses; u++)
	{
		// Is this our corpse?
		if(m_puCorpseGuids[u] == uGuid)
		{
			// Remove from the corpse list...
			for(u_int v = (u + 1); v < m_uNumCorpses; v++)
			{
				m_puCorpseGuids[v - 1]	= m_puCorpseGuids[v];
			}

			m_uNumCorpses--;

			// Disconnect this corpse...
			ApplyDisconnection(bServer, uGuid);
		}
	}

	// Failed to find the specified corpse...
	Asura_Assertf(false, ("Failed to find corpse to detach (GUID = %d)", uGuid));
	return(false);
}

/// End of function 'AVP_CorpseCollection::RemoveCorpse'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : AVP_CorpseCollection::RemoveAllCorpses
// Author       : Andy Tate
// Date         : 17-Nov-2006
////////////////////////////////////////////////////////////////////////////////

void AVP_CorpseCollection::RemoveAllCorpses(const bool bServer)
{
	for(u_int u = 0; u < m_uNumCorpses; u++)
	{
		const Asura_Guid	uGuid	= m_puCorpseGuids[u];

		// Disconnect this corpse...
		ApplyDisconnection(bServer, uGuid);
	}

	// Reset the list...
	m_uNumCorpses	= 0;
}

/// End of function 'AVP_CorpseCollection::RemoveAllCorpses'. ///


/// End of file. ///
