#include "actor.h"
#include "info.h"
#include "p_local.h"
#include "s_sound.h"
#include "p_enemy.h"
#include "a_action.h"
#include "m_random.h"

static FRandom pr_ettinatk ("EttinAttack");
static FRandom pr_dropmace ("DropMace");

// Ettin --------------------------------------------------------------------

void A_EttinAttack (AActor *);
void A_DropMace (AActor *);

class AEttin : public AActor
{
	DECLARE_ACTOR (AEttin, AActor)
public:
	void Howl ();
};

FState AEttin::States[] =
{
#define S_ETTIN_LOOK 0
	S_NORMAL (ETTN, 'A',   10, A_Look					, &States[S_ETTIN_LOOK+1]),
	S_NORMAL (ETTN, 'A',   10, A_Look					, &States[S_ETTIN_LOOK+0]),

#define S_ETTIN_CHASE (S_ETTIN_LOOK+2)
	S_NORMAL (ETTN, 'A',	5, A_Chase					, &States[S_ETTIN_CHASE+1]),
	S_NORMAL (ETTN, 'B',	5, A_Chase					, &States[S_ETTIN_CHASE+2]),
	S_NORMAL (ETTN, 'C',	5, A_Chase					, &States[S_ETTIN_CHASE+3]),
	S_NORMAL (ETTN, 'D',	5, A_Chase					, &States[S_ETTIN_CHASE+0]),

#define S_ETTIN_PAIN (S_ETTIN_CHASE+4)
	S_NORMAL (ETTN, 'H',	7, A_Pain					, &States[S_ETTIN_CHASE+0]),

#define S_ETTIN_ATK1 (S_ETTIN_PAIN+1)
	S_NORMAL (ETTN, 'E',	6, A_FaceTarget 			, &States[S_ETTIN_ATK1+1]),
	S_NORMAL (ETTN, 'F',	6, A_FaceTarget 			, &States[S_ETTIN_ATK1+2]),
	S_NORMAL (ETTN, 'G',	8, A_EttinAttack			, &States[S_ETTIN_CHASE+0]),

#define S_ETTIN_DEATH1 (S_ETTIN_ATK1+3)
	S_NORMAL (ETTN, 'I',	4, NULL 					, &States[S_ETTIN_DEATH1+1]),
	S_NORMAL (ETTN, 'J',	4, NULL 					, &States[S_ETTIN_DEATH1+2]),
	S_NORMAL (ETTN, 'K',	4, A_Scream 				, &States[S_ETTIN_DEATH1+3]),
	S_NORMAL (ETTN, 'L',	4, A_NoBlocking 			, &States[S_ETTIN_DEATH1+4]),
	S_NORMAL (ETTN, 'M',	4, A_QueueCorpse			, &States[S_ETTIN_DEATH1+5]),
	S_NORMAL (ETTN, 'N',	4, NULL 					, &States[S_ETTIN_DEATH1+6]),
	S_NORMAL (ETTN, 'O',	4, NULL 					, &States[S_ETTIN_DEATH1+7]),
	S_NORMAL (ETTN, 'P',	4, NULL 					, &States[S_ETTIN_DEATH1+8]),
	S_NORMAL (ETTN, 'Q',   -1, NULL 					, NULL),

#define S_ETTIN_DEATH2 (S_ETTIN_DEATH1+9)
	S_NORMAL (ETTB, 'A',	4, NULL 					, &States[S_ETTIN_DEATH2+1]),
	S_NORMAL (ETTB, 'B',	4, A_NoBlocking 			, &States[S_ETTIN_DEATH2+2]),
	S_NORMAL (ETTB, 'C',	4, A_DropMace				, &States[S_ETTIN_DEATH2+3]),
	S_NORMAL (ETTB, 'D',	4, A_Scream 				, &States[S_ETTIN_DEATH2+4]),
	S_NORMAL (ETTB, 'E',	4, A_QueueCorpse			, &States[S_ETTIN_DEATH2+5]),
	S_NORMAL (ETTB, 'F',	4, NULL 					, &States[S_ETTIN_DEATH2+6]),
	S_NORMAL (ETTB, 'G',	4, NULL 					, &States[S_ETTIN_DEATH2+7]),
	S_NORMAL (ETTB, 'H',	4, NULL 					, &States[S_ETTIN_DEATH2+8]),
	S_NORMAL (ETTB, 'I',	4, NULL 					, &States[S_ETTIN_DEATH2+9]),
	S_NORMAL (ETTB, 'J',	4, NULL 					, &States[S_ETTIN_DEATH2+10]),
	S_NORMAL (ETTB, 'K',	4, NULL 					, &States[S_ETTIN_DEATH2+11]),
	S_NORMAL (ETTB, 'L',   -1, NULL 					, NULL),

#define S_ETTIN_ICE (S_ETTIN_DEATH2+12)
	S_NORMAL (ETTN, 'R',	5, A_FreezeDeath			, &States[S_ETTIN_ICE+1]),
	S_NORMAL (ETTN, 'R',	1, A_FreezeDeathChunks		, &States[S_ETTIN_ICE+1])
};
IMPLEMENT_ACTOR (AEttin, Hexen, 10030, 4)
	PROP_SpawnHealth (175)
	PROP_RadiusFixed (25)
	PROP_HeightFixed (68)
	PROP_Mass (175)
	PROP_SpeedFixed (13)
	PROP_Damage (3)
	PROP_PainChance (60)
	PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_COUNTKILL)
	PROP_Flags2 (MF2_FLOORCLIP|MF2_PUSHWALL|MF2_MCROSS|MF2_TELESTOMP)

	PROP_SpawnState (S_ETTIN_LOOK)
	PROP_SeeState (S_ETTIN_CHASE)
	PROP_PainState (S_ETTIN_PAIN)
	PROP_MeleeState (S_ETTIN_ATK1)
	PROP_DeathState (S_ETTIN_DEATH1)
	PROP_XDeathState (S_ETTIN_DEATH2)
	PROP_IDeathState (S_ETTIN_ICE)

	PROP_SeeSound ("EttinSight")
	PROP_AttackSound ("EttinAttack")
	PROP_PainSound ("EttinPain")
	PROP_DeathSound ("EttinDeath")
	PROP_ActiveSound ("EttinActive")
END_DEFAULTS

void AEttin::Howl ()
{
	int howl = S_FindSound ("PuppyBeat");
	if (!S_GetSoundPlayingInfo (this, howl))
	{
		S_SoundID (this, CHAN_BODY, howl, 1, ATTN_NORM);
	}
}

// Ettin mace ---------------------------------------------------------------

class AEttinMace : public AActor
{
	DECLARE_ACTOR (AEttinMace, AActor)
};

FState AEttinMace::States[] =
{
	S_NORMAL (ETTB, 'M',	5, NULL 					, &States[1]),
	S_NORMAL (ETTB, 'N',	5, NULL 					, &States[2]),
	S_NORMAL (ETTB, 'O',	5, NULL 					, &States[3]),
	S_NORMAL (ETTB, 'P',	5, NULL 					, &States[0]),

	S_NORMAL (ETTB, 'Q',	5, NULL 					, &States[5]),
	S_NORMAL (ETTB, 'R',	5, A_QueueCorpse			, &States[6]),
	S_NORMAL (ETTB, 'S',   -1, NULL 					, NULL)
};

IMPLEMENT_ACTOR (AEttinMace, Hexen, -1, 0)
	PROP_RadiusFixed (5)
	PROP_HeightFixed (5)
	PROP_Flags (MF_DROPOFF|MF_CORPSE)
	PROP_Flags2 (MF2_NOTELEPORT|MF2_FLOORCLIP)

	PROP_SpawnState (0)
	PROP_CrashState (4)
END_DEFAULTS

// Ettin mash ---------------------------------------------------------------

class AEttinMash : public AEttin
{
	DECLARE_STATELESS_ACTOR (AEttinMash, AEttin)
};

IMPLEMENT_STATELESS_ACTOR (AEttinMash, Hexen, -1, 102)
	PROP_FlagsSet (MF_NOBLOOD)
	PROP_Flags2Set (MF2_FLOORCLIP|MF2_PASSMOBJ|MF2_MCROSS|MF2_PUSHWALL|MF2_BLASTED)
	PROP_RenderStyle (STYLE_Translucent)
	PROP_Alpha (HX_ALTSHADOW)

	PROP_DeathState (~0)
	PROP_XDeathState (~0)
	PROP_IDeathState (~0)
END_DEFAULTS

//============================================================================
// Ettin AI
//============================================================================

void A_EttinAttack (AActor *actor)
{
	if (actor->CheckMeleeRange())
	{
		int damage = pr_ettinatk.HitDice (2);
		P_DamageMobj (actor->target, actor, actor, damage, MOD_HIT);
		P_TraceBleed (damage, actor->target, actor);
	}
}


void A_DropMace (AActor *actor)
{
	AEttinMace *mo;

	mo = Spawn<AEttinMace> (actor->x, actor->y,
		actor->z + (actor->height>>1));
	if (mo)
	{
		mo->momx = (pr_dropmace()-128) << 11;
		mo->momy = (pr_dropmace()-128) << 11;
		mo->momz = FRACUNIT*10+(pr_dropmace()<<10);
		mo->target = actor;
	}
}

