

//good old DieBerdemon

Class DieBerdemon : Cyberdemon
{
    Default
    {
		-COUNTKILL
        Health 5;
        Radius 40;
        Height 110;
        Speed 64;
        Tag "DieBerdemon";
		
    }
    States
    {
        Missile:
            CYBR E 6 A_FaceTarget;
            CYBR E 12 A_FaceTarget;
            CYBR E 12 A_FaceTarget;
            Goto See;
    }

}

//a candle for some reason

Class HauntedCandle : Actor
{
	bool candleLit;

	override bool Used (Actor user)
	{
		if (candleLit)
		{
			SetStateLabel("LitCandle");
		}
		else
		{
			SetStateLabel("Spawn");
		}
		
		candleLit = !candleLit;
		
		return true;
	}

	Default
	{
		+NOGRAVITY
		+FIXMAPTHINGPOS
		Radius 6.5;
	}
	States
	{
		Spawn:
			TNT1 A 0
			{
				candleLit = false;
			}
			Goto UnlitCandle;
		UnlitCandle:
			PCDF A 2;
			loop;
		LitCandle:
			PCDN ABC 2;
			loop;
		
	
	}
	

}

//Macguffin
Class RelicMcGuff : Inventory
{
	Default
	{
		Inventory.PickupMessage "Demiurgic Shard";
		Inventory.Amount 1;
		Inventory.MaxAmount 5;
		+COUNTITEM //means that the item counts toward item percentage
	}
	States
	{
		Spawn:
			MCGF ABCD 2;
			loop;
	}
}

Class SacredGHLKey : Inventory
{
	Default
	{
		Inventory.PickupMessage "Sacred Golden Hidden Laboratory Key";
		Inventory.Amount 1;
		Inventory.MaxAmount 1;
		+COUNTITEM //means that the item counts toward item percentage	
	}
	States
	{
		Spawn:
			GOKE ABC 2 BRIGHT;
			loop;
	}	
}

//Custom projectile

class OrangeDeathOrb : Actor
{
	Actor firer;
	double theta;
	double phi;
	double phiOff;
	double r;
	
	override void PostBeginPlay()
	{
		firer = null;
	}
	
	override int SpecialMissileHit(Actor victim)
	{
		int rtn = super.SpecialMissileHit(victim);
		
		return rtn;
	}
	
	
	
	/*void setFirer(Actor a)
	{
		firer = a;
	}*/

	 Default
	 {
	   Radius 20;
	   Height 40;
	   Speed 10;
	   FastSpeed 20;
	   Damage 3;
	   Projectile;
	   +RANDOMIZE
	   +ZDOOMTRANS
	   RenderStyle "Add";
	   Alpha 1;
	   SeeSound "imp/attack";
	   DeathSound "imp/shotx";
	 }
	 States
	 {
	 Spawn:
	   ZDRB ABCD 2 BRIGHT;
	   Loop;
	 Death:
	   TNT1 A -1 BRIGHT;
	   
	   Stop;
	 }
}

//Boss stage 1

class HolyArchon : Actor
{
	
	int numOrb;
	Array<OrangeDeathOrb> orbs;
	bool alive;
	bool firing;
	double pi;
	int ticker;
	
	void addOrbit()
	{
		//OrangeDeathOrb newOrb = OrangeDeathOrb(A_SpawnProjectile("OrangeDeathOrb", 48));
		vector3 displ = self.pos;
		double rota = self.Angle;
		displ.x += (128 * cos(rota));
		displ.y += (128 * sin(rota));
		displ.z += self.Height / 2;
		OrangeDeathOrb newOrb = OrangeDeathOrb(Spawn("OrangeDeathOrb",displ));
		newOrb.theta = rota;
		newOrb.phi = FRandom(0.0,90.0);
		newOrb.phiOff = FRandom(0.0,360.0);
		//newOrb.setFirer(self);
		if(newOrb)
		{
			orbs.Push(newOrb);
		}
		
	}
	
	void updateOrbs()
	{
		for (int i = 0; i < orbs.size(); i++)
		{
			let orb = orbs[i];
			
			if(orb)
			{
				//vector3 newPos = (self.Pos.x + (128 * cos(orb.theta)),self.Pos.y + (128 * sin(orb.theta)),self.Pos.z + self.Height / 2);
				double cphi = orb.phi*cos(orb.theta + orb.phiOff);
				vector3 newPos = (self.Pos.x + (128 * cos(orb.theta)),self.Pos.y + (128 * sin(orb.theta) * cos(cphi)),(self.Pos.z + self.Height / 2) + (128 * sin(cphi)));
				
				//orb.Pos.x = self.Pos.x + (128 * cos(orb.theta));
				//orb.Pos.y = self.Pos.y + (128 * sin(orb.theta));
				//orb.Pos.z = self.Pos.z + self.Height / 2;
				orb.SetOrigin(newPos,true);
				
				orb.theta += 8;
				//orb.phi += 8
			}
			
			
		}
	}
	
	void regenOrb()
	{
		numOrb -= 1;
	}
	
	
	override void PostBeginPlay()
	{
		super.PostBeginPlay();
		ticker = 0;
		pi = 3.14159;
		numOrb = 0;
		alive = true;
		firing = false;
	}
	
	override void Tick()
	{
		super.Tick();
		if (alive && firing)
		{
			self.updateOrbs();
		
			double theta = FRandom(-180.0,180.0);
			double pitch = FRandom(-90.0,90.0);
			//OrangeDeathOrb newOrb = OrangeDeathOrb(A_SpawnProjectile("OrangeDeathOrb", 48,0,theta,CMF_AIMDIRECTION,pitch));
			//newOrb.setFirer(self);
			if(ticker % 10 == 0 && orbs.size() < 10)
			{
				addOrbit();
				numOrb = numOrb + 1;
			}
			

		}
		
		ticker++;
	}

	override void Die(Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath)
	{
		Super.Die(source,inflictor,dmgFlags,MeansOfDeath);
		alive = false;
		
		for (int i = 0; i < orbs.size(); i++)
		{
			let orb = orbs[i];
			if(orb)
			{
				orb.destroy();
			}
		}
	}

	Default
	{
		Health 200;
		Radius 20;
		Height 56;
		Mass 100;
		Speed 8;
		PainChance 200;
		Monster;
		+FLOORCLIP
		+NOGRAVITY
		SeeSound "imp/sight";
		PainSound "imp/pain";
		DeathSound "imp/death";
		ActiveSound "imp/active";
		HitObituary "$OB_IMPHIT";
		Obituary "$OB_IMP";
		Tag "Holy Archon";
	}
	States
	{
	Spawn:
		HLAR A 10 A_Look;
		Loop;
	See:
		TNT1 A 0
		{
			firing = true;
		}
		HLAR AABBCCDD 3 A_Chase;
		Loop;
	Melee:
	Missile:
		HLAR EF 8 A_FaceTarget;
		//TROO G 6 A_TroopAttack ;
		HLAR G 6 A_SpawnProjectile("OrangeDeathOrb", 48);
		Goto See;
	Pain:
		HLAR D 2;
		HLAR D 2 A_Pain;
		Goto See;
	Death:
		TROO I 8;
		TROO J 8 A_Scream;
		TROO K 6;
		TROO L 6 A_NoBlocking;
		TROO M -1;
		Stop;
	XDeath:
		TROO N 5;
		TROO O 5 A_XScream;
		TROO P 5;
		TROO Q 5 A_NoBlocking;
		TROO RST 5;
		TROO U -1;
		Stop;
	Raise:
		TROO ML 8;
		TROO KJI 6;
		Goto See;
	}
}

//boss stage 2

class LordTranscend : Actor
{
	bool spawned;
	bool spawner;
	Array<Actor> orbs;	

	override void PostBeginPlay()
	{
		super.PostBeginPlay();
		spawned = false;
		spawner = true;
	}
	
	override void Tick()
	{
		super.Tick();
		
		if (spawner && !spawned)
		{
			addOrbit();
			addOrbit();
			spawned = true;
		}
	}
	
	Action void ForceBurst()
	{

	}
	
	void addOrbit()
	{		
		//double theta = FRandom(-180.0,180.0);
		//double pitch = FRandom(-90.0,90.0);
		
		double pitch = 30.0;
		//double rota = self.Angle;
		double rota = FRandom(-180.0,180.0);
		vector3 displ = self.pos;
		vector3 velo;
		displ.x += (128 * cos(rota));
		displ.y += (128 * sin(rota));
		displ.z += self.Height / 2;
		
		double speed = 12.0;
		velo.x = speed * cos(rota);
		velo.y = speed * sin(rota);
		velo.z = speed * cos(pitch);
		
		
		let newOrb = Spawn("Revenant", displ);
		//newOrb.spawner = false;
		
		//newOrb.setOrigin(displ);
		newOrb.Vel = velo;
		
		orbs.push(newOrb);
		
		
		
	
	}
	
	override void Die(Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath)
	{
		Super.Die(source,inflictor,dmgFlags,MeansOfDeath);
		//alive = false;
		
		for (int i = 0; i < orbs.size(); i++)
		{
			let orb = orbs[i];
			if(orb)
			{
				//orb.destroy();
				orb.A_Die();
			}
		}
	}		

	Default
	{
		Health 500;
		Radius 20;
		Height 56;
		Mass 500;
		Speed 10;
		PainChance 100;
		Monster;
		MeleeThreshold 196;
		+MISSILEEVENMORE 
		+FLOORCLIP
		SeeSound "skeleton/sight";
		PainSound "skeleton/pain";
		DeathSound "skeleton/death";
		ActiveSound "skeleton/active";
		MeleeSound "skeleton/melee";
		HitObituary "$OB_UNDEADHIT";
		Obituary "$OB_UNDEAD";
		Tag "Lord Transcendant";
	}
	States
	{
	Spawn:
		SKEL AB 10 A_Look;
		Loop;
	See:
		SKEL AABBCCDDEEFF 2 A_Chase;
		Loop;
	Melee:
		SKEL G 0 A_FaceTarget;
		SKEL G 6 A_SkelWhoosh;
		SKEL H 6 A_FaceTarget;
		SKEL I 6 A_SkelFist;
		Goto See;
	Missile:
		SKEL J 0 BRIGHT A_FaceTarget;
		SKEL J 10 BRIGHT A_FaceTarget;
		//SKEL K 10 A_SkelMissile;
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");		
		SKEL K 1 BRIGHT A_SpawnProjectile("PlasmaBall");
		SKEL K 10 A_FaceTarget;
		Goto See;
	Pain:
		SKEL L 5;
		SKEL L 5 A_Pain;
		Goto See;
	Death:
		SKEL LM 7;
		SKEL N 7 A_Scream;
		SKEL O 7 A_NoBlocking;
		SKEL P 7;
		SKEL Q -1;
		Stop;
	Raise:
		SKEL Q 5;
		SKEL PONML 5;
		Goto See;
	}
}


//boss stage 3

class AscendSubjer : Actor
{

	

	Array<Actor> orbs;
	bool alive;
	bool firing;
	int ticker;

	override void PostBeginPlay()
	{
		super.PostBeginPlay();
		alive = true;
		firing = false;
		ticker = 0;
	}

	override void Tick()
	{
		super.Tick();
		if (alive && firing)
		{
			self.updateOrbs();
		
			
			//OrangeDeathOrb newOrb = OrangeDeathOrb(A_SpawnProjectile("OrangeDeathOrb", 48,0,theta,CMF_AIMDIRECTION,pitch));
			//newOrb.setFirer(self);
			if(ticker % 10 == 0 && orbs.size() < 15)
			{
				addOrbit();
			}
			

		}
		
		ticker++;
	}
	
