Class GHAGMoonBlastGun : GHAGPokemonMove
{
	Default
	{
		Weapon.SlotNumber 7;
		Tag "Moon Blast";
		+Weapon.NoAlert;
		+Weapon.No_Auto_Switch;
		Weapon.SelectionOrder 4000;
		
		Inventory.PickupMessage "Tada! Gardevoir learned \c[Pink]Moon Blast!"; // and thankfully didn't forget anything!
	}
	
	int charge;
	
	States
	{
		Spawn:
			TMFY A -1;
			stop;
		Select :
			HAND A 1 
			{
				A_GHAGRaise();
				A_DrawMoonOverlay();
			}
			Loop;
		Deselect :
			HAND A 1 {
				A_GHAGLower();
				A_DrawMoonOverlay();
			}
			Loop;
		Ready :
			HAND A 1 {
				invoker.charge == 0;
				A_WeaponReady();
				A_DrawMoonOverlay();
			}
			Loop;
		Fire :
			TNT1 A 0 
			{
				A_Overlay(-1, "Moon.Clear", true);
				A_StartSound("attack/MOONCHARGE", CHAN_WEAPON);
			}
			HAND HHHHHHHHH 6 
			{
				A_DrawMoonOverlay(true);
				A_SetTics(GHAGGardevoir(self).GetTicModifier(6));
				++invoker.charge;
				int rngrange = Int(Max(20 * Max(invoker.charge / 1000, 0.01), 2));
				A_OverlayOffset(0, random(-rngrange, rngrange), 43 + random(-rngrange, rngrange), WOF_INTERPOLATE);
			}
			TNT1 A 0 {
				A_MoonBlast();
				invoker.charge = 0;
			}
			HAND J 12 Offset(0, 5);
			TNT1 A 0 A_Refire();
			goto Ready;
		Moon.Charge:
			MNBL IHGFEDCBAAA 1 Bright A_SetTics(GHAGGardevoir(self).GetTicModifier(6));
			stop;
		Moon.Idle:
			MNBL A 1 Bright;
			stop;
	}
	
	Action void A_DrawMoonOverlay(bool charge = false)
	{
		A_OverlayPivot(-1);
	
		if (!charge) {
			A_Overlay(-1, "Moon.Idle", true);
		}
		else if (charge) 
		{
			A_Overlay(-1, "Moon.Charge", true);
		}
		
		A_OverlayFlags(-1, PSPF_ADDBOB, false);
		A_OverlayOffset(-1, 300, 64);
		A_OverlayOffset(-1, sin(gametic) * 0.05, cos(gametic) * 0.05, WOF_ADD | WOF_INTERPOLATE);
	}
	
	Action void A_MoonBlast()
	{
		let gardie = GHAGGardevoir(players[consoleplayer].mo);
		
		A_StartSound("attack/MOONBOOM", CHAN_WEAPON, 0, 1);
		A_ClearOverlays();
		
		FLineTraceData blast;
		LineTrace(angle, 2048, pitch, 0, height - 12, 0, 0, blast);
		Self.Spawn('GHAGMoonBlastKaboom', blast.HitLocation);
		
		A_QuakeEx(4, 4, 4, 25, 0, 64, "", QF_SCALEDOWN);
		double modifier = GHAGGardevoir(players[consoleplayer].mo).getRageModifier();
		A_RailAttack(512 + Int(512 * modifier), 0, false, "D56671", "BADBB2", RGF_SILENT | RGF_NOPIERCING | RGF_FULLBRIGHT, 0, "", 0, 0, 0, 20);
		A_AlertMonsters();
		
		gardie.subtractAnger(200);
	}
}

Class GHAGMoonBlastKaboom : Actor
{
	default
	{
		+NoGravity;
		+ForceRadiusDmg;
		Radius 10;
	}
	states
	{
		Spawn:
			MNBL A 1 NoDelay Bright
			{
				double modifier = GHAGGardevoir(players[consoleplayer].mo).getRageModifier();
				A_SetScale(1 + modifier, 1 + modifier);
				A_MoonBlastBlast(BF_DONTWARN | BF_AFFECTBOSSES | BF_NOIMPACTDAMAGE | 16, 512 + (512 * modifier), 512 + (512 * modifier), 40 + (40 * modifier));
			}
			MNBL A 1 Bright;
			MNBL BCDEFGHIJKLMNOPQRS 2 Bright;
			stop;
	}
	
	Action void A_MoonBlastBlast(int blastflags = 0, double strength = 255, double radius = 255, double speed = 20, class<Actor> blasteffect = "BlastEffect", sound blastsound = "BlastRadius")
	{
		A_StartSound (blastsound, CHAN_AUTO);

		if (!(blastflags & BF_DONTWARN))
		{
			SoundAlert (self);
		}
		ThinkerIterator it = ThinkerIterator.Create("Actor");
		Actor mo;
		while ( (mo = Actor(it.Next ())) )
		{
			//ignore player
			if (GHAGGardevoir(mo)) continue;
			if (mo == self || (mo.bBoss && !(blastflags & BF_AFFECTBOSSES)) || mo.bDormant || mo.bDontBlast)
			{ // Not a valid monster: originator, boss, dormant, or otherwise protected
				continue;
			}
			if (mo.bIceCorpse || mo.bCanBlast)
			{
				// Let these special cases go
			}
			else if (mo.bIsMonster && mo.health <= 0)
			{
				continue;
			}
			else if (!mo.player && !mo.bMissile && (!mo.bIsMonster && !BossBrain(mo)) && !mo.bCanBlast && !mo.bTouchy && !mo.bVulnerable)
			{	// Must be monster, player, missile, touchy or vulnerable
				continue;
			}
			if (Distance2D(mo) > radius)
			{ // Out of range
				continue;
			}
			if (mo.CurSector.PortalGroup != CurSector.PortalGroup && !CheckSight(mo))
			{
				// in another region and cannot be seen.
				continue;
			}
			if ((blastflags & 16) && !isVisible(mo, true)) 
			{
				//only blast if target can bee seen by calling actor
				continue;
			}
			A_MoonBlastActor(mo, strength, speed, blasteffect, !!(blastflags & BF_NOIMPACTDAMAGE));
		}
	}
	Action Void A_MoonBlastActor (Actor victim, double strength, double speed, Class<Actor> blasteffect, bool dontdamage)
	{
		if (!victim.SpecialBlastHandling (self, strength))
		{
			return;
		}

		double ang = AngleTo(victim);
		Vector2 move = AngleToVector(ang, speed);
		victim.Vel.XY = move;

		// Spawn blast puff
		ang -= 180.;
		Vector3 spawnpos = victim.Vec3Offset(
			(victim.radius + 1) * cos(ang),
			(victim.radius + 1) * sin(ang),
			(victim.Height / 2) - victim.Floorclip);
		Actor mo = blasteffect? Spawn (blasteffect, spawnpos, ALLOW_REPLACE) : null;
		if (mo)
		{
			mo.Vel.XY = victim.Vel.XY;
		}
		if (victim.bMissile)
		{
			// [RH] Floor and ceiling huggers should not be blasted vertically.
			if (!victim.bFloorHugger && !victim.bCeilingHugger)
			{
				victim.Vel.Z = 8;
				if (mo != null) mo.Vel.Z = 8;
			}
		}
		else
		{
			victim.Vel.Z = 1000. / victim.Mass;
		}
		if (victim.player)
		{
			// Players handled automatically
		}
		else if (!dontdamage)
		{
			victim.bBlasted = true;
		}
		if (victim.bTouchy)
		{ // Touchy objects die when blasted
			victim.bArmed = false; // Disarm
			victim.DamageMobj(self, self, victim.health, 'Melee', DMG_FORCED|DMG_EXPLOSION);
		} else {
			victim.DamageMobj(self, GHAGGardevoir(players[consoleplayer].mo), 512, "Explosive");
			if (victim.health > 0) victim.SetStateLabel('Pain');
		}
	}
}