/*
 * DamNums: by Xaser Acheron
 *
 * Events. 'Nuff said.
 */

class DamNumEventHandler : StaticEventHandler
{
	/*
	 * Raw DamNum spawner for "shotgun spray" mode.
	 * Everything else is handled by DamNumTracker.
	 */
	int SpriteTexHeight;
	TextureID SpriteTexture; Bool SpriteFlip; Vector2 SpriteScale;
	Vector3 spawnPos;
	override void WorldThingDamaged(WorldEvent e)
	{
		if (WoC_Dam_enabled && e.Thing.bIsMonster && WoC_Dam_spray && e.DamageType != 'Massacre' && e.Thing.CountInv("CurrentMaxHealth"))
		{
			[SpriteTexture, SpriteFlip, SpriteScale] = e.Thing.CurState.GetSpriteTexture(e.Thing.SpriteRotation);
			SpriteTexHeight = SpriteTexture ? TexMan.CheckRealHeight(SpriteTexture) : e.Thing.Height;
			spawnPos = e.Thing.pos + (0, 0, SpriteTexHeight - 8);
			DamNum.spawnDamageNumbers(spawnPos, e.Damage, e.DamageType);
		}
	}

	/*
	 * Create a DamNumTracker when an actor spawns or is revived.
	 */
	override void WorldThingSpawned(WorldEvent e)
	{
		if (e.Thing.bIsMonster && !e.Thing.CountInv("DamNumTracker"))
			DamNumTracker.Create(e.thing);
	}
	override void WorldThingRevived(WorldEvent e)
	{
		if (e.Thing.bIsMonster && !e.Thing.CountInv("DamNumTracker"))
			DamNumTracker.Create(e.thing);
	}
	
	void DoSpawnPlayerDamNum(PlayerPawn p)
	{
		if (p) p.GiveInventory("DamNumTracker", 1);
	}

	override void PlayerEntered(PlayerEvent e)
	{
		let p = players[e.PlayerNumber].mo;
		if (p) DoSpawnPlayerDamNum(p);
	}

	override void PlayerRespawned(PlayerEvent e)
	{
		let p = players[e.PlayerNumber].mo;
		if (p) DoSpawnPlayerDamNum(p);
	}
}

/*
 * The Tracker. Observes an actor, tracks damage changes over the
 * course of a tic, and spawns damage numbers once the tic is complete.
 */
class DamNumTracker : Inventory
{
	int currentHealth, SpriteTexHeight, TotalDamage;
	TextureID SpriteTexture; Bool SpriteFlip; Vector2 SpriteScale;
	Vector3 position;
	
	Default
	{
		Inventory.Amount 1;
		Inventory.MaxAmount 1;
		+INVENTORY.UNDROPPABLE
		+INVENTORY.UNTOSSABLE
	}
	/*
	 * Create & set up Tracker for the specified actor.
	 *
	 * TODO: remove this function if it turns out it isn't needed.
	 */
	static void Create(Actor thing)
	{
		if (thing) {
			thing.GiveInventoryType('DamNumTracker');
		}
	}

	/*
	 * Initialize the tracker just before its first tic.
	 */
	override void PostBeginPlay()
	{
		// Don't spawn a tracker if the tracked thing is gone or already dead.
		// This stops numbers from spawning for PE-spawned Lost Souls that die
		// instantly due to being in a wall. Was amusing, but unintentional. :P
		if (!self.owner || self.owner.health < 1) {
			self.Destroy();
			return;
		}

		self.currentHealth = self.owner.health;

		Super.PostBeginPlay();
	}

	/*
	 * Track damage and spawn stuff while the actor is alive.
	 */
	override void Tick()
	{
		if (self.owner) {
			if (WoC_Dam_enabled && !WoC_Dam_spray && self.owner.health != self.currentHealth) {
				self.SpawnNumbers();
				self.currentHealth = self.owner.health;
			}
		} else {
			// clean up after oneself just in case an actor gets
			// Thing_Remove'd or similar.
			self.Destroy();
		}
		Super.Tick();
	}

	/*
	 * Upon owner death, spawn the last round of numbers. This is necessary to
	 * cover the case where an actor is removed immediately upon death. 
	 */
	override void OwnerDied()
	{
		self.SpawnNumbers();
		self.owner.RemoveInventory(self);
	}

	/*
	 * Do the actual number spawn. There's a bit of calculation and checking
	 * that's common to all Tracker spawns, so it's done here for convenience.
	 */
	void SpawnNumbers()
	{
		if (WoC_Dam_enabled && !WoC_Dam_spray && self.owner && self.owner.DamageTypeReceived != 'Massacre')
		{
			[SpriteTexture, SpriteFlip, SpriteScale] = self.owner.CurState.GetSpriteTexture(self.owner.SpriteRotation);
			SpriteTexHeight = SpriteTexture ? TexMan.CheckRealHeight(SpriteTexture) : self.owner.Height;
			position = self.owner.pos + (0, 0, SpriteTexHeight - 8);
			totalDamage = 0;
			If(self.currentHealth > self.owner.health) //Damage
			{
				totalDamage = self.currentHealth - self.owner.health;
				DamNum.spawnDamageNumbers(position, totalDamage, self.owner.DamageTypeReceived);
			}
			Else If(self.currentHealth < self.owner.health && (self.owner.GetAge() > 2))
			{
				totalDamage =  self.owner.health - self.currentHealth;
				DamNum.spawnDamageNumbers(position, totalDamage, "Healing");
			}
		}
	}
}
