

/*
	ChebMaster's note:
	I strongly encourage re-using my code in other mods
	-- but, PRETTY PLEASE, invent your own prefix and search-and-replace "FBD_"
	   with that prefix of yours everywhere in the borrowed code.
	Because when someone *else* goes a step further building something
		even more awesome by cros-breeeding the mods they'd have a *colossal pain*
		if identifiers in those mods are the same.
	I encountered this problem when trying to run Franken Brutal Doom Monsters-only	
		on top of Project Brutality. It went pear-shaped because PB copies *tons*
		of BD code verbatim, with class names staying *the same* - and GZDoom 
		fucks class inheritance up *hard* when it tries resolving two PK3s
		that declare identical class names.
*/

//see const float FIXED_TO_FLOAT = 0.0000152587890625; // 1 / 65536.0 in Abstract.txt

ACTOR PreventSCOvercast: Inventory { inventory.maxamount 1 }

ACTOR SCCastGiver: CustomInventory 
{
	+INVENTORY.AUTOACTIVATE
	+INVENTORY.ALWAYSPICKUP
	inventory.maxamount 1
    States
    {
		Pickup:
			// inventory item's states executes in the context of the actor that item is in inventory of
			TNT1 A 0
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_MarkMonsterAsBeingAimedAt")
			Stop
    }
}

ACTOR FBD_PlayerAimAlerterDispenser
{
	Radius 1
	Height 1
	+NOCLIP
	+NOINTERACTION
	+SERVERSIDEONLY
	States
	{
		Spawn:
			TNT1 A 0 NODELAY A_RadiusGive("SCCastGiver", 200, RGF_MONSTERS | RGF_CUBE | RGF_NOSIGHT)
			TNT1 A 30//KYDB G 30
			Stop
	
	}
}

ACTOR HeadboxMkII 
{
	
	var int user_scale; // guaranteed to be set by the ACS script that creates us
	var int user_hbs; // packed result of script call. bits 0..7 x, bits 8..15 y, bits 16..23 z. 
		// bit 29 means must assign an unique TID and report it back to the monster
		// bit 30 means must warp
		//If zero, terminates self.
	var int user_use_headache;
	
	damagefactor "Taunt", 0.0 damagefactor "Blood", 0.0 damagefactor "BlueBlood", 0.0
	damagefactor "Head", 0.0 damagefactor "MinorHead", 0.0 damagefactor "KillMe", 0.0
	damagefactor "Control", 0.0 damagefactor "Trample", 0.0 damagefactor "GibRemoving", 0.0
	damagefactor "Alert", 0.0 damagefactor "SSG", 1.5 damagefactor "ExplosiveImpact", 0.0
	damagefactor "GibRemoving", 0.0 damagefactor "use", 0.0 damagefactor "SHOTGUN", 1.4
	damagefactor "TeleportRemover", 0.0  damagefactor "Stealth", 0.0
	
	damagefactor "FriendlyExplosion", 0.0
	damagefactor "YouMustDuck", 1.0
	damagefactor "Leg", 0.0
	
	//***Che this was fine on its own but it conflicts with other mods that add hitscan Fire damage
	// (and with Demon Tech Gun that does the same)
	// So I switch flamethrowers to "Flames" but allow headbox taking direct Fire damage
	//damagefactor "Fire", 0.0
	damagefactor "Fire", 0.8
	damagefactor "Flames", 0.0
	
	damagefactor "SniperBullet", 2.0 // a headshot with Mosin-Nagant (60 damage) 
		//a) counts as stun, because it inflicts 120 > 118 threshold
		//b) inflicts 240 on the monster	
	
	Health 2300
	Radius 7
	Height 18
	Mass 999999
	DamageType head
	BloodType "FBD_Blood", "FBD_SawBlood", "FBD_SawBlood"
	PainChance 255
	
	+SERVERSIDEONLY

	+QUICKTORETALIATE // always switch target to your last damager
	+PIERCEARMOR // meaningles but what if

	-COUNTKILL +NOTARGET
	+NOGRAVITY +NOTELEPORT +FORCERADIUSDMG -SOLID +NODAMAGETHRUST
	+THRUGHOST +NORADIUSDMG +GHOST +NOTAUTOAIMED
	+NOTRIGGER //Disables all line action (crossing, impacting, using, etc.) for the actor.

	+SHOOTABLE
	-THRUACTORS
	-NOPAIN	
	States
	{
		Spawn:
			TNT1 A 0 NODELAY A_GiveInventory("TargetIsAHeadbox")
		Follow:	
			KYDB N 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat")) // the script itself cannot set it 
			 // because it switches activator to the monster with no cheap way to go back
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			TNT1 A 0 A_JumpIf(tid || !((user_hbs >> 29) & 1), 2)
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_HeadboxAssumeTID")

			// Warping on the DECORATE side 
			//   since I tried warping on the ACS side and found SetActorPosition() wanting:
			//   it doesn't have nocheckposition so headbox freezes if pushed into a wall
			//   or another monster/decoration!
			// 0.0000152587890625 is 1/65536 (1.0 in fixed point)
			// DECORATE operates in 64-bit float doubles and so suffers no overflows
			// ACS operates in 32-bit 16:16 fixed point and so suffers horrible overflows but is very performant
			//   Both formats are much more precise than the single-precision 32-bit float
			
			// unpack the values from the packed 32-bit integer as we apply them:
			TNT1 A 0 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION) 
			// (green)
	
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgFollow")
			
			TNT1 A 1
			TNT1 A 0 A_CheckFlag("SHOOTABLE", "Follow", AAPTR_Tracer) // a fallback check in case the ACS failed 
				// also, automatically removes headbox from monsters performing a fatality
			TNT1 A 0 A_Die("Vanish")
			Goto Vanish
			
		DbgFollow:	
			KYDB O 1 // green
			TNT1 A 0 A_CheckFlag("SHOOTABLE", "Follow", AAPTR_Tracer) // a fallback check in case the ACS failed 
				// also, automatically removes headbox from monsters performing a fatality
			TNT1 A 0 A_Die("Vanish")
			Goto Vanish
			
		XDeath:	
		Death: // This should NOT happen, normally
			// BUT we can now make headboxes with limited hit points for weaker monsters!
			TNT1 A 0
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_OnHeadboxDeletion") // decrease their count
			TNT1 A 1 A_NoBlocking
			TNT1 A 0 A_ChangeFlag("ISMONSTER", 1) // for the master pointer to work
			TNT1 A 0 A_RearrangePointers(AAPTR_NULL, AAPTR_NULL, AAPTR_Tracer, 0)	// move tracer pointer to master
			TNT1 AAAAA 0 A_DamageMaster(9999, "HeadStun")
			TNT1 A 1
			Stop
			
		Vanish:
			TNT1 A 0 A_Die("Vanish")
		Death.Vanish:
			TNT1 A 0 
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_OnHeadboxDeletion") // decrease their count
			TNT1 A 1 A_NoBlocking
			Stop
		
		Inflict: 	
			//***Che Searched far and wide, there is *no* other way to convey attacker properly :(
			// Found all kinds of nifty methods, all rely on functions that do not exist in Zandronum.
			// Using the NOBLOCKMAP flag during this is also impossible.
			// So, two warps per hit :( Poor, poor performance :( Poor blockmaps :(
			
			// teleport to the monster's origin
			TNT1 A 0 A_Warp(AAPTR_Tracer,0,0,5,0,WARPF_NOCHECKPOSITION)
			// inflict AOE damage
			TNT1 A 0 A_Explode(CallAcs("FBD_HeadshotDamage", user_use_headache, 1),5,0)
			// return to our previous position
			TNT1 A 0 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			
			
			TNT1 A 0 A_ChangeFlag("NOPAIN", 1)
			TNT1 A 0 A_ChangeFlag("SHOOTABLE", 1)
			TNT1 A 0 A_ChangeFlag("THRUACTORS", 0)
			
			/*
			This wasn't working because health presumably was equal to spawnhealth
			The headache giving is now integrated into the FBD_HeadshotDamage script
			TNT1 A 0 A_JumpIf(health >= CallAcs("GetSpawnHealth"), 3) //4)
			TNT1 A 0 A_JumpIf(!user_use_headache, 2)
			TNT1 A 0 A_GiveInventory("Headache", (CallAcs("GetSpawnHealth") - health) / 10, AAPTR_TRACER)			
			TNT1 A 0 HealThing(-100) // restore to 100% health
			*/
			
			
			TNT1 A 0 HealThing(-100) // restore to 100% health
			
			// (magenta) damage accumulation frames (can only inflict headshot damage every 4th tic)
			TNT1 A 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat")) 
				// the script itself cannot set it 
				// because it switches activator to the monster with no cheap way to go back
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgInflict")
			
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			TNT1 A 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat")) 
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			TNT1 A 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat"))
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			
			TNT1 A 0 A_ChangeFlag("NOPAIN", 0)
			TNT1 A 0 A_CheckFlag("SHOOTABLE", "AfterInflicting", AAPTR_Tracer)
			TNT1 A 0 A_Die("Vanish")
			
		DbgInflict:	
			// magenta
			KYDB H 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			TNT1 A 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat")) 
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			KYDB H 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			TNT1 A 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat"))
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			KYDB H 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			TNT1 A 0 A_ChangeFlag("NOPAIN", 0)
			TNT1 A 0 A_CheckFlag("SHOOTABLE", "AfterInflicting", AAPTR_Tracer)
			TNT1 A 0 A_Die("Vanish")		
		
		AfterInflicting:
			TNT1 A 0 A_JumpIf(health < CallAcs("GetSpawnHealth"), "Inflict") // more damage accumulated during the accumulation frames
			Goto Follow

		Pain:
			TNT1 A 0
			// an one-tic long accumulation frame to gather *all* the damage from that tic			
			TNT1 A 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat")) 
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgPain")
			
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			Goto Pain2
			
		DbgPain:
			// yellow
			KYDB L 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			Goto Pain2
		
		Pain2:
			TNT1 A 0 A_JumpIf(CallAcs("FBD_HeadshotDamage") >= 298, "StunInstead")
			TNT1 A 0 A_SetDamageType("Head") 
			Goto Inflict			
			
		Pain.Plasma:
		Pain.Plasma2:
		Pain.SuperPlasma:
		Pain.GreenFire:
		Pain.Bfg10k:
			TNT1 A 0
			KYDB N 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat")) 
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgPainPlasma")
			
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			Goto PainPlasma2
			
		DbgPainPlasma:
			// yellow
			KYDB L 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			Goto PainPlasma2
			
		PainPlasma2:	
			TNT1 A 0 A_JumpIf(CallAcs("FBD_HeadshotDamage") >= 298, "StunInstead")
			TNT1 A 0 A_SetDamageType("HeadPlasma") 
			Goto Inflict			
			
		Pain.Saw: // "Saw" is the vertical swing damage of both chanisaw and axe		
			TNT1 A 0
			// an one-tic long accumulation frame to gather *all* the damage from that tic
			KYDB N 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat"))
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")

			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgPainSaw")
			
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			
			Goto PainSaw2
			
		DbgPainSaw:
			 // blue
			KYDB I 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			Goto PainSaw2
			
		PainSaw2:	
			TNT1 A 0 A_JumpIf(CallAcs("FBD_HeadshotDamage") >= 298, "StunInstead")
			TNT1 A 0 A_SetDamageType("Saw") // hitting the head simply doubles the damage
				// (Isn't this brokenly OP ? A vertical swing lands on the head most of the time!) 
			Goto Inflict			
		
		Pain.SniperBullet:
			TNT1 A 0
			KYDB N 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat"))
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgPainSniperBullet")
			
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			// Mosin-Nagant scoped headshots always stun!
			Goto StunInstead
		
		DbgPainSniperBullet:
			// blue
			KYDB I 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			Goto StunInstead
			
		StunInstead:	
			TNT1 A 0
			TNT1 A 0 A_SetDamageType("HeadStun")
			Goto Inflict
			
		Pain.Cut: // "Cut" is the horizontal swing damage of both chainsaw and axe
			TNT1 A 0
			KYDB N 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat"))
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgPainCut")
			
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			// *never* conveyed as stun!
			TNT1 A 0 A_SetDamageType("Decaptate") 
			Goto Inflict
			
		DbgPainCut:
			// red
			KYDB M 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			// *never* conveyed as stun!
			TNT1 A 0 A_SetDamageType("Decaptate") 
			Goto Inflict
			
		Pain.Fire:
			TNT1 A 0
			KYDB N 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat"))
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")
			
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgPainFire")
			
			TNT1 A 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			// *never* conveyed as stun!
			TNT1 A 0 A_SetDamageType("Flames") 
			Goto Inflict
		DbgPainFire:
			// red
			KYDB M 1 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION)
			// *never* conveyed as stun!
			TNT1 A 0 A_SetDamageType("Flames") 
			Goto Inflict			
			
		Pain.YouMustDuck:
			// do NOT convey as damage!
			TNT1 A 0
			TNT1 A 0 A_GiveInventory("DuckYouFool", 1, AAPTR_Tracer)
			TNT1 A 0 A_JumpIfHealthLower(2298, "Pain")
			TNT1 A 0 HealThing(2)
			Goto Follow
	}
}

