
// Ironlich -----------------------------------------------------------------

class Ironlich : Actor
{
	Default
	{
		Health 700;
		Radius 40;
		Height 72;
		Mass 325;
		Speed 6;
		Painchance 32;
		Monster;
		+NOBLOOD
		+DONTMORPH
		+DONTSQUASH
		+BOSSDEATH
		SeeSound "ironlich/sight";
		AttackSound "ironlich/attack";
		PainSound "ironlich/pain";
		DeathSound "ironlich/death";
		ActiveSound "ironlich/active";
		Obituary "$OB_IRONLICH";
		HitObituary "$OB_IRONLICHHIT";
		DropItem "BlasterAmmo", 84, 10;
		DropItem "ArtiEgg", 51, 0;
	}

	
	States
	{
	Spawn:
		LICH A 10 A_Look;
		Loop;
	See:
		LICH A 4 A_Chase;
		Loop;
	Missile:
		LICH A 5 A_FaceTarget;
		LICH B 20 A_LichAttack;
		Goto See;
	Pain:
		LICH A 4;
		LICH A 4 A_Pain;
		Goto See;
	Death:
		LICH C 7;
		LICH D 7 A_Scream;
		LICH EF 7;
		LICH G 7 A_NoBlocking;
		LICH H 7;
		LICH I -1 A_BossDeath;
		Stop;
	}
	
	//----------------------------------------------------------------------------
	//
	// PROC A_LichAttack
	//
	//----------------------------------------------------------------------------

	void A_LichAttack ()
	{
		static const int atkResolve1[] = { 50, 150 };
		static const int atkResolve2[] = { 150, 200 };

		// Ice ball		(close 20% : far 60%)
		// Fire column	(close 40% : far 20%)
		// Whirlwind	(close 40% : far 20%)
		// Distance threshold = 8 cells

		if (target == null)
		{
			return;
		}
		A_FaceTarget ();
		if (CheckMeleeRange ())
		{
			int damage = random[LichAttack](1, 8) * 6;
			int newdam = target.DamageMobj (self, self, damage, 'Melee');
			target.TraceBleed (newdam > 0 ? newdam : damage, self);
			return;
		}
		int dist = Distance2D(target) > 8 * 64;
		int randAttack = random[LichAttack]();
		if (randAttack < atkResolve1[dist])
		{ // Ice ball
			SpawnMissile (target, "HeadFX1");
			A_PlaySound ("ironlich/attack2", CHAN_BODY);
		}
		else if (randAttack < atkResolve2[dist])
		{ // Fire column
			Actor baseFire = SpawnMissile (target, "HeadFX3");
			if (baseFire != null)
			{
				baseFire.SetStateLabel("NoGrow");
				for (int i = 0; i < 5; i++)
				{
					Actor fire = Spawn("HeadFX3", baseFire.Pos, ALLOW_REPLACE);
					if (i == 0)
					{
						A_PlaySound ("ironlich/attack1", CHAN_BODY);
					}
					fire.target = baseFire.target;
					fire.angle = baseFire.angle;
					fire.Vel = baseFire.Vel;
					fire.SetDamage(0);
					fire.health = (i+1) * 2;
					fire.CheckMissileSpawn (radius);
				}
			}
		}
		else
		{ // Whirlwind
			Actor mo = SpawnMissile (target, "Whirlwind");
			if (mo != null)
			{
				mo.AddZ(-32);
				mo.tracer = target;
				mo.health = 20*TICRATE; // Duration
				A_PlaySound ("ironlich/attack3", CHAN_BODY);
			}
		}
	}
	
}

// Head FX 1 ----------------------------------------------------------------

class HeadFX1 : Actor
{
	Default
	{
		Radius 12;
		Height 6;
		Speed 13;
		FastSpeed 20;
		Damage 1;
		Projectile;
		-ACTIVATEIMPACT
		-ACTIVATEPCROSS
		+THRUGHOST
		RenderStyle "Add";
	}


	States
	{
	Spawn:
		FX05 ABC 6 BRIGHT;
		Loop;
	Death:
		FX05 D 5 BRIGHT A_LichIceImpact;
		FX05 EFG 5 BRIGHT;
		Stop;
	}
	
	//----------------------------------------------------------------------------
	//
	// PROC A_LichIceImpact
	//
	//----------------------------------------------------------------------------

	void A_LichIceImpact()
	{
		for (int i = 0; i < 8; i++)
		{
			Actor shard = Spawn("HeadFX2", Pos, ALLOW_REPLACE);
			shard.target = target;
			shard.angle = i*45.;
			shard.VelFromAngle();
			shard.Vel.Z = -.6;
			shard.CheckMissileSpawn (radius);
		}
	}
}

// Head FX 2 ----------------------------------------------------------------

class HeadFX2 : Actor
{
	Default
	{
		Radius 12;
		Height 6;
		Speed 8;
		Damage 3;
		Projectile;
		-ACTIVATEIMPACT
		-ACTIVATEPCROSS
		RenderStyle "Add";
	}

	States
	{
	Spawn:
		FX05 HIJ 6 BRIGHT;
		Loop;
	Death:
		FX05 DEFG 5 BRIGHT;
		Stop;
	}
}


// Head FX 3 ----------------------------------------------------------------

class HeadFX3 : Actor
{
	Default
	{
		Radius 14;
		Height 12;
		Speed 10;
		FastSpeed 18;
		Damage 5;
		Projectile;
		+WINDTHRUST	
		-ACTIVATEIMPACT
		-ACTIVATEPCROSS
		-NOBLOCKMAP
		RenderStyle "Add";
	}

	States
	{
	Spawn:
		FX06 ABC 4 BRIGHT A_LichFireGrow;
		Loop;
	NoGrow:
		FX06 ABC 5 BRIGHT;
		Loop;
	Death:
		FX06 DEFG 5 BRIGHT;
		Stop;
	}
	
	//----------------------------------------------------------------------------
	//
	// PROC A_LichFireGrow
	//
	//----------------------------------------------------------------------------

	void A_LichFireGrow ()
	{
		health--;
		AddZ(9.);
		if (health == 0)
		{
			RestoreDamage();
			SetStateLabel("NoGrow");
		}
	}
}


// Whirlwind ----------------------------------------------------------------

class Whirlwind : Actor
{
	Default
	{
		Radius 16;
		Height 74;
		Speed 10;
		Damage 1;
		Projectile;
		-ACTIVATEIMPACT
		-ACTIVATEMCROSS
		+SEEKERMISSILE
		+EXPLOCOUNT
		+StepMissile
		RenderStyle "Translucent";
		DefThreshold 60;
		Threshold 50;
		Alpha 0.4;
	}

	States
	{
	Spawn:
		FX07 DEFG 3;
		FX07 ABC 3 A_WhirlwindSeek;
		Goto Spawn+4;
	Death:
		FX07 GFED 4;
		Stop;
	}
	
	override int DoSpecialDamage (Actor target, int damage, Name damagetype)
	{
		int randVal;

		if (!target.bDontThrust)
		{
			target.angle += Random2[WhirlwindDamage]() * (360 / 4096.);
			target.Vel.X += Random2[WhirlwindDamage]() / 64.;
			target.Vel.Y += Random2[WhirlwindDamage]() / 64.;
		}

		if ((level.time & 16) && !target.bBoss && !target.bDontThrust)
		{
			randVal = min(160, random[WhirlwindSeek]());
			target.Vel.Z += randVal / 32.;
			if (target.Vel.Z > 12)
			{
				target.Vel.Z = 12;
			}
		}
		if (!(level.time & 7))
		{
			target.DamageMobj (null, target, 3, 'Melee');
		}
		return -1;
	}

	//----------------------------------------------------------------------------
	//
	// PROC A_WhirlwindSeek
	//
	//----------------------------------------------------------------------------

	void A_WhirlwindSeek()
	{

		health -= 3;
		if (health < 0)
		{
			Vel = (0,0,0);
			SetStateLabel("Death");
			bMissile = false;
			return;
		}
		if ((threshold -= 3) < 0)
		{
			threshold = 58 + (random[WhirlwindSeek]() & 31);
			A_PlaySound("ironlich/attack3", CHAN_BODY);
		}
		if (tracer && tracer.bShadow)
		{
			return;
		}
		A_SeekerMissile(10, 30);
	}
	
}



