//All frames in this monster are replaced with fading versions to create a neato visual effect
//Technically I could use the method I used for the summons to create this effect, but it would change the appearance of the monster subtly so I won't
class BabelArchvile : BabelMonster Replaces Archvile
{
	default
	{
		Health 700;
		Radius 20;
		Height 56;
		Mass 500;
		Speed 15;
		PainChance 10;
		Monster;
		MaxTargetRange 896;
		+QUICKTORETALIATE;
		+NOTARGET;
		SeeSound "vile/sight";
		PainSound "vile/pain";
		DeathSound "vile/death";
		ActiveSound "vile/active";
		MeleeSound "vile/stop";
		Obituary "$OB_VILE";
		RenderStyle "Translucent";
		Alpha 0.01; //wouldn't you know it the fucking BFG can't actually see invisible things
		Species "Wraith";
		PainChance "PlayerPistol", 15;
		DamageType "Monster";
		Tag "Arch-vile (Babel)";
	}
	int summonCounter;
	override void BeginPlay()
	{
		super.BeginPlay();
		summonCounter = 6; //summon 6 guys max, may increase later but 6 is still quite a lot
	}
	override void Tick()
	{
		super.Tick();
		//Just make sure that counter never goes out of range
		if(summonCounter > 6)
		{
			summonCounter = 6;
		}
		else if (summonCounter < 0)
		{
			summonCounter = 0;
		}
	}
	
	//--A series of functions to make the ZScript look less awful in some parts
	action void A_VileGhost(float fadeRate = 0.028)
	{
		bool s = false;
		Actor a = null;
		[s, a] = A_SpawnItemEx("VileFrameUniversal", 0,0,0, 0,0,0, 0, SXF_TRANSFERSPRITEFRAME);
		if(s)
		{
			VileFrameUniversal(a).fadeRate = fadeRate;
		}
	}
	
	action void A_GhostLook(float fadeRate = 0.028)
	{
		A_VileGhost(fadeRate);
		A_Look();
	}
	
	action void A_GhostChase(float fadeRate = 0.028)
	{
		A_VileGhost(fadeRate);
		A_VileChase();
	}
	
	action void A_GhostStart(float fadeRate = 0.028)
	{
		A_VileGhost(fadeRate);
		A_VileStart();
	}
	
	action void A_GhostFaceTarget(float fadeRate = 0.028)
	{
		A_VileGhost(fadeRate);
		A_FaceTarget();
	}
	
	action void A_GhostTarget(float fadeRate = 0.028)
	{
		A_VileGhost(fadeRate);
		A_VileTarget();
	}
	//-----------------------------------------------------
	
	States
	{
	Spawn:
		VILE AB 10 A_GhostLook();
		Loop;
	See:
		VILE AABBCCDDEEFF 2 A_GhostChase();
		Loop;
	Missile:
		TNT1 A 0 
		{
			if(summonCounter > 0)
			{
				if(random(0, 3) == 0)
				{
					return ResolveState("Summon");
				}
			}
			return ResolveState(null);
		}
	MissileNoSummon:
		VILE G 0 Bright A_GhostStart();
		VILE GGGGG 2 Bright A_GhostFaceTarget();
		VILE H 8 Bright A_GhostTarget();
		VILE IIIIJJJJKKKKLLLLMMMMNNNN 2 Bright A_GhostFaceTarget();
		VILE O 2 Bright
		{
			A_VileGhost();
			A_VileTarget("VileExplosionFire");
			A_VileAttack();
		}
		VILE OOO 2 Bright A_VileGhost();
		VILE P 20 Bright A_VileGhost(0.02);
		Goto See;
	Heal:
		VILE [[[[[\\\\\]]]]] 2 Bright A_VileGhost();
		Goto See;
	Summon:
		TNT1 A 0 JumpIfCannotSee("See");
		TNT1 A 0 
		{
			if(summonCounter <= 0)
			{
				return ResolveState("MissileNoSummon"); //to prevent churning, we won't re-roll our summon chance
				//We should end up here anyway but still
			}
			return ResolveState(null);
		}
		VILE [[[[[\\\\\]]]]] 2 Bright A_VileGhost();
		TNT1 A 0 
		{
			for(int i = 0; i < 3; i++)
			{
				if(summonCounter > 0)
				{
					A_SpawnItemEx("Spawner", 0,0,0, 0,0,0, 0, SXF_SETMASTER);
					summonCounter -= 1;
				}
				else
				{
					break;
				}
			}
		}
		VILE "]" 2 Bright A_VileGhost();
		Goto See;
	Pain:
		VILE Q 5 A_VileGhost();
		VILE Q 5 
		{
			A_VileGhost();
			A_BabelPain();
		}
		Goto See;
	Death:
		TNT1 A 0 ScareOthers("BabelMonster", random(800,1500));
		TNT1 A 0 A_Jump(192, "Death.Monster");
		TNT1 A 0 
		{
			TriggerSync("BabelDemon", 85.0);
			TriggerSync("BabelImp", 85.0);
			TriggerSync("BabelZombieMan", 40.0);
			TriggerSync("BabelChaingunGuy", 40.0);
			TriggerSync("BabelShotgunGuy", 40.0);
			TriggerSync("BabelNazi", 75.0);
			TriggerSync("BabelBaronOfHell", 40.0);
			TriggerSync("BabelHellKnight", 80.0);
			TriggerDodge(); //Cacodemon
			
			TriggerChain("BabelRevenant", 25.0);
			TriggerChain("BabelFatso", 25.0);
		}
	Death.Monster:
	Death.Massacre:
		TNT1 A 0;
		VILE Q 7 
		{
			A_SpawnItemEx("VileDeathAnim");
			A_VileGhost();
		}
		VILE R 7 
		{
			A_VileGhost();
			A_Scream();
		}
		VILE S 7 
		{
			A_VileGhost();
			A_NoBlocking();
		}
		//-------------------------------------
		VILE T 7;
		VILE U 7;
		VILE V 7;
		VILE W 7;
		VILE X 7;
		VILE Y 7;
		//-------------------------------------
		VILE Z 1;
		Stop; //remove entirely
	}
}