	override void Die(Actor source, Actor inflictor, int dmgflags, Name MeansOfDeath)
	{
		Super.Die(source,inflictor,dmgFlags,MeansOfDeath);
		alive = false;
		
		for (int i = 0; i < orbs.size(); i++)
		{
			let orb = orbs[i];
			if(orb)
			{
				//orb.destroy();
				orb.A_Die();
			}
		}
	}	
	
	void addOrbit()
	{
		self.updateOrbs();
		
		//double theta = FRandom(-180.0,180.0);
		//double pitch = FRandom(-90.0,90.0);
		
		double pitch = 30.0;
		//double rota = self.Angle;
		double rota = FRandom(-180.0,180.0);
		vector3 displ = self.pos;
		vector3 velo;
		displ.x += (128 * cos(rota));
		displ.y += (128 * sin(rota));
		displ.z += self.Height / 2;
		
		double speed = 12.0;
		velo.x = speed * cos(rota);
		velo.y = speed * sin(rota);
		velo.z = speed * cos(pitch);
		
		
		let newOrb = Spawn("DoomImp", displ);
		
		//newOrb.setOrigin(displ);
		newOrb.Vel = velo;
		
		orbs.push(newOrb);
		
		
		
	
	}
	
	void updateOrbs()
	{
		for(int i = orbs.size() - 1; i >= 0; i--)
		{
			let orb = orbs[i];
			
			if (orb.Health < 1)
			{
				//orb.destroy();
				orbs.Delete(i);
			}
		}
	}
	

	Default
	{
		Health 900;
		Radius 48;
		Height 128;
		Mass 1000;
		Speed 8;
		PainChance 80;
		Monster;
		+FLOORCLIP
		+BOSSDEATH
		SeeSound "fatso/sight";
		PainSound "fatso/pain";
		DeathSound "fatso/death";
		ActiveSound "fatso/active";
		Obituary "$OB_FATSO";
		Tag "Ascendant Subjugatrix";
	}
	States
	{
	Spawn:
		SBJX AB 15 A_Look;
		Loop;
	See:
		TNT1 A 0
		{
			firing = true;
		}
		SBJX AABBAABBAABB 4 A_Chase;
		Loop;
	Missile:
		SBJX A 20 A_FatRaise;
		SBJX C 10 BRIGHT A_FatAttack1;
		SBJX AB 5 A_FaceTarget;
		SBJX C 10 BRIGHT A_FatAttack2;
		SBJX AB 5 A_FaceTarget;
		SBJX C 10 BRIGHT A_FatAttack3;
		SBJX AB 5 A_FaceTarget;
		Goto See;
	Pain:
		SBJX D 3;
		SBJX D 3 A_Pain;
		Goto See;
	Death:
		FATT K 6;
		FATT L 6 A_Scream;
		FATT M 6 A_NoBlocking;
		FATT NOPQRS 6;
		FATT T -1 A_BossDeath;
		Stop;
	 Raise:
		FATT R 5;
		FATT QPONMLK 5;
		Goto See;
	}
}

class SabaothStub:Actor
{
	Default
	{
		Radius 16;
		Height 256;
		Tag "Sabaoth Stationary";
	}
	States
	{
	Spawn:
		SABH A 2;
		Loop;
	}
}

// Talkable NPC
class GenericChatter:Actor
{
	Default
	{
	
		+FLOORCLIP
		+USESPECIAL
		-COUNTKILL
		
	}
}

// The Infernal Reverend Billy Bothways
class BillyBothways:GenericChatter
{
	Default
	{
		Health 60;
		Radius 20;
		Height 56;
		ActiveSound "imp/active";		
		Tag "Billy Bothways";
	}
	
	States
	{
	Spawn:
		BLBW A 10;
		Loop;
	}
}

//Solvecorp CEO Jane Business
class JaneBusiness:GenericChatter
{
	Default
	{
		Health 60;
		Radius 20;
		Height 60;
		ActiveSound "grunt/active";
		Tag "Jane Business";		
	}
	
	States
	{
	Spawn:
		JANE A 10;
		Loop;
	}
}