//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Giant walking strider thing!
//
// $NoKeywords: $
//=============================================================================//

#include "cbase.h"

#include "hlw_npc_strider.h"

#include "hl2wars/rts_point_order.h"
#include "hl2wars/rts_globalresource.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

extern ConVar strider_idle_test;


//-----------------------------------------------------------------------------
//
// CHLW_NPC_Strider
//
//-----------------------------------------------------------------------------

//IMPLEMENT_SERVERCLASS_ST(CHLW_NPC_Strider, DT_HLW_NPC_Strider)
//END_SEND_TABLE()

//-------------------------------------

LINK_ENTITY_TO_CLASS( hlw_npc_strider, CHLW_NPC_Strider );

//-------------------------------------

BEGIN_DATADESC( CHLW_NPC_Strider )
END_DATADESC()


//---------------------------------------------------------
//---------------------------------------------------------
CHLW_NPC_Strider::CHLW_NPC_Strider()
{
}

//---------------------------------------------------------
//---------------------------------------------------------
CHLW_NPC_Strider::~CHLW_NPC_Strider()
{
}

//---------------------------------------------------------
//---------------------------------------------------------
void CHLW_NPC_Strider::Spawn()
{
	BaseClass::Spawn();

	CapabilitiesAdd( bits_CAP_NO_HIT_PLAYER | bits_CAP_NO_HIT_SQUADMATES | bits_CAP_FRIENDLY_DMG_IMMUNE );
	m_flDistTooFar = 500.0f * 4.0f;
}

//---------------------------------------------------------
//---------------------------------------------------------
int CHLW_NPC_Strider::SelectSchedule()
{
	// First, check abilities
	if( GetCurrentOrder() )
	{
		if( GetCurrentOrder()->GetOrderType() == ORDER_DO_ABILITY && GetCurrentOrder()->GetAbility() != ABILITY_NONE )
		{
			if( !HasCondition(COND_CAN_DO_ABILITY) ) 
			{
				if( HasCondition(COND_TOO_CLOSE_FOR_ABILITY) || HasCondition(COND_TOO_FAR_FOR_ABILITY) ) 
				{
					return SCHED_MOVE_TO_ABILITY_RANGE;
				}
			}

			m_iActiveAbilityButton = GetCurrentOrder()->GetAbilityButton();
			
			if( GetCurrentOrder()->GetAbility() == ABILITY_STRIDER_CANNON )
			{
				//return SCHED_STRIDER_RANGE_ATTACK2;
				m_AttemptCannonLOSTimer.Force();
				if( GetCurrentOrder()->GetTarget() )
					m_hCannonTarget = GetCurrentOrder()->GetTarget();
				else
					m_hCannonTarget = GetCurrentOrder();
			}
		}
	}
/*
	if( GetMoveType() != MOVETYPE_FLY )
	{
		// Dropship just released me.
		SetMoveType( MOVETYPE_FLY );
		return SCHED_STRIDER_FALL_TO_GROUND;
	}
*/
	if ( strider_idle_test.GetBool() )
	{
		m_pMinigun->Enable( this, false );
		return SCHED_IDLE_STAND;
	}
	else
	{
		m_pMinigun->Enable( this, true );
	}

	if( m_NPCState == NPC_STATE_SCRIPT )
		return BaseClass::SelectSchedule();

	// If we're starting to die, then just wait for this to happen
	if ( m_lifeState == LIFE_DYING )
		return SCHED_IDLE_STAND;

	if( m_NPCState == NPC_STATE_DEAD )
		return SCHED_STRIDER_DIE;

	if( HasPendingTargetPath() )
	{
#if 0
		if( IsInCrouchedPosture() && !m_bCrouchLocked )
		{
			// Make the strider stand!
			return SCHED_STRIDER_STAND;
		}
		else
		{
			SetTargetPath();
		}
#else
		SetTargetPath();
#endif
	}

	//---------------------------------

	if( HasCondition( COND_STRIDER_SHOULD_CROUCH ) && GetHeight() - GetMinHeight() > GetHeightRange() * .5 )
	{
		return SCHED_STRIDER_CROUCH;
	}
	if( HasCondition( COND_STRIDER_SHOULD_STAND ) && !m_bCrouchLocked  && GetHeight() - GetMinHeight() < GetHeightRange() * .5 )
	{
		return SCHED_STRIDER_STAND;
	}

	if( HasCondition( COND_CAN_RANGE_ATTACK2 ) )
	{
		return SCHED_STRIDER_RANGE_ATTACK2;
	}
	else if( m_AttemptCannonLOSTimer.Expired() && HasCondition( COND_STRIDER_HAS_CANNON_TARGET ) )
	{
		m_AttemptCannonLOSTimer.Set( 5 );
		return SCHED_STRIDER_ESTABLISH_LINE_OF_FIRE_CANNON;
	}

	//---------------------------------

	if( m_NPCState == NPC_STATE_COMBAT )
	{
		if ( !HasCondition( COND_NEW_ENEMY ) )
		{
			if ( m_hRagdoll.Get() && (gpGlobals->curtime > m_ragdollTime  || HasCondition( COND_STRIDER_DO_FLICK ) ) )
			{
				return SCHED_STRIDER_FLICKL;
			}
		}

		if ( HasCondition( COND_STRIDER_SHOULD_CROUCH ) )
		{
			return SCHED_STRIDER_CROUCH;
		}

		if ( HasCondition( COND_STRIDER_SHOULD_STAND ) )
		{
			return SCHED_STRIDER_STAND;
		}
		
		if ( HasCondition( COND_CAN_MELEE_ATTACK1 ) )
		{
			return SCHED_MELEE_ATTACK1;
		}
		if ( HasCondition( COND_CAN_RANGE_ATTACK1 ) )
		{
			return SCHED_STRIDER_RANGE_ATTACK1;
		}

		ClearCondition( COND_STRIDER_ENEMY_UPDATED );
		if ( !m_EnemyUpdatedTimer.Expired() )
		{
			int baseResult = BaseClass::SelectSchedule();
			if ( baseResult != SCHED_COMBAT_FACE || !GetGoalEnt() )
				return baseResult;
		}

		if ( !GetGoalEnt() )
			return BaseClass::SelectSchedule();

		return SCHED_STRIDER_HUNT;
	}

	//---------------------------------
	return CAI_BaseNPC::SelectSchedule();
}

//---------------------------------------------------------
//---------------------------------------------------------
void CHLW_NPC_Strider::StartTask( const Task_t *pTask )
{
	switch ( pTask->iTask )
	{

	case TASK_STRIDER_FIRE_CANNON:
		if( !AbilityTakeResources() ) 
		{
			TaskFail( NO_TASK_FAILURE );
			break;
		}
		FireCannon();
		AbilityCompleted();
		TaskComplete();
		break;

	default:
		BaseClass::StartTask( pTask );
		break;
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHLW_NPC_Strider::Event_Killed( const CTakeDamageInfo &info )
{
	return BaseClass::Event_Killed(info);
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int	CHLW_NPC_Strider::OnTakeDamage_Alive( const CTakeDamageInfo &info )
{
	return BaseClass::OnTakeDamage_Alive(info);
}

//-----------------------------------------------------------------------------
// Purpose: Strider is always UNIT_STRIDER
//-----------------------------------------------------------------------------
void CHLW_NPC_Strider::InitUnitIndex()
{
	const char *m_sUnitType;
	m_sUnitType = "UNIT_STRIDER";
	m_iUnitIndex = g_pRTSResource->GetUnitIndex( m_sUnitType );
}