class VileExplosionFire : Actor
{
	states
	{
		Spawn:
			TNT1 A 0 Nodelay A_JumpIf(CVar.FindCVar("egr_particle_toggle").GetInt() == 0, "Done");
			TNT1 AAAAAAAAAAAAAAAAAAAA 0 A_SpawnParticle (0xffaa00, SPF_FULLBRIGHT, random(25,35), random(2,4), 0, frandom(-8.0, 8.0), frandom(-8.0, 8.0), frandom(0.0, 32.0)+4,  frandom(-6.0, 6.0), frandom(-6.0, 6.0), frandom(3.0, 5.0),  0,0,0.1, 0.7, -1);
			TNT1 AAAAAAAAAAAAAAAAAAAA 0 A_SpawnParticle (0xffcc00, SPF_FULLBRIGHT, random(25,35), random(2,4), 0, frandom(-8.0, 8.0), frandom(-8.0, 8.0), frandom(0.0, 32.0)+4,  frandom(-6.0, 6.0), frandom(-6.0, 6.0), frandom(3.0, 5.0),  0,0,0.1, 0.7, -1);
			TNT1 AAAAAAAAAAAAAAAAAAAA 0 A_SpawnParticle (0xffff22, SPF_FULLBRIGHT, random(25,35), random(2,4), 0, frandom(-8.0, 8.0), frandom(-8.0, 8.0), frandom(0.0, 32.0)+4,  frandom(-6.0, 6.0), frandom(-6.0, 6.0), frandom(3.0, 5.0),  0,0,0.1, 0.7, -1);
		Done:
			TNT1 A 0;
			stop;
	}
}

class ParticleArchvileFire : ArchvileFire Replaces ArchvileFire
{
	int lifetime;
	int angle;
	int displacement;
	bool particles;
	default
	{
		+NOBLOCKMAP;
		+NOGRAVITY;
		RenderStyle "Add";
		Alpha 1;
		DamageType "Monster";
	}
	override void BeginPlay()
	{
		super.BeginPlay();
		particles = bool(CVar.FindCVar("egr_particle_toggle").GetInt());
	}
	override void Tick()
	{
		super.Tick();
		lifetime = random(25, 40);
		angle = random(0, 359);
		displacement = random(20, 40);
		if(particles)
		{
			A_SpawnParticle (0xffaa00, SPF_FULLBRIGHT, lifetime, random(2,4), 0, displacement*cos(angle), displacement*sin(angle), frandom(0.0, 32.0)+4,	-1*displacement*cos(angle)/lifetime, -1*displacement*sin(angle)/lifetime, frandom(3.0, 5.0),	-(displacement*cos(angle)/lifetime)/lifetime, -(displacement*sin(angle)/lifetime)/lifetime, 0.1, 0.7, -1);
			A_SpawnParticle (0xffcc00, SPF_FULLBRIGHT, lifetime, random(2,4), 0, displacement*cos(angle), displacement*sin(angle), frandom(0.0, 32.0)+4,	-1*displacement*cos(angle)/lifetime, -1*displacement*sin(angle)/lifetime, frandom(3.0, 5.0),	-(displacement*cos(angle)/lifetime)/lifetime, -(displacement*sin(angle)/lifetime)/lifetime, 0.1, 0.7, -1);
			A_SpawnParticle (0xffff22, SPF_FULLBRIGHT, lifetime, random(2,4), 0, displacement*cos(angle), displacement*sin(angle), frandom(0.0, 32.0)+4,	-1*displacement*cos(angle)/lifetime, -1*displacement*sin(angle)/lifetime, frandom(3.0, 5.0),	-(displacement*cos(angle)/lifetime)/lifetime, -(displacement*sin(angle)/lifetime)/lifetime, 0.1, 0.7, -1);
		}
	}
	
	States
	{
	Spawn:
		FIRE A 2 Bright A_StartFire;
		FIRE BAB 2 Bright A_Fire;
		FIRE C 2 Bright A_FireCrackle;
		FIRE BCBCDCDCDEDED 2 Bright A_Fire;
		FIRE E 2 Bright A_FireCrackle;
		FIRE FEFEFGHGHGH 2 Bright A_Fire;
		Stop;
	}
}

class Spawner : Actor
{
	bool particles;
	default
	{
		Monster;
		Speed 10;
		Radius 20;
		Height 56;
		+LOOKALLAROUND;
		+THRUACTORS;
		-CountKill;
		RenderStyle "Translucent";
		Scale 0.4;
	}
	override void BeginPlay()
	{
		super.BeginPlay();
		particles = bool(CVar.FindCVar("egr_particle_toggle").GetInt());
	}
	//Could this be done better? Yes. Will I do it better? Not right now.
	action void A_SpawnerWander()
	{
		invoker.A_Wander();
		if(invoker.particles)
		{
			
			invoker.A_SpawnParticle (0xffaa00, SPF_FULLBRIGHT, random(25,35), random(6,7), 0, frandom(-3.0, 3.0),frandom(-3.0, 3.0),frandom(-3.0, 3.0),  frandom(-1.0, 1.0),frandom(-1.0, 1.0),frandom(2.0, 5.0),  0,0,0.1, 0.7, -1);
			invoker.A_SpawnParticle (0xffcc00, SPF_FULLBRIGHT, random(25,35), random(6,9), 0, frandom(-3.0, 3.0),frandom(-3.0, 3.0),frandom(-3.0, 3.0),  frandom(-1.0, 1.0),frandom(-1.0, 1.0),frandom(2.0, 5.0),  0,0,0.1, 0.7, -1);
		}
		invoker.A_Wander();
		if(invoker.particles)
		{
			invoker.A_SpawnParticle (0xffaa00, SPF_FULLBRIGHT, random(25,35), random(6,7), 0, frandom(-3.0, 3.0),frandom(-3.0, 3.0),frandom(-3.0, 3.0),  frandom(-1.0, 1.0),frandom(-1.0, 1.0),frandom(2.0, 5.0),  0,0,0.1, 0.7, -1);
			invoker.A_SpawnParticle (0xffcc00, SPF_FULLBRIGHT, random(25,35), random(6,9), 0, frandom(-3.0, 3.0),frandom(-3.0, 3.0),frandom(-3.0, 3.0),  frandom(-1.0, 1.0),frandom(-1.0, 1.0),frandom(2.0, 5.0),  0,0,0.1, 0.7, -1);
		}
		invoker.A_Wander();
		if(invoker.particles)
		{
			invoker.A_SpawnParticle (0xffaa00, SPF_FULLBRIGHT, random(25,35), random(6,7), 0, frandom(-3.0, 3.0),frandom(-3.0, 3.0),frandom(-3.0, 3.0),  frandom(-1.0, 1.0),frandom(-1.0, 1.0),frandom(2.0, 5.0),  0,0,0.1, 0.7, -1);
			invoker.A_SpawnParticle (0xffcc00, SPF_FULLBRIGHT, random(25,35), random(6,9), 0, frandom(-3.0, 3.0),frandom(-3.0, 3.0),frandom(-3.0, 3.0),  frandom(-1.0, 1.0),frandom(-1.0, 1.0),frandom(2.0, 5.0),  0,0,0.1, 0.7, -1);
		}
	}
	States
	{
		Spawn:
			BAL1 A 1 NoDelay A_Look();
			Loop;
		See:
			//BAL1 AAAAAAAAAAAAAAAAAAAA 1 A_SpawnerWander();
			FIRE ABABABABABABABABCDCDCD 1 A_SpawnerWander();
			TNT1 A 4 A_SpawnItemEx("ParticleArchvileFire", 0, 0, 0, 0, 0, 0, 0, SXF_NOCHECKPOSITION);
			TNT1 A 0 A_Jump(256, "DropZBM", "DropSGG", "DropImp");
		DropZBM:
			TNT1 A 1 
			{
				if(!A_SpawnItemEx("VileZombieman", 0, 0, 0, 0, 0, 0, 0, SXF_TRANSFERPOINTERS))
				{
					if(BabelArchvile(master))
					{
						BabelArchvile(master).summonCounter = BabelArchvile(master).summonCounter + 1; //failed summon
					}
				}
			}
			Stop;
		DropSGG:
			TNT1 A 1 
			{
				if(CVar.FindCVar("egr_vile_shotgun_drop").GetInt() == 1)
				{
					if(!A_SpawnItemEx("VileShotgunguy", 0, 0, 0, 0, 0, 0, 0, SXF_TRANSFERPOINTERS))
					{
						if(BabelArchvile(master))
						{
							BabelArchvile(master).summonCounter = BabelArchvile(master).summonCounter + 1; //failed summon
						}
					}
				}
				else
				{
					if(!A_SpawnItemEx("VileShotgunguyNoDrop", 0, 0, 0, 0, 0, 0, 0, SXF_TRANSFERPOINTERS))
					{
						if(BabelArchvile(master))
						{
							BabelArchvile(master).summonCounter = BabelArchvile(master).summonCounter + 1; //failed summon
						}
					}
				}
			}
			Stop;
		DropImp:
			TNT1 A 1 
			{
				if(!A_SpawnItemEx("VileImp", 0, 0, 0, 0, 0, 0, 0, SXF_TRANSFERPOINTERS))
				{
					if(BabelArchvile(master))
					{
						BabelArchvile(master).summonCounter = BabelArchvile(master).summonCounter + 1; //failed summon
					}
				}
			}
			Stop;
	}
}

