
// The Cleric's Serpent Staff -----------------------------------------------

class CWeapStaff : ClericWeapon
{
	Default
	{
		Weapon.SelectionOrder 1600;
		Weapon.AmmoUse1 1;
		Weapon.AmmoGive1 25;
		Weapon.KickBack 150;
		Weapon.YAdjust 10;
		Weapon.AmmoType1 "Mana1";
		Inventory.PickupMessage "$TXT_WEAPON_C2";
		Obituary "$OB_MPCWEAPSTAFFM";
		Tag "$TAG_CWEAPSTAFF";
	}

	States
	{
	Spawn:
		WCSS A -1;
		Stop;
	Select:
		CSSF C 1 A_Raise;
		Loop;
	Deselect:
		CSSF B 3;
		CSSF C 4;
		CSSF C 1 A_Lower;
		Wait;
	Ready:
		CSSF C 4;
		CSSF B 3 A_CStaffInitBlink;
		CSSF AAAAAAA 1 A_WeaponReady;
		CSSF A 1 A_CStaffCheckBlink;
		Goto Ready + 2;
	Fire:
		CSSF A 1 Offset (0, 45) A_CStaffCheck;
		CSSF J 1 Offset (0, 50) A_CStaffAttack;
		CSSF J 2 Offset (0, 50);
		CSSF J 2 Offset (0, 45);
		CSSF A 2 Offset (0, 40);
		CSSF A 2 Offset (0, 36);
		Goto Ready + 2;
	Blink:
		CSSF BBBCCCCCBBB 1 A_WeaponReady;
		Goto Ready + 2;
	Drain:
		CSSF K 10 Offset (0, 36);
		Goto Ready + 2;
	}
	
	//============================================================================
	//
	// A_CStaffCheck
	//
	//============================================================================

	action void A_CStaffCheck()
	{
		FTranslatedLineTarget t;

		if (player == null)
		{
			return;
		}
		Weapon weapon = player.ReadyWeapon;

		int damage = 20 + (random[StaffCheck]() & 15);
		int max = player.mo.GetMaxHealth();
		for (int i = 0; i < 3; i++)
		{
			for (int j = 1; j >= -1; j -= 2)
			{
				double ang = angle + j*i*(45. / 16);
				double slope = AimLineAttack(ang, 1.5 * DEFMELEERANGE, t, 0., ALF_CHECK3D);
				if (t.linetarget)
				{
					LineAttack(ang, 1.5 * DEFMELEERANGE, slope, damage, 'Melee', "CStaffPuff", false, t);
					if (t.linetarget != null)
					{
						angle = t.angleFromSource;
						if (((t.linetarget.player && (!t.linetarget.IsTeammate(self) || level.teamdamage != 0)) || t.linetarget.bIsMonster)
							&& (!t.linetarget.bDormant && !bInvulnerable))
						{
							int newLife = player.health + (damage >> 3);
							newLife = newLife > max ? max : newLife;
							if (newLife > player.health)
							{
								health = player.health = newLife;
							}
							if (weapon != null)
							{
								State newstate = weapon.FindState("Drain");
								if (newstate != null) player.SetPsprite(PSP_WEAPON, newstate);
							}
						}
						if (weapon != null)
						{
							weapon.DepleteAmmo(weapon.bAltFire, false);
						}
					}
					return;
				}
			}
		}
	}

	//============================================================================
	//
	// A_CStaffAttack
	//
	//============================================================================

	action void A_CStaffAttack()
	{
		if (player == null)
		{
			return;
		}

		Weapon weapon = player.ReadyWeapon;
		if (weapon != null)
		{
			if (!weapon.DepleteAmmo (weapon.bAltFire))
				return;
		}
		Actor mo = SpawnPlayerMissile ("CStaffMissile", angle - 3.0);
		if (mo)
		{
			mo.WeaveIndexXY = 32;
		}
		mo = SpawnPlayerMissile ("CStaffMissile", angle + 3.0);
		if (mo)
		{
			mo.WeaveIndexXY = 0;
		}

		// [BC] Apply spread.
		if (FindInventory("PowerSpread"))
		{
			mo = SpawnPlayerMissile ("CStaffMissile", angle - 3.0 + 15.);
			if (mo)
			{
				mo.WeaveIndexXY = 32;
			}
			mo = SpawnPlayerMissile ("CStaffMissile", angle + 3.0 + 15.);
			if (mo)
			{
				mo.WeaveIndexXY = 0;
			}

			mo = SpawnPlayerMissile ("CStaffMissile", angle - 3.0 - 15.);
			if (mo)
			{
				mo.WeaveIndexXY = 32;
			}
			mo = SpawnPlayerMissile ("CStaffMissile", angle + 3.0 - 15.);
			if (mo)
			{
				mo.WeaveIndexXY = 0;
			}
		}

		A_PlaySound ("ClericCStaffFire", CHAN_WEAPON);
	}

	//============================================================================
	//
	// A_CStaffInitBlink
	//
	//============================================================================

	// [BB] clientsafe
	clientsafe action void A_CStaffInitBlink()
	{
		weaponspecial = (random[CStaffBlink]() >> 1) + 20;
	}

	//============================================================================
	//
	// A_CStaffCheckBlink
	//
	//============================================================================

	// [BB] clientsafe
	clientsafe action void A_CStaffCheckBlink()
	{
		if (player && player.ReadyWeapon)
		{
			if (!--weaponspecial)
			{
				player.SetPsprite(PSP_WEAPON, player.ReadyWeapon.FindState ("Blink"));
				weaponspecial = (random[CStaffBlink]() + 50) >> 2;
			}
			else 
			{
				A_WeaponReady();
			}
		}
	}
}

// Serpent Staff Missile ----------------------------------------------------

class CStaffMissile : Actor
{
	Default
	{
		Speed 22;
		Radius 12;
		Height 10;
		Damage 5;
		RenderStyle "Add";
		Projectile;
		DeathSound "ClericCStaffExplode";
		Obituary "$OB_MPCWEAPSTAFFR";
	}
	States
	{
	Spawn:
		CSSF DDEE 1 Bright A_CStaffMissileSlither;
		Loop;
	Death:
		CSSF FG 4 Bright;
		CSSF HI 3 Bright;
		Stop;
	}
	
	override int DoSpecialDamage (Actor target, int damage, Name damagetype)
	{
		// Cleric Serpent Staff does poison damage
		if (target.player)
		{
			target.player.PoisonPlayer (self, self.target, 20);
			damage >>= 1;
		}
		return damage;
	}
	
}

extend class Actor
{

	//============================================================================
	//
	// A_CStaffMissileSlither
	//
	//============================================================================

	// [BB] clientsafe
	clientsafe void A_CStaffMissileSlither()
	{
		A_Weave(3, 0, 1., 0.);
	}

}

// Serpent Staff Puff -------------------------------------------------------

class CStaffPuff : Actor
{
	Default
	{
		+NOBLOCKMAP +NOGRAVITY
		+PUFFONACTORS
		RenderStyle "Translucent";
		Alpha 0.6;
		SeeSound "ClericCStaffHitThing";
	}
	States
	{
	Spawn:
		FHFX STUVW 4;
		Stop;
	}
}