ACTOR HeadboxMkIIChaosMarine: HeadboxMkII
{
	Radius 5
	Height 12
	Species "EvilMarines" // without this, when they use rocket launcher their rockets hit their headbox and explode
	
	//for debugging
	XScale 0.71
	YScale 0.67
}

ACTOR HeadboxMkIIRevenant: HeadboxMkII
{
	BloodType "Bone_DustFBD", "Bone_DustFBD", "Bone_DustFBD"
	+DONTRIP
}

ACTOR HeadboxMkIIMummy: HeadboxMkIIRevenant {
	Radius 5
	Height 12
	
	//for debugging
	XScale 0.71
	YScale 0.67
}

ACTOR HeadboxMkIINoble: HeadboxMkII {
	BloodType "Green_Blood", "GreenFBD_SawBlood", "GreenFBD_SawBlood"
	BloodColor "DarkGreen"
	Radius 12
	Height 22
	+DONTRIP
	Species "Bruisers" // without this, barrel thrown by baron explodes against baron's head

	//for debugging
	XScale 1.71
	YScale 1.22
	States
	{
		Spawn:
			TNT1 A 0 NODELAY A_GiveInventory("TargetIsAHeadbox")
			TNT1 A 0 A_SetUserVar("user_use_headache", 1) 
			/* 
				Only barons and knight use this feature
				(becoming wary of headshots after receiving that much headshot damage,
					basically they start dodge-leaping every time at receiving more)
				because those are the only monsters to *survive* that many headshots.
			*/
			Goto Follow
	}
}

// Duke of Hell was part of chebskies-EDAY, later ported to standalone FBD 21.5
ACTOR HeadboxMkIIDuke: HeadboxMkIINoble {
	Radius 19
	Height 35
	
	//for debugging
	XScale 2.74
	YScale 1.95
}

ACTOR HeadboxMkIIDyingNoble: HeadboxMkIINoble {
	-DONTRIP
	States
	{
		Spawn:
			TNT1 A 0 NODELAY A_GiveInventory("TargetIsAHeadbox")
			Goto Follow
	}
}

ACTOR HeadboxMkIICyber: HeadboxMkII {
	Radius 24
	Height 44
	damagefactor "Explosive", 0.7
	//***Che
	damagefactor "Bfg10k", 0.7
	+DONTRIP

	//for the debugging square to show the correct size
	XScale 3.43
	YScale 2.44
}

ACTOR HeadboxMkIITyrant: HeadboxMkIICyber {
	Radius 20
	Height 37
	damagefactor "Explosive", 0.85
	damagefactor "Bfg10k", 0.85

	//for the debugging square to show the correct size
	XScale 2.84
	YScale 2.03
}

ACTOR HeadboxMkIIAnnihilator: HeadboxMkIICyber {
	Radius 17 
	/*
		Mifghtily annoying, sprites have theit origin 5 pixels above the front hoof's bottom.
		The *modern* game engines shout "surprise, mother****!"
		 as they force-align such sprites to avoid clipping through the floor
		 when rendered via GPU
		 -- effectively raising them by 5 pixels, in this instance!
		So, headbox 24 tall becomes too short because it is 5*1.2 = 6 pixels below where
		it was calculated to be relative the sprite!
		
		FBD is *plagued* by such misalignments :(
		
	*/
	Height 30 //24
	XScale 2.43
	YScale 1.67
	Species "Cyberdemons"
}

ACTOR HeadboxMkIIE2M8Boss: HeadboxMkIICyber {
	Radius 34 
	Height 60 //48
	XScale 4.85
	YScale 3.33
	damagefactor "Desintegrate", 0.75 // bfg 9k, unmaker
	Species "Cyberdemons"
	+DONTRIP
}

ACTOR HeadboxMkIIMother: HeadboxMkIICyber {
	Radius 14
	Height 40
	Species "Motherdemons" // otherwise her big fireball explodes hitting it

	//for the debugging square to show the correct size
	XScale 2.0
	YScale 2.22
}

ACTOR HeadboxMkIIVolcabus: HeadboxMkII {
	Radius 14
	Height 24
	+DONTRIP

	//for debugging
	XScale 2.0
	YScale 1.33
}

ACTOR HeadboxMkIITankWeakSpot: HeadboxMkII {
	damagefactor "Shotgun", 0.4
	
	// vulnerable to flames:
	-NORADIUSDMG 
	damagefactor "Fire", 0.5
	damagefactor "Flames", 0.5
	damagefactor "Burn", 0.5
	damagefactor "GreenFire", 0.5	
	
	// but still immune to explosion splash damage:
	//  (otherwise, artillery tank kills itself by launching its rockets)
	damagefactor "ExplosiveImpact", 0.0
	damagefactor "FriendlyExplosion", 0.0
	damagefactor "Shrapnel", 0.0 // if the hand grenade wants in on the action, it can use its "Shotgun" type projectiles
	damagefactor "CauseWaterSplash", 0.0
	damagefactor "TeleportRemover", 0.0
	DamageFactor "CallingTheBaronAFaggot", 0.0
	damagefactor "Avoid", 0.0
	damagefactor "DontCallTheBaron", 0.0
	DamageFactor "CauseSplash", 0.0 DamageFactor "CauseObjectsToSplashSlime", 0.0 DamageFactor "CauseObjectsToSplashNukage", 0.0
	DamageFactor "CauseObjectsToSplashBlood", 0.0 DamageFactor "CauseObjectsToSplashLava", 0.0
	damagefactor "Blood", 0.0 damagefactor "BlueBlood", 0.0 damagefactor "GreenBlood", 0.0
	
	-THRUACTORS
	+THRUSPECIES
	Species "EnemyTank"
	Radius 24
	Height 44
	
	//for debugging
	XScale 3.43
	YScale 2.44	
	
	BloodType "TankEngineBlood", "TankEngineBlood", "TankEngineBlood"
}

ACTOR HeadboxMkIIMechCockpit: HeadboxMkII {
	damagefactor "Shotgun", 1.0
	-THRUACTORS
	+THRUSPECIES
	Species "EnemyMech"
	Radius 24
	Height 44
	
	//for debugging
	XScale 3.43
	YScale 2.44		
	
	damagefactor "ExplosiveImpact", 0.0
	damagefactor "FriendlyExplosion", 0.0
	damagefactor "Shrapnel", 0.0 
	damagefactor "CauseWaterSplash", 0.0
	damagefactor "TeleportRemover", 0.0
	DamageFactor "CallingTheBaronAFaggot", 0.0
	damagefactor "Avoid", 0.0
	damagefactor "DontCallTheBaron", 0.0
	DamageFactor "CauseSplash", 0.0 DamageFactor "CauseObjectsToSplashSlime", 0.0 DamageFactor "CauseObjectsToSplashNukage", 0.0
	DamageFactor "CauseObjectsToSplashBlood", 0.0 DamageFactor "CauseObjectsToSplashLava", 0.0
	damagefactor "Blood", 0.0 damagefactor "BlueBlood", 0.0 damagefactor "GreenBlood", 0.0	
	
	BloodType "MecCockpitBlood", "MecCockpitBlood", "MecCockpitBlood"
	
/*
	damagefactor "RailAvoid", 1.0 // NO USE: it has thrughost and headboxes are ghosts!
	PainChance "RailAvoid", 255			
	
	States 
	{
		Pain.RailAvoid:
			// do NOT convey as damage!
			TNT1 A 0
			TNT1 A 0 A_JumpIfHealthLower(2290, "Pain")
			TNT1 A 0 HealThing(10)
			TNT1 A 0 A_GiveInventory("DuckYouFool", 1, AAPTR_TRACER)
			Goto Follow		
	}
*/	
}


