// Afraid of Monsters: Director's Cut Script
// Monster Script: Ghost
// Author: Zorbos

namespace AOMGhost
{
// Monster events
const int GHOST_AE_ATTACK = 1;

// Behavior modifiers
const float GHOST_MOD_HEALTH = 150.0;
const float GHOST_MOD_MOVESPEED = 325.0;
const int GHOST_MOD_DMG_INIT = 2; // Initial damage
const int GHOST_MOD_DMG_TICK = 3; // Damage per DoT tick

const float GHOST_MOD_HEALTH_SURVIVAL = 225.0;
const float GHOST_MOD_MOVESPEED_SURVIVAL = 400.0;
const int GHOST_MOD_DMG_INIT_SURVIVAL = 5; // Initial damage
const int GHOST_MOD_DMG_TICK_SURVIVAL = 4; // Damage per DoT tick

class CMonsterGhost : ScriptBaseMonsterEntity
{
	private float m_flNextAttack = 0;
	private float m_flDmgInit, m_flDmgTick;
	private bool bSurvivalEnabled = g_EngineFuncs.CVarGetFloat("mp_survival_starton") == 1 && g_EngineFuncs.CVarGetFloat("mp_survival_supported") == 1;
	CScheduledFunction@ interval;
	
	void Precache()
	{
		BaseClass.Precache();

		g_Game.PrecacheModel("models/aomdc/monsters/ghost/ghost.mdl");

		g_SoundSystem.PrecacheSound("aomdc/monsters/ghost/ear_ringing.wav");
		g_SoundSystem.PrecacheSound("aomdc/monsters/ghost/slv_alert2.wav");
		g_SoundSystem.PrecacheSound("aomdc/monsters/ghost/slv_die.wav");
	}
	
	void Spawn()
	{
		Precache();

		if( !self.SetupModel() )
			g_EntityFuncs.SetModel( self, "models/aomdc/monsters/ghost/ghost.mdl" );
			
		g_EntityFuncs.SetSize( self.pev, VEC_HUMAN_HULL_MIN, VEC_HUMAN_HULL_MAX );
	
		if(bSurvivalEnabled)
			self.pev.health = GHOST_MOD_HEALTH_SURVIVAL;
		else
			self.pev.health = GHOST_MOD_HEALTH;
	
		pev.solid					= SOLID_SLIDEBOX;
		pev.movetype				= MOVETYPE_STEP;
		self.m_bloodColor			= BLOOD_COLOR_RED;
		self.pev.health				= GHOST_MOD_HEALTH;
		self.pev.view_ofs			= Vector( 0, 0, 80 );
		self.m_flFieldOfView		= 0.8;
		self.m_MonsterState			= MONSTERSTATE_NONE;
		self.m_afCapability			= bits_CAP_DOORS_GROUP;
		
		self.m_FormattedName		= "Ghost";

		self.MonsterInit();
	}
	
	int	Classify()
	{
		return self.GetClassification( CLASS_ALIEN_MONSTER );
	}
	
	void SetYawSpeed()
	{
		if(bSurvivalEnabled)
			self.pev.yaw_speed = GHOST_MOD_MOVESPEED_SURVIVAL;
		else
			self.pev.yaw_speed = GHOST_MOD_MOVESPEED;
	}
	
	void DeathSound()
	{
		g_SoundSystem.EmitSoundDyn( self.edict(), CHAN_VOICE, "aomdc/monsters/ghost/slv_die.wav", 1, ATTN_NORM, 0, PITCH_NORM );
	}
	
	void Killed(entvars_t@ pevAttacker, int iGib)
	{
		BaseClass.Killed(pevAttacker, iGib);
	}
	
	void AlertSound()
	{	
		g_SoundSystem.EmitSoundDyn( self.edict(), CHAN_VOICE, "aomdc/monsters/ghost/slv_alert2.wav", 1, ATTN_NORM, 0, PITCH_NORM );
	
	}
	
	int TakeDamage( entvars_t@ pevInflictor, entvars_t@ pevAttacker, float flDamage, int bitsDamageType)
	{	
		if(pevAttacker is null)
			return 0;

		CBaseEntity@ pAttacker = g_EntityFuncs.Instance( pevAttacker );

		if(self.CheckAttacker( pAttacker ))
			return 0;

		return BaseClass.TakeDamage(pevInflictor, pevAttacker, flDamage, bitsDamageType);
	}
	
	CBaseEntity@ initAttack()
	{
		TraceResult tr;

		Math.MakeVectors(pev.angles);
		Vector vecStart = pev.origin;
		vecStart.z += pev.size.z * 0.5;
		Vector vecEnd = vecStart + (g_Engine.v_forward * 64);

		g_Utility.TraceHull(vecStart, vecEnd, dont_ignore_monsters, head_hull, self.edict(), tr);
		
		if(tr.pHit !is null)
		{
			CBaseEntity@ pEntity = g_EntityFuncs.Instance(tr.pHit);
			return pEntity;
		}

		return null;
	}	
	
	bool CheckMeleeAttack1( float flDot, float flDist )
	{
		CBaseMonster@ pEnemy;

		if(self.m_hEnemy.IsValid())
		{
			@pEnemy = self.m_hEnemy.GetEntity().MyMonsterPointer();

			if (pEnemy is null)
				return false;
		}

		if(flDist <= 64 && flDot >= 0.7)
			return true;
			
		return false;
	}
	
	bool CheckRangeAttack1(float flDot, float flDist)
	{	
		return false;
	}
	
	bool CheckRangeAttack2(float flDot, float flDist)
	{	
		return false;
	}
	
	void RingEars(CBasePlayer@ pPlayer)
	{	
		g_SoundSystem.PlaySound(pPlayer.edict(), CHAN_STATIC, "aomdc/monsters/ghost/ear_ringing.wav", 0.65f, 1.0f, 0, 100, pPlayer.entindex());
		g_PlayerFuncs.ScreenFade(pPlayer, Vector(150, 0, 0), 2, 12, 255, FFADE_MODULATE | FFADE_IN);
	}
	
	void RingEarsTick(CBasePlayer@ pPlayer)
	{
		if(bSurvivalEnabled)
			m_flDmgTick = GHOST_MOD_DMG_TICK_SURVIVAL;
		else
			m_flDmgTick = GHOST_MOD_DMG_TICK;
			
		pPlayer.TakeDamage(pev, pev, m_flDmgTick, DMG_CLUB);
	}
	
	void HandleAnimEvent(MonsterEvent@ pEvent)
	{
		if(g_Engine.time < m_flNextAttack)
			return;
			
		if(pEvent.event == GHOST_AE_ATTACK)
		{
			CBaseEntity@ pHurt = initAttack();
			CBasePlayer@ pPlayer = cast<CBasePlayer@>(pHurt);
			
			if (pPlayer !is null)
			{
				if(bSurvivalEnabled)
					m_flDmgInit = GHOST_MOD_DMG_INIT_SURVIVAL;
				else
					m_flDmgInit = GHOST_MOD_DMG_INIT;
					
				Math.MakeVectors(pev.angles);
				pPlayer.pev.punchangle.x = 20;
				pPlayer.TakeDamage(pev, pev, m_flDmgInit, DMG_CLUB);
				@interval = g_Scheduler.SetInterval(@this, "RingEarsTick", 2, 6, @pPlayer);
				
				m_flNextAttack = g_Engine.time + 13;
				RingEars(pPlayer);	
			}
		}
		else
			BaseClass.HandleAnimEvent(pEvent);
	}
}

void Register()
{
	g_CustomEntityFuncs.RegisterCustomEntity( "AOMGhost::CMonsterGhost", "monster_ghost" );
}
} // end namespace