Class GHAGMegaPunch : GHAGPokemonMove
{
	Default
	{
		Weapon.SlotNumber 1;
		Weapon.kickback 150;
		Tag "Mega Punch";
		+Weapon.No_Auto_Switch;
	}
	
	States {
		Select :
			MPUN A 1 A_Raise();
			Loop;
		Deselect :
			MPUN A 1 A_Lower();
			Loop;
		Ready :
			MPUN A 1 A_WeaponReady();
			Loop;
		Fire :
			#### # 2 {
				GHAGGardevoir(self).subtractAnger(20);
			}
			#### A 0 A_StartSound("fists/MEGAPNCH", CHAN_AUTO);
			#### A 0 A_JumpIf(random(1, 100) <= 50, "Fire.Lefty");
		Fire.Righty:
			#### BC 3 A_SetTics(GHAGGardevoir(self).GetTicModifier(3));
			#### D 4 A_MegaPunch();
			#### EFG 4 {
				A_WeaponReady(WRF_NOFIRE | WRF_ALLOWRELOAD);
				A_SetTics(GHAGGardevoir(self).GetTicModifier(4));
			}
			#### A 1 A_Refire();
			goto Ready;
		Fire.Lefty:
			#### HI 3 A_SetTics(GHAGGardevoir(self).GetTicModifier(3));
			#### J 4 A_MegaPunch();
			#### KLM 4 {
				A_WeaponReady(WRF_NOFIRE | WRF_ALLOWRELOAD);
				A_SetTics(GHAGGardevoir(self).GetTicModifier(4));
			}
			#### A 1 A_Refire();
			goto Ready;
	}

	Action void A_ExplosivePunch(int damage, bool norandom = false, int flags = CPF_USEAMMO, class<Actor> pufftype = "BulletPuff", double range = 0, double lifesteal = 0, int lifestealmax = 0, class<BasicArmorBonus> armorbonustype = "ArmorBonus", sound MeleeSound = 0, sound MissSound = "")
	{
		let player = self.player;
		if (!player) return;

		let weapon = player.ReadyWeapon;

		double angle;
		double pitch;
		FTranslatedLineTarget t;
		int			actualdamage;

		if (!norandom)
			damage *= random[cwpunch](1, 8);

		angle = self.Angle + random2[cwpunch]() * (5.625 / 256);
		if (range == 0) range = DEFMELEERANGE;
		pitch = AimLineAttack (angle, range, t, 0., ALF_CHECK3D);

		// only use ammo when actually hitting something!
		if ((flags & CPF_USEAMMO) && t.linetarget && weapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
		{
			if (!weapon.DepleteAmmo(weapon.bAltFire, true))
				return;	// out of ammo
		}

		if (pufftype == NULL)
			pufftype = 'BulletPuff';
		int puffFlags = LAF_ISMELEEATTACK | ((flags & CPF_NORANDOMPUFFZ) ? LAF_NORANDOMPUFFZ : 0);

		Actor puff;
		[puff, actualdamage] = LineAttack (angle, range, pitch, damage, 'Melee', pufftype, puffFlags, t);

		if (!t.linetarget)
		{
			if (MissSound) A_StartSound(MissSound, CHAN_WEAPON);
		}
		else
		{
			A_BlastLOS(BF_AFFECTBOSSES | BF_DONTWARN | 16, 255, 256 * GHAGGardevoir(self).GetRageModifier(), 20 * GHAGGardevoir(self).GetRageModifier(), pufftype, damage);
			Self.A_Quake(32 + Int(GHAGGardevoir(self).getRageModifier() * 64), max(3, 15 * Int(GHAGGardevoir(self).getRageModifier())), 0, 32, "");
			if (lifesteal > 0 && !(t.linetarget.bDontDrain))
			{
				if (flags & CPF_STEALARMOR)
				{
					if (armorbonustype == NULL)
					{
						armorbonustype = 'ArmorBonus';
					}
					if (armorbonustype != NULL)
					{
						let armorbonus = BasicArmorBonus(Spawn(armorbonustype));
						if (armorbonus)
						{
							armorbonus.SaveAmount *= int(actualdamage * lifesteal);
							if (lifestealmax > 0) armorbonus.MaxSaveAmount = lifestealmax;
							armorbonus.bDropped = true;
							armorbonus.ClearCounters();

							if (!armorbonus.CallTryPickup(self))
							{
								armorbonus.Destroy ();
							}
						}
					}
				}
				else
				{
					GiveBody (int(actualdamage * lifesteal), lifestealmax);
				}
			}
			if (weapon != NULL)
			{
				if (MeleeSound) A_StartSound(MeleeSound, CHAN_WEAPON);
				else			A_StartSound(weapon.AttackSound, CHAN_WEAPON);
			}

			if (!(flags & CPF_NOTURN))
			{
				// turn to face target
				self.Angle = t.angleFromSource;
			}

			if (flags & CPF_PULLIN) self.bJustAttacked = true;
			if (flags & CPF_DAGGER) t.linetarget.DaggerAlert (self);
		}
	}
	
	action void A_BlastLOS(int blastflags = 0, double strength = 255, double radius = 255, double speed = 20, class<Actor> blasteffect = "BlastEffect", int _damage = 0, sound blastsound = "BlastRadius")
	{

		if (player && (blastflags & BF_USEAMMO) && invoker == player.ReadyWeapon && stateinfo != null && stateinfo.mStateType == STATE_Psprite)
		{
			Weapon weapon = player.ReadyWeapon;
			if (weapon != null && !weapon.DepleteAmmo(weapon.bAltFire))
			{
				return;
			}
		}

		A_StartSound (blastsound, CHAN_AUTO);

		if (!(blastflags & BF_DONTWARN))
		{
			SoundAlert (self);
		}
		ThinkerIterator it = ThinkerIterator.Create("Actor");
		Actor mo;
		while ( (mo = Actor(it.Next ())) )
		{
			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 && !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;
			}
			
			Actor victim = mo;
			
			double ang = AngleTo(victim);
			Vector2 move = AngleToVector(ang, speed);
			victim.Vel.XY = move;

			ang -= 180.;
			Vector3 spawnpos = victim.Vec3Offset(
				(victim.radius + 1) * cos(ang),
				(victim.radius + 1) * sin(ang),
				(victim.Height / 2) - victim.Floorclip);
			Actor puff = blasteffect? Spawn (blasteffect, spawnpos, ALLOW_REPLACE) : null;
			if (puff)
			{
				puff.target = victim;
			}
			if (victim.bMissile)
			{
				// [RH] Floor and ceiling huggers should not be blasted vertically.
				if (!victim.bFloorHugger && !victim.bCeilingHugger)
				{
					victim.Vel.Z = 8;
					if (puff != null) mo.Vel.Z = 8;
				}
			}
			else
			{
				victim.Vel.Z = 1000. / victim.Mass;
			}
			if (victim.bTouchy)
			{
				victim.bArmed = false;
				victim.DamageMobj(self, self, victim.health, 'Melee', DMG_FORCED|DMG_EXPLOSION);
			}
			victim.DamageMobj(self, self, int(_damage * (2. / 3.)), Puff.damageType, DMG_FORCED|DMG_EXPLOSION);
		}
	}
	
	Action void A_MegaPunch() 
	{
		Invoker.kickback = 150 + Int(500 * GHAGGardevoir(self).GetRageModifier());
		A_ExplosivePunch(80 + Int(160 * GHAGGardevoir(self).GetRageModifier()), true, CPF_NOTURN, "GHAGMegaPuff", 64 + Int(64 * GHAGGardevoir(self).GetRageModifier()), 0, 0, "", "attack/CONTACT");
	}
}

Class GHAGMegaPuff : BulletPuff
{
	Default {
		+PUFFONACTORS;
		+HITTARGET;
		-RANDOMIZE;
		VSpeed 0;
		Alpha 1;
	}
	
	override void tick() {
	
		if (target) {
		
			Vector3 follow = target.pos;
			if (target.health > 0 || target.bIceCorpse)
			{
				follow.z += (target.height) - (target.height / 3.);
			} else {
				follow.z += 32;
			}
			SetOrigin(follow, false);

		}
		
		Super.tick();
	}

	States
	{
		Spawn:
		Melee:
			MPUF BABABA 4 Bright;
		Death:
			stop;
	}
}