class VileZombieman : BabelZombieMan
{
	int ghost;
	default
	{
		RenderStyle "Translucent";
		Alpha 0.01;
		+LOOKALLAROUND;
		-CountKill;
		Tag "Summoned Zombieman (Babel)";
	}
	override void BeginPlay()
	{
		super.BeginPlay();
		ghost = 0;
	}
	override void Tick()
	{
		if(health > 0)
		{
			BabelArchvile leader = BabelArchvile(master);
			if(leader)
			{
				if(leader.health <= 0)
				{
					self.DamageMobj(self, self, self.health+1, "Monster");
				}
			}
			else
			{
				self.DamageMobj(self, self, self.health+1, "Monster");
			}
			if(ghost <= 0)
			{
				A_VileGhost();
				ghost = 2;
			}
			else
			{
				ghost -= 1;
			}
		}
		super.Tick();
	}
	override void Die(Actor source, Actor inflictor, int dmgflags)
	{
		BabelArchvile leader = BabelArchvile(master);
		if(leader)
			leader.summonCounter = leader.summonCounter + 1;
		A_SpawnItemEx("VileZMDeathAnim");
		super.Die(source, inflictor, dmgflags);
	}
	action void A_VileGhost(float fadeRate = 0.019)
	{
		bool s = false;
		Actor a = null;
		[s, a] = A_SpawnItemEx("VileFrameUniversal", 0,0,0, 0,0,0, 0, SXF_TRANSFERSPRITEFRAME);
		if(s)
		{
			VileFrameUniversal(a).fadeRate = fadeRate;
		}
	}
	states
	{
		XDeath:
			Goto Death;
		Raise:
			stop;
	}
}

class VileShotgunguy : BabelShotgunGuy
{
	int ghost;
	default
	{
		RenderStyle "Translucent";
		Alpha 0.01;
		+LOOKALLAROUND;
		-CountKill;
		Tag "Summoned Shotgun Guy (Babel)";
	}
	override void BeginPlay()
	{
		super.BeginPlay();
		ghost = 0;
	}
	override void Tick()
	{
		if(health > 0)
		{
			BabelArchvile leader = BabelArchvile(master);
			if(leader)
			{
				if(leader.health <= 0)
				{
					self.DamageMobj(self, self, self.health+1, "Monster");
				}
			}
			else
			{
				self.DamageMobj(self, self, self.health+1, "Monster");
			}
			if(ghost <= 0)
			{
				A_VileGhost();
				ghost = 2;
			}
			else
			{
				ghost -= 1;
			}
		}
		super.Tick();
	}
	override void Die(Actor source, Actor inflictor, int dmgflags)
	{
		BabelArchvile leader = BabelArchvile(master);
		if(leader)
			leader.summonCounter = leader.summonCounter + 1;
		A_SpawnItemEx("VileSGDeathAnim");
		super.Die(source, inflictor, dmgflags);
	}
	action void A_VileGhost(float fadeRate = 0.019)
	{
		bool s = false;
		Actor a = null;
		[s, a] = A_SpawnItemEx("VileFrameUniversal", 0,0,0, 0,0,0, 0, SXF_TRANSFERSPRITEFRAME);
		if(s)
		{
			VileFrameUniversal(a).fadeRate = fadeRate;
		}
	}
	states
	{
		XDeath:
			Goto Death;
		Raise:
			stop;
	}
}

class VileShotgunguyNoDrop : VileShotgunguy
{
	default
	{
		DropItem "Shell", 255, 4;
		Tag "Summoned Shotgun Guy (Babel)";
	}
}

class VileImp : BabelImp
{
	int ghost;
	default
	{
		RenderStyle "Translucent";
		Alpha 0.01;
		+LOOKALLAROUND;
		-CountKill;
		Tag "Summoned Imp (Babel)";
	}
	override void BeginPlay()
	{
		super.BeginPlay();
		ghost = 0;
	}
	override void Tick()
	{
		if(health > 0)
		{
			BabelArchvile leader = BabelArchvile(master);
			if(leader)
			{
				if(leader.health <= 0)
				{
					self.DamageMobj(self, self, self.health+1, "Monster");
				}
			}
			else
			{
				self.DamageMobj(self, self, self.health+1, "Monster");
			}
			if(ghost <= 0)
			{
				A_VileGhost();
				ghost = 2;
			}
			else
			{
				ghost -= 1;
			}
		}
		super.Tick();
	}
	override void Die(Actor source, Actor inflictor, int dmgflags)
	{
		BabelArchvile leader = BabelArchvile(master);
		if(leader)
			leader.summonCounter = leader.summonCounter + 1;
		A_SpawnItemEx("VileImpDeathAnim");
		super.Die(source, inflictor, dmgflags);
	}
	action void A_VileGhost(float fadeRate = 0.019)
	{
		bool s = false;
		Actor a = null;
		[s, a] = A_SpawnItemEx("VileFrameUniversal", 0,0,0, 0,0,0, 0, SXF_TRANSFERSPRITEFRAME);
		if(s)
		{
			VileFrameUniversal(a).fadeRate = fadeRate;
		}
	}
	states
	{
		XDeath:
			Goto Death;
		Raise:
			stop;
	}
}

/* Ghost-y effect */
class VileFrameUniversal : Actor
{
	default
	{
		RenderStyle "Translucent";
		+NOINTERACTION;
		Alpha 1.0;
	}
	double fadeRate;
	double currentAlpha;
	override void BeginPlay()
	{
		super.BeginPlay();
		currentAlpha = 0.40;
		fadeRate = 0.028;
	}
	states
	{
		Spawn:
			"####" "#" 1 NoDelay
			{
				A_SetTranslucent(currentAlpha);
				currentAlpha -= fadeRate;
				if(currentAlpha <= 0)
					return ResolveState("Null");
				return ResolveState(null);
			}
			Loop;
	}
}

class VileDeathAnim : Actor
{
	default
	{
		RenderStyle "Translucent";
		+NOINTERACTION;
		Alpha 0.8;
	}
	States
	{
		Spawn:
			VILE RSTUVWXYZ 7 A_FadeOut(0.152);
			Stop;
	}
}

class VileZMDeathAnim : Actor
{
	default
	{
		RenderStyle "Translucent";
		+NOINTERACTION;
		Alpha 0.8;
	}
	States
	{
		Spawn:
			POSS HHHHHIIIIIJJJJJKKKKKLLLLL 1 A_FadeOut(0.0476);
			Stop;
	}
}

class VileSGDeathAnim : Actor
{
	default
	{
		RenderStyle "Translucent";
		+NOINTERACTION;
		Alpha 0.8;
	}
	States
	{
		Spawn:
			SPOS HHHHHIIIIIJJJJJKKKKKLLLLL 1 A_FadeOut(0.0476);
			Stop;
	}
}

class VileImpDeathAnim : Actor
{
	default
	{
		RenderStyle "Translucent";
		+NOINTERACTION;
		Alpha 0.8;
	}
	States
	{
		Spawn:
			TROO IIIIIIIIJJJJJJJJ 1 A_FadeOut(0.0344);
			TROO KKKKKKLLLLLL 1 A_FadeOut(0.0344);
			TROO MM 1 A_FadeOut(0.0344);
			Stop;
	}
}
