//////////////////////////////////////////////////////////////////////////////
//
// AVP_Knowledge_System_Predator.cpp
//
// Copyright (C) 2007 Rebellion. All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

// core
#include "Core/Asura.h"

// header
#include "Knowledge/AVP_Knowledge_System_Predator.h"

// asura
#include "ChunkSystem/Asura_Chunk_Stream.h"
#ifndef ASURA_NO_DEBUG_OUTPUT
#include "Rendering/Asura_Font_System.h"
#endif

// avp
#include "Core/BrainTypes/AVP_Brain_Actor.h"
#include "Entity/AVP_Entity_Classification.h"
#include "Entity/Locations/ShootAt/AVP_ServerEntity_ShootAt.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Alien/AVP_ServerActor_Alien.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/FaceHugger/AVP_ServerActor_FaceHugger.h"
#include "Entity/PhysicalObject/Actor/Vertebrates/Predator/AVP_ServerActor_Predator.h"

// axon
#include "Knowledge/Axon_Knowledge.h"
#include "Knowledge/SenseTypes/AVP_Sense_Hearing_Predator.h"
#include "Knowledge/SenseTypes/AVP_Sense_Vision_Actor.h"
#include "Knowledge/SenseTypes/AVP_Sense_Vision_Predator.h"
#include "Core/AVP_Waypoint_Manager.h"
#include "Core/BrainTypes/AVP_Brain_Actor_Predator.h"


//////////////////////////////////////////////////////////////////////////////
//
// AVP_Knowledge_System_Predator
//
//////////////////////////////////////////////////////////////////////////////

float AVP_Knowledge_System_Predator::s_fAggressiveToActiveTime		= 5.5f;
float AVP_Knowledge_System_Predator::s_fActiveToPassiveTime		= 10.0f;

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: Constructor
//---------------------------------------------------------------------------
AVP_Knowledge_System_Predator::AVP_Knowledge_System_Predator(AVP_Brain_Actor* pxBrain)
: PARENT(pxBrain)
, m_xBestThreatKnowledge()
, m_pxSecondaryThreatKnowledge(NULL)
, m_uNumSecondaryThreats(0)
, m_xBestAlertKnowledge()
, m_fAlertLevelTimer(0.0f)
, m_uShootAtGuid(ASURA_GUID_UNREGISTERED)
, m_bIsTargetAShootAtNode(false)
{
	m_xBestThreatKnowledge.Reset();
	m_xBestAlertKnowledge.Reset();
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: Deconstructor
//---------------------------------------------------------------------------
AVP_Knowledge_System_Predator::~AVP_Knowledge_System_Predator()
{
	if (m_pxSecondaryThreatKnowledge)
	{
		delete [] m_pxSecondaryThreatKnowledge;
		m_pxSecondaryThreatKnowledge = NULL;
	}
}


//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: Verify
//---------------------------------------------------------------------------
#ifndef ASURA_NO_DEBUG_OUTPUT
bool AVP_Knowledge_System_Predator::Verify()
{
	Asura_Assert( m_pxVision, "AVP_Knowledge_System_Predator::Verify - no vision" );
	Asura_Assert( m_pxHearing, "AVP_Knowledge_System_Predator::Verify - no hearing" );
	return ( PARENT::Verify() && m_pxVision && m_pxHearing );
}
#endif

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: Initialise
//---------------------------------------------------------------------------
void AVP_Knowledge_System_Predator::Initialise()
{
	PARENT::Initialise();

	m_xBestThreatKnowledge.Reset();
	m_xBestAlertKnowledge.Reset();

	m_uShootAtGuid = ASURA_GUID_UNREGISTERED;
	m_bIsTargetAShootAtNode = false;
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: ReadFromChunkStream
//---------------------------------------------------------------------------
void AVP_Knowledge_System_Predator::ReadFromChunkStream( Asura_Chunk_Stream& xStream )
{
    int iVersion;
    xStream >> iVersion;

    PARENT::ReadFromChunkStream( xStream );

    if ( iVersion == CURRENT_CHUNK_VERSION )
    {
    }
    else
    {
        Asura_Assertf( iVersion == CURRENT_CHUNK_VERSION, ( "AVP_Knowledge_System_Predator::ReadFromChunkStream - unhandled chunk version (%d)", iVersion ) );
    }
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: WriteToChunkStream
//---------------------------------------------------------------------------
void AVP_Knowledge_System_Predator::WriteToChunkStream( Asura_Chunk_Stream& xStream ) const
{
    xStream << CURRENT_CHUNK_VERSION;

    PARENT::WriteToChunkStream( xStream );
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: Update
//---------------------------------------------------------------------------
void AVP_Knowledge_System_Predator::Update(const float fTimeslice)
{
	PARENT::Update(fTimeslice);

	UpdateBestKnowledge(fTimeslice);
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: UpdateBestKnwoledge
//---------------------------------------------------------------------------

DEBUGVAR float dbg_fVisionStabilisationTime = 0.5f;

void AVP_Knowledge_System_Predator::UpdateBestKnowledge(const float fTimeslice)
{
	AVP_ServerEntity_Actor* pxOurActor = GetActorBrain()->GetActor();

	if (!pxOurActor)
	{
		return;
	}

	m_xBestThreatKnowledge.Reset();
	m_xBestAlertKnowledge.Reset(); 

	
	float fClosestVisionThreatDistSq	= Asura_Maths::LargeFloat;	
	float fTimeSinceSeen				= Asura_Maths::LargeFloat;	
	u_int uNumEntries					= m_pxVision->GetList()->GetNumEntries();
	int iBestPriority = AVP_AI_TargetPriorityData::IGNORE_P;

	// special shoot at target
	if (m_uShootAtGuid != ASURA_GUID_UNREGISTERED)
	{
		if (m_bIsTargetAShootAtNode) // not a real actor
		{
			const AVP_ServerEntity_ShootAt* pxShootAtTarget = AVP_ServerEntity_ShootAt::FindEntity(m_uShootAtGuid);
			Asura_Assertf(pxShootAtTarget, ("ShootAtTarget entity %u not found", m_uShootAtGuid));
			if (pxShootAtTarget)
			{
				m_xBestThreatKnowledge.m_uKnowledgeID          = GetNewKnowledgeID();
				m_xBestThreatKnowledge.m_uSourceGuid           = pxShootAtTarget->GetGuid();
				m_xBestThreatKnowledge.m_uSourceClassification = pxShootAtTarget->GetClassification();
				m_xBestThreatKnowledge.m_iSenseID              = AXON_SENSE_TYPE_VISION;
				m_xBestThreatKnowledge.m_uTypeInformation      = AVP_Sense_Vision::TYPE_INFO_NOT_SET;
				m_xBestThreatKnowledge.m_fAge                  = 0.0f;
				m_xBestThreatKnowledge.m_fThreatValue          = 0.0f;
				m_xBestThreatKnowledge.m_xPosition             = pxShootAtTarget->GetPosition();
				m_xBestThreatKnowledge.m_xDirection            = pxShootAtTarget->GetPosition() - pxOurActor->GetPosition();
				m_xBestThreatKnowledge.m_fDistance             = m_xBestThreatKnowledge.m_xDirection.Normalise();
			}
		}
		else
		{
			const AVP_ServerEntity_Actor* pxShootAtTarget = AVP_ServerEntity_Actor::FindEntity(m_uShootAtGuid);
			if (pxShootAtTarget && !pxShootAtTarget->IsDead() && !pxShootAtTarget->IsDestroyed())
			{
				m_xBestThreatKnowledge.m_uKnowledgeID          = GetNewKnowledgeID();
				m_xBestThreatKnowledge.m_uSourceGuid           = pxShootAtTarget->GetGuid();
				m_xBestThreatKnowledge.m_uSourceClassification = pxShootAtTarget->GetClassification();
				m_xBestThreatKnowledge.m_iSenseID              = AXON_SENSE_TYPE_VISION;
				m_xBestThreatKnowledge.m_uTypeInformation      = AVP_Sense_Vision::TYPE_INFO_NOT_SET;
				m_xBestThreatKnowledge.m_fAge                  = 0.0f;
				m_xBestThreatKnowledge.m_fThreatValue          = 0.0f;
				m_xBestThreatKnowledge.m_xPosition             = pxShootAtTarget->GetPosition();
				m_xBestThreatKnowledge.m_xDirection            = pxShootAtTarget->GetPosition() - pxOurActor->GetPosition();
				m_xBestThreatKnowledge.m_fDistance             = m_xBestThreatKnowledge.m_xDirection.Normalise();
			}
		}
	}

	// we found a valid target
	if ( m_xBestThreatKnowledge.GetGuid() != ASURA_GUID_UNREGISTERED )
	{
		return;
	}

	// Vision!
	for ( Asura_Hashed_List_ConstIt< Axon_Knowledge > xVisionIt( m_pxVision->GetList() ); !xVisionIt.Done(); xVisionIt.Next() )
	{
		// Use the closest enemy entity as our threat for now
		const Axon_Knowledge* pxKnowledge = xVisionIt.GetCurrent();
		Asura_Assert( pxKnowledge, "AVP_Knowledge_System::UpdateBestKnowledge: invalid vision knowledge" );
		if ( pxKnowledge )
		{

			int iPriority;
			if(!GetActorBrain()->CalcTargetingPriority(pxKnowledge->m_uSourceClassification, pxKnowledge->m_uSourceGuid, iPriority))
			{
				iPriority = AVP_AI_TargetPriorityData::NORMAL;
			}

			switch (pxKnowledge->m_uSourceClassification)
			{
			default:
				continue;
			case AVP_ENTITYCLASS_ALIEN:
			case AVP_ENTITYCLASS_ALIENQUEEN:
			case AVP_ENTITYCLASS_ALIENCHESTBURSTER:
			case AVP_ENTITYCLASS_HUMAN:
			case AVP_ENTITYCLASS_ALIEN_HYBRID:
			case AVP_ENTITYCLASS_ANDROID:
			case AVP_ENTITYCLASS_MARINE:
			case AVP_ENTITYCLASS_CIVILIAN:
			case AVP_ENTITYCLASS_SENTRYGUN:
				break;
			case AVP_ENTITYCLASS_ALIENFACEHUGGER: // ignore hugging facehuggers as they already dead;
				{
					const AVP_ServerActor_FaceHugger* pxTarget = AVP_ServerActor_FaceHugger::FindEntity( pxKnowledge->GetGuid() );
					if ( !pxTarget || pxTarget->IsHugging() )
					{
						continue;
					}
				}
				break;
			}

			if (iPriority < iBestPriority || iPriority == AVP_AI_TargetPriorityData::IGNORE_P)
			{
				continue;
			}

			Asura_Vector_3				xThreatDirection	= pxKnowledge->m_xPosition - pxOurActor->GetPosition();
			const float					fDistanceSq			= xThreatDirection.MagnitudeSquared();

			if (!(pxKnowledge->m_fAge > fTimeSinceSeen + dbg_fVisionStabilisationTime) && fDistanceSq < fClosestVisionThreatDistSq)
			{
				fTimeSinceSeen = pxKnowledge->m_fAge;
				fClosestVisionThreatDistSq = fDistanceSq;
				m_xBestThreatKnowledge     = *pxKnowledge;
				iBestPriority = iPriority;
			}
		}
	}

	// Build an array of secondary threats
	if ( ( m_xBestThreatKnowledge.GetGuid() != ASURA_GUID_UNREGISTERED ) && ( uNumEntries > 1 ) )
	{
		BuildSecondaryThreatArray(uNumEntries);
	}
	else
	{
		ClearSecondaryThreatArray();
	}

	// If we have a threat we don't need alert info
	if ( m_xBestThreatKnowledge.GetGuid() != ASURA_GUID_UNREGISTERED
		 && m_xBestThreatKnowledge.m_fAge == 0.0f)
	{
		return;
	}


	// Finds the closest sound to them for both threat sounds and alert sounds
	float fClosestAlertThreatDistSq	= Asura_Maths::LargeFloat;

	// Sound!
	for ( Asura_List_ConstIt< Axon_Knowledge > xHearingIt( m_pxHearing->GetList() ); !xHearingIt.Done(); xHearingIt.Next() )
	{
		const Axon_Knowledge* pxKnowledge = xHearingIt.GetCurrent();	
		
		if (pxKnowledge)
		{

			int iPriority;
			if(!GetActorBrain()->CalcTargetingPriority(pxKnowledge->m_uSourceClassification, pxKnowledge->m_uSourceGuid, iPriority))
			{
				iPriority = AVP_AI_TargetPriorityData::NORMAL;
			}

			if (iPriority <= AVP_AI_TargetPriorityData::IGNORE_P )
			{
				continue;
			}

			switch (pxKnowledge->m_uSourceClassification)
			{
			default:
				continue;
			case AVP_ENTITYCLASS_ALIEN:
			case AVP_ENTITYCLASS_ALIENFACEHUGGER:
			case AVP_ENTITYCLASS_ALIENQUEEN:
			case AVP_ENTITYCLASS_ALIENCHESTBURSTER:
			case AVP_ENTITYCLASS_HUMAN:
			case AVP_ENTITYCLASS_ALIEN_HYBRID:
			case AVP_ENTITYCLASS_ANDROID:
			case AVP_ENTITYCLASS_MARINE:
			case AVP_ENTITYCLASS_CIVILIAN:
			case AVP_ENTITYCLASS_SENTRYGUN:
				break;
			}

			const float fDistanceSq = ( pxKnowledge->m_xPosition - pxOurActor->GetPosition() ).MagnitudeSquared();

			// Pick the closest one
			if ( fDistanceSq < fClosestAlertThreatDistSq )
			{
				fClosestAlertThreatDistSq = fDistanceSq;
				m_xBestAlertKnowledge	  = *pxKnowledge;
			}
		}
	}
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: ClearSecondaryThreatArray
//---------------------------------------------------------------------------

void AVP_Knowledge_System_Predator::ClearSecondaryThreatArray()
{

	m_uNumSecondaryThreats = 0;
	if (m_pxSecondaryThreatKnowledge)
	{
		delete [] m_pxSecondaryThreatKnowledge;
		m_pxSecondaryThreatKnowledge = NULL;
	}

}
//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: BuildSecondaryThreatarray
//---------------------------------------------------------------------------

void AVP_Knowledge_System_Predator::BuildSecondaryThreatArray(u_int uNumEntries)
{
	ClearSecondaryThreatArray();

	if (uNumEntries <= 1)
	{
		Asura_Assert( false, "AVP_Knowledge_System_Predator :: BuildSecondaryThreatArray - there are no secondary threats, shoudln't have been able to get here" );
		return;
	}

	// Clear secondary threat data
	m_pxSecondaryThreatKnowledge = new Axon_Knowledge[uNumEntries - 1];

	// reset the elements of the secondary threat array
	for ( u_int u = 0; u < uNumEntries - 1; ++u )
	{
		m_pxSecondaryThreatKnowledge[u].Reset();
	}

	// do a second iteration now we have found the primary threat
	for ( Asura_Hashed_List_ConstIt< Axon_Knowledge > xVisionIt( m_pxVision->GetList() ); !xVisionIt.Done(); xVisionIt.Next() )
	{
		const Axon_Knowledge* pxKnowledge = xVisionIt.GetCurrent();
		Asura_Assert( pxKnowledge, "AVP_Knowledge_System::UpdateBestKnowledge: invalid vision knowledge" );

		switch (pxKnowledge->m_uSourceClassification)
		{
		default:
			continue;
		case AVP_ENTITYCLASS_ALIEN:
		case AVP_ENTITYCLASS_ALIENFACEHUGGER:
		case AVP_ENTITYCLASS_ALIENQUEEN:
		case AVP_ENTITYCLASS_ALIENCHESTBURSTER:
		case AVP_ENTITYCLASS_HUMAN:
		case AVP_ENTITYCLASS_ALIEN_HYBRID:
		case AVP_ENTITYCLASS_ANDROID:
		case AVP_ENTITYCLASS_MARINE:
		case AVP_ENTITYCLASS_CIVILIAN:
		case AVP_ENTITYCLASS_SENTRYGUN:
			break;
		}

		if ( ( pxKnowledge ) && ( pxKnowledge->GetGuid() != m_xBestThreatKnowledge.GetGuid() ) )
		{
			int iPriority;
			if(!GetActorBrain()->CalcTargetingPriority(pxKnowledge->m_uSourceClassification, pxKnowledge->m_uSourceGuid, iPriority))
			{
				iPriority = AVP_AI_TargetPriorityData::NORMAL;
			}
			if (iPriority > AVP_AI_TargetPriorityData::IGNORE_P)
			{
				m_pxSecondaryThreatKnowledge[m_uNumSecondaryThreats] = *pxKnowledge;
				++m_uNumSecondaryThreats;
			}
		}
	}
}

#ifndef ASURA_NO_DEBUG_OUTPUT
void AVP_Knowledge_System_Predator::RenderDebugInfo()
{
	
}
#endif

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: UpdatePlayerAlienAlertStatus
//---------------------------------------------------------------------------
bool AVP_Knowledge_System_Predator::UpdatePlayerAlienAlertStatus()
{
	for (Asura_Hashed_List_It<AVP_ServerActor_Vertebrate> it(AVP_ServerActor_Vertebrate::GetList()); !it.Done(); it.Next())
	{
		AVP_ServerActor_Vertebrate* pxVertebrate = it.GetCurrent();

		if (pxVertebrate)
		{
			if (pxVertebrate->IsPlayer())
				continue;

			if (!pxVertebrate->GetActorBrain())
				continue;

			if (pxVertebrate->IsDead())
				continue;

			if (pxVertebrate->GetClassification() == AVP_ENTITYCLASS_PREDATOR)
			{
				AVP_Brain_Actor_Predator* pxBrain = (AVP_Brain_Actor_Predator*)pxVertebrate->GetActorBrain();

				if ((pxBrain->GetKnowledgeSystem()->GetBestAlertKnowledge().GetGuid() != ASURA_GUID_UNREGISTERED) &&
					(pxBrain->GetKnowledgeSystem()->GetBestAlertKnowledge().m_uSourceClassification == AVP_ENTITYCLASS_ALIEN))
				{
					AVP_ServerActor_Alien* pxPlayerAlien = AVP_ServerActor_Alien::FindEntity(pxBrain->GetKnowledgeSystem()->GetBestAlertKnowledge().GetGuid());

					if (pxPlayerAlien)
					{
						if (pxPlayerAlien->IsPlayer())
						{
							return true;
						}
						else
						{
							pxPlayerAlien = NULL;
							continue;
						}
					}
				}
				else
				{
					continue;
				}
			}
		}
	}

	return false;
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: AddKnowledgeIfNeeded
//---------------------------------------------------------------------------
void AVP_Knowledge_System_Predator::AddKnowledgeIfNeeded(const Axon_Knowledge& xNewKnowledge)
{
	bool			bAdd = true;

	for (Asura_Hashed_List_ConstIt<Axon_Knowledge> xVisionIt(m_pxVision->GetList()); !xVisionIt.Done(); xVisionIt.Next())
	{
		// Use the closest enemy entity as our threat for now
		const Axon_Knowledge* pxKnowledge = xVisionIt.GetCurrent();

		if (pxKnowledge)
		{
			if (pxKnowledge->GetGuid() == xNewKnowledge.GetGuid())
			{
				bAdd = false;
				break;
			}
		}
	}


	if (bAdd)
	{
		AVP_ServerEntity_Actor* pxServerActor	= GetActorBrain()->GetActor();
		AVP_ServerEntity_Actor*	pxActor			= AVP_ServerEntity_Actor::FindEntity(xNewKnowledge.GetGuid());

		if (pxActor && pxServerActor && !pxServerActor->IsDead() && GetActorBrain()->IsActive())
		{
			Axon_Knowledge*	pxKnowledge	= CreateKnowledge();
			if ( pxKnowledge )
			{
				pxKnowledge->m_uKnowledgeID          = GetNewKnowledgeID();
				pxKnowledge->m_uSourceGuid           = pxActor->GetGuid();
				pxKnowledge->m_uSourceClassification = pxActor->GetClassification();
				pxKnowledge->m_iSenseID              = AXON_SENSE_TYPE_VISION;
				pxKnowledge->m_uTypeInformation      = xNewKnowledge.m_uTypeInformation;
				pxKnowledge->m_fAge                  = xNewKnowledge.m_fAge;
				pxKnowledge->m_fThreatValue          = xNewKnowledge.m_fThreatValue;
				pxKnowledge->m_xPosition             = pxActor->GetPosition();
				pxKnowledge->m_xDirection            = pxActor->GetPosition() - pxServerActor->GetPosition();
				pxKnowledge->m_fDistance             = pxKnowledge->m_xDirection.Normalise();
				
				GetPredatorVision()->AddToVisionList(pxKnowledge);
			}
		}
	}
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: AddKnowledgeIfNeeded
//---------------------------------------------------------------------------
void AVP_Knowledge_System_Predator::AddAlertKnowledgeIfNeeded(const Axon_Knowledge& xNewKnowledge)
{
	bool bAdd = true;

	for (Asura_List_ConstIt<Axon_Knowledge> xHearingIt(m_pxHearing->GetList()); !xHearingIt.Done(); xHearingIt.Next())
	{
		const Axon_Knowledge* pxKnowledge = xHearingIt.GetCurrent();

		if (pxKnowledge)
		{
			if (pxKnowledge->GetGuid() == xNewKnowledge.GetGuid())
			{
				bAdd = false;
				break;
			}
		}
	}

	if (bAdd)
	{
		AVP_ServerEntity_Actor* pxServerActor	= GetActorBrain()->GetActor();
		AVP_ServerEntity_Actor*	pxActor			= AVP_ServerEntity_Actor::FindEntity(xNewKnowledge.GetGuid());

		if (pxActor && pxServerActor && !pxServerActor->IsDead() && GetActorBrain()->IsActive())
		{
			Axon_Knowledge*	pxKnowledge	= CreateKnowledge();
			if ( pxKnowledge )
			{
				pxKnowledge->m_uKnowledgeID          = GetNewKnowledgeID();
				pxKnowledge->m_uSourceGuid           = pxActor->GetGuid();
				pxKnowledge->m_uSourceClassification = pxActor->GetClassification();
				pxKnowledge->m_iSenseID              = AXON_SENSE_TYPE_HEARING;
				pxKnowledge->m_uTypeInformation      = xNewKnowledge.m_uTypeInformation;
				pxKnowledge->m_fAge                  = xNewKnowledge.m_fAge;
				pxKnowledge->m_fThreatValue          = xNewKnowledge.m_fThreatValue;
				pxKnowledge->m_xPosition             = pxActor->GetPosition();
				pxKnowledge->m_xDirection            = pxActor->GetPosition() - pxServerActor->GetPosition();
				pxKnowledge->m_fDistance             = pxKnowledge->m_xDirection.Normalise();

				AVP_Sense_Hearing_Predator* pxHearingSense = static_cast<AVP_Sense_Hearing_Predator*>(m_pxHearing);
				pxHearingSense->AddToHearingList(pxKnowledge);
			}
		}
	}
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: DeleteCurrentAlertKnowledge
//---------------------------------------------------------------------------
void AVP_Knowledge_System_Predator::DeleteCurrentAlertKnowledge( const Asura_Guid uAlertGuid )
{
	for (Asura_List_ConstIt<Axon_Knowledge> xHearingIt(m_pxHearing->GetList()); !xHearingIt.Done(); xHearingIt.Next())
	{
		const Axon_Knowledge* pxKnowledge = xHearingIt.GetCurrent();

		if (pxKnowledge)
		{
			if (pxKnowledge->GetGuid() == uAlertGuid)
			{
				AVP_Sense_Hearing_Predator* pxHearingSense = static_cast<AVP_Sense_Hearing_Predator*>(m_pxHearing);
				if (pxHearingSense)
				{
					pxHearingSense->DeleteFromHearingList(pxKnowledge);
					m_xBestAlertKnowledge.Reset();
				}
				break;
			}
		}
	}
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: GetActorBrain
//---------------------------------------------------------------------------
AVP_Brain_Actor* AVP_Knowledge_System_Predator::GetActorBrain() const
{
	return static_cast< AVP_Brain_Actor* >( GetBrain() );
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: CreateVisionSense
//---------------------------------------------------------------------------
Axon_Sense_Vision* AVP_Knowledge_System_Predator::CreateVisionSense() 
{
	return new AVP_Sense_Vision_Predator(this);
}

//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: createHearingSense
//---------------------------------------------------------------------------
Axon_Sense_Hearing* AVP_Knowledge_System_Predator::CreateHearingSense() 
{
	return new AVP_Sense_Hearing_Predator(this);
}


//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: CanSee, CanSeeNow
//---------------------------------------------------------------------------
const Axon_Knowledge* AVP_Knowledge_System_Predator::CanSee(Asura_Guid uGuid) const
{
	return m_pxVision->GetList()->FindEntity(uGuid);
}

const Axon_Knowledge* AVP_Knowledge_System_Predator::CanSeeNow(Asura_Guid uGuid) const
{
	const Axon_Knowledge* pxKnowledge = m_pxVision->GetList()->FindEntity(uGuid);
	if (pxKnowledge && pxKnowledge->m_fAge == 0.0f)
	{
		return pxKnowledge;
	}

	return NULL;
}


//---------------------------------------------------------------------------
// AVP_Knowledge_System_Predator :: CanHear
//---------------------------------------------------------------------------
// const Axon_Knowledge* AVP_Knowledge_System_Predator::CanHear(Asura_Guid uGuid) const
// {
// 	for (Asura_List_ConstIt<Axon_Knowledge> xHearingIt(m_pxHearing->GetList()); !xHearingIt.Done(); xHearingIt.Next())
// 	{
// 		const Axon_Knowledge* pxKnowledge = xHearingIt.GetCurrent();
// 
// 		if (pxKnowledge && pxKnowledge->GetGuid() == uGuid && pxKnowledge->m_fAge == 0.0f)
// 		{
// 			return pxKnowledge;
// 		}
// 	}
// 
// 	return NULL;
// }


void AVP_Knowledge_System_Predator::SetShootAtTarget( Asura_Guid uGuid, bool bIsShootAtNode )
{
	m_uShootAtGuid = uGuid;
	m_bIsTargetAShootAtNode = bIsShootAtNode;
}

void AVP_Knowledge_System_Predator::ResetShootAtTarget()
{
	m_uShootAtGuid = ASURA_GUID_UNREGISTERED;
	m_bIsTargetAShootAtNode = false;
	m_xBestThreatKnowledge.Reset();
}

bool AVP_Knowledge_System_Predator::IsBestThreatAShootAtNode() const
{
	return m_bIsTargetAShootAtNode;
}