// Lost Soul hackery -----------------

ACTOR HeadboxMkIILostSoul: HeadboxMkII
{
	// has no physical presence whatsoever, utterly undetectable by other actors
	-SHOOTABLE
	+NOINTERACTION
	+NOCLIP
	
	States {
		Spawn:
			TNT1 A 0
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_StartLSFlames")
			Goto Follow
		Follow:	
			KYDB N 0 A_SetUserVar("user_hbs", CallAcs("FBD_HeadboxHeartbeat")) // the script itself cannot set it 
			 // because it switches activator to the monster with no cheap way to go back
			TNT1 A 0 A_JumpIf(!user_hbs, "Vanish")

			TNT1 A 0 A_Warp(AAPTR_Tracer, FIXED_TO_FLOAT * user_scale * ((user_hbs & 255) - 128), FIXED_TO_FLOAT * user_scale * (((user_hbs >> 8) & 255) - 128) , FIXED_TO_FLOAT * user_scale * ((user_hbs >> 16) & 127), 0, WARPF_NOCHECKPOSITION | WARPF_COPYINTERPOLATION) 
			// (green)
	
			TNT1 A 0 A_JumpIf(CallAcs("DoDebugLogging"), "DbgFollow")
			
			TNT1 A 1
			TNT1 A 0 A_CheckFlag("SHOOTABLE", "Follow", AAPTR_Tracer) // a fallback check in case the ACS failed 
				// also, automatically removes headbox from monsters performing a fatality
			TNT1 A 0 A_Die("Vanish")
			Goto Vanish
			
		DbgFollow:	
			KYDB N 1 // gray
			TNT1 A 0 A_CheckFlag("SHOOTABLE", "Follow", AAPTR_Tracer) // a fallback check in case the ACS failed 
				// also, automatically removes headbox from monsters performing a fatality
			TNT1 A 0 A_Die("Vanish")
			Goto Vanish			
			
		Vanish:
			TNT1 A 0 A_Die("Vanish")
		Death:
		Death.Vanish:
			TNT1 A 0
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_StopLSFlames")
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_OnHeadboxDeletion") // decrease their count
			TNT1 A 3
			Stop
	}
}

ACTOR HeadboxMkIIHater: HeadboxMkIILostSoul
{
	States
	{
		Spawn:
			TNT1 A 0
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_StartLSFlames", 1) // agony particles rather than flame particles
			Goto Follow	
	}
}


// EDAY bosses -------------------------------------------------------------------------------------

ACTOR HeadboxMkIIInfernal: HeadboxMkIICyber {
	Height 60
	YScale 3.33
	damagefactor "Desintegrate", 0.6 // bfg 9000 & unmaker -- only 120% damage
}

ACTOR HeadboxMkIICyberlord: HeadboxMkIICyber {
	Radius 70 
	Height 125 //100
	XScale 10.0
	YScale 6.94
	// inherited damagefactor "Explosive", 0.7	damagefactor "Bfg10k", 0.7
	damagefactor "Desintegrate", 0.6 // bfg 9k, unmaker
	Species "Cyberdemons" // otherwise his fire breath is blocked by his own head!
	+DONTRIP
}

ACTOR HeadboxMkIIYfrit: HeadboxMkII {
	BloodType "FieryBlood", "FieryBloodSaw", "FieryBlood"
	bloodcolor None
	Radius 12
	// Height 17 - NOT 22 as for knight and barons
	+DONTRIP

	//for debugging
	XScale 1.71
	
	
	damagefactor "Flames", 0.0
	damagefactor "Fire", 0.1
	damagefactor "Burn", 0.3
}