
// NOTE the project brutality's sprites had their origin raised by 12 to make the monster more compact!

ACTOR FBD_Cacolord: FBD_Cacodemon 17880
{
	//$category "FBD Monsters"
	
	Tag "$CACOLORD"
	Obituary "$CACOLORD_O"
	
	SeeSound "cacolord/sight"
	PainSound "cacolord/pain"
	DeathSound "cacolord/death"
	ActiveSound "cacolord/active"
	
	var int user_head_scale; // scale in percent relative to cacodemon
		// projectile firing offsets are calculated from this
	var int user_stun_limit;
	
	Health 1300
	Scale 0.8
	Radius 38
	Height 64
	
	Translation "168:174=[255,255,255]:[225,225,255]", "175:191=192:207", "80:111=168:187", "5:8=[89,0,0]:[0,0,0]"
	
	PainChance "Ice", 96
	
	
	/*
	//***Che: NOTE, the "BRIGHT" frames are a stop-gap, I will implement brightmaps at a later post-release patch!
		A - A.
		B, C - left and right slightly (like pain elemental's walking frames)
		DEF - melee attack (mouth opening with no glow, arms thrown wide)
		GHI - breath attack (mouth opening with glow inside)
			Note: as with caclet, the frames EF and HI only differ in presence of glow, otherwise the pose is pixel-identic (not true for D and G, mouth shape shifts one pixel). This allows for flickering charge up like caclets do
		JK - casting, tilted a bit forward with palms forward. Frames are identical but in K palms are red (blue after translation)
		L - pain
		M..V - death
		
		So, my frankenstein he has *NO* melee attack, rather breathes a short-ranged lightning beam (initiation range 300, missile range 500) - that state is still called "Melee" for ease of editing.
		I use regular GHI for this attack
		
		For his regular ranged attack, I use DEK-keep firing-KJ since he fires six caco balls from his palms
	
	*/
	
	+FLOORCLIP
	+SPECIALFLOORCLIP
	
	States {
		Spawn:
			OVER A 0 NODELAY ACS_NamedExecuteWithResult("FBD_RunMonster", 0, 100)
			OVER A 0 A_SetUserVar("user_stun_limit", 8)
			OVER A 1 A_GiveInventory("CacoStamina", 100)
			Goto Stand
		Stand:	
			OVER A 10 A_Look
			Loop

		Pain.Ice:
			"----" A 12 A_Pain
			Goto Pain
		
		
		WaitTargetsFatalityOut:
			OVER L 1 ACS_NamedExecuteWithResult("FBD_PlayActiveSound") //A_PlaySound("cacolord/sight", CHAN_VOICE)
			OVER L 1 A_FaceTarget
			OVER L 6 A_Recoil(1)
			OVER L 1 A_Jump(128, "WTF3")
			OVER L Random(6,24)
		WTF2:
			OVER L 6
			OVER L 1 A_Jump(256, "AvoidLeft", "AvoidRight", "See")
			Wait
		WTF3: 
			OVER CBCBCBCB 3
			OVER L 1 A_Jump(256, "AvoidLeft", "AvoidRight", "See")
			Wait
		
		
		Pain.Avoid: // inflicted by the tracer "Alerter" fired by: the vanilla bfg9000; the revenant launcher; the minigun when beginning to spin up; the rocket launcher. 
			TNT1 A 0
			TNT1 A 0 HealThing(1)
			TNT1 A 0 A_JumpIf(user_sleeping, "Flatfooted") // dont dodge if unaware
			
			TNT1 A 0 A_JumpIfInventory("CacoStamina", 15, 1) // max two such dodges, then cooldown
			Goto Flatfooted // no dodging if out of juice
			
			TNT1 A 0 A_TakeInventory("CacoStamina", 15)
			OVER L 1 A_Jump(256, "AvoidLeft", "AvoidRight")
			Wait
			//Goto AvoidLeft
		  
		AvoidLeft:
			OVER C 1 A_FaceTarget
			TNT1 A 0 ThrustThing(angle*256/360+192, 10, 0, 0)
			OVER CCCCC 2 
			Goto Missile
		AvoidRight:
			OVER B 1 A_FaceTarget
			TNT1 A 0 ThrustThing(angle*256/360+64, 10, 0, 0)
			OVER BBBBB 2
			Goto Missile
		Flatfooted:
			TNT1 A 0 A_FaceTarget
			TNT1 A 0 A_SetUserVar("user_sleeping", 0)
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_PlaySeeSound") //A_PlaySound("cacolord/sight", CHAN_VOICE)
			OVER BCLJA 4 
			Goto See
		
		Idle: // without this, the game engine puts him into his Spawn state when he loses target 
				//-- and that wrecks havok with the init scripts!
			OVER A 1 A_ClearTarget
			TNT1 A 0 A_SetUserVar("user_sleeping", 1)
			
		SearchPlayer:
			TNT1 A 0 A_JumpIfInventory("EnemyMemory", 1, 2) // this causes to clear target on the second loop
			TNT1 A 0 A_ClearTarget
			TNT1 A 0 A_TakeInventory("EnemyMemory", 40)
			OVER A 5 A_Look
			OVER C 5
			TNT1 A 0 A_SetAngle(angle - 30)
			OVER A 5 A_Look
			OVER B 5
			TNT1 A 0 A_SetAngle(angle + 30)
			OVER A 5 A_Look
			OVER B 5
			TNT1 A 0 A_SetAngle(angle + 30)
			OVER A 5 A_Look
			OVER C 5
			TNT1 A 0 A_SetAngle(angle - 30)
			
			
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			TNT1 A 0 A_GiveInventory("CacoStamina", 30)
			
			TNT1 A 0 A_Jump(128, "SearchPlayer")
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			OVER A 0 A_Wander
			OVER A 2 A_Look
			TNT1 A 0 A_GiveInventory("CacoStamina", 30)
			Goto SearchPlayer
		VanillaSee:	
			OVER A 3 A_Chase
			Loop
		See:
			TNT1 A 0
	
			// slaughtermap manage
			TNT1 A 0 A_JumpIf(!user_sleeping, 3) // forgo the expensive sight check if already awake
			TNT1 A 0 A_CheckSight(2) // do not consider ourselves awake if none of the players can see us
			TNT1 A 0 A_SetUserVar("user_sleeping", 0)
			
			TNT1 A 0 A_JumpIfInTargetInventory("IsPlayer", 1, "ChasePlayer")
			TNT1 A 0 A_JumpIfInTargetLOS("SeeContinue", 0, JLOSF_DEADNOJUMP)
			TNT1 A 0 A_CheckSight("See2")
			
		SeeContinue:	
			OVER A 2 A_Chase
			OVER AA 2 A_Chase ("","")
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 1)
			
			TNT1 A 0 A_CheckSight("See2")
			OVER A 2 A_Chase
			OVER AA 2 A_Chase ("","")
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 1)

			TNT1 A 0 A_CheckSight("See2")
			OVER A 2 A_Chase
			OVER AA 2 A_Chase ("","")
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 1)

			TNT1 A 0 A_CheckSight("See2")
			OVER A 2 A_Chase
			OVER AA 2 A_Chase ("","")
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 1)

			TNT1 A 0 A_CheckSight("See2")
			OVER A 2 A_Chase
			OVER AA 2 A_Chase ("","")
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 1)

			TNT1 A 0 A_CheckSight("See2")
			OVER A 2 A_Chase
			OVER AA 2 A_Chase ("","")
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 1)
			TNT1 A 0 A_GiveInventory("CacoStamina", 10)
			
			Loop
			
		See2:
			OVER AAAAAA 2 A_Chase
			TNT1 A 0 A_GiveInventory("CacoStamina", 15)
			TNT1 A 0 A_JumpIfInventory("EnemyMemory", 25, "Idle")
			TNT1 A 0 A_GiveInventory("EnemyMemory", 1)
			Goto See
		ForgetQuicker:
			OVER AAAAAA 2 A_Chase
			TNT1 A 0 A_GiveInventory("CacoStamina", 15)
			TNT1 A 0 A_JumpIfInventory("EnemyMemory", 25, "Idle")
			TNT1 A 0 A_GiveInventory("EnemyMemory", 4)
			OVER AAAAAA 2 A_Wander
			TNT1 A 0 A_GiveInventory("CacoStamina", 15)
			TNT1 A 0 A_JumpIfInventory("EnemyMemory", 25, "Idle")
			TNT1 A 0 A_GiveInventory("EnemyMemory", 4)
			Goto See

		ChasePlayer:
			OVER A 2 A_Chase("", "")
			TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), "ForgetQuicker")
			// the Hexen boss dodging only works closer than 640 anyway(hardcoded in C++)
			TNT1 A 0 A_JumpIfInTargetLOS("Dance", 30, JLOSF_DEADNOJUMP | JLOSF_CLOSENOSIGHT, 400, 180)
			
			OVER A 2 A_Chase
			OVER AA 2 A_Chase ("","")
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 5)	
			TNT1 A 0 A_GiveInventory("CacoStamina", 10)
			TNT1 A 0 A_JumpIfTargetInLOS("ChasePlayer")
			Goto See2

		Dance:
			TNT1 A 0 A_JumpIfInventory("CacoStamina", 6, 1) // skip the goto
			Goto SeeContinue // out of juice
			TNT1 A 0 A_TakeInventory("CacoStamina", 6)
			OVER A 4 A_Chase
			OVER B 4 A_Chase ("","", CHF_FASTCHASE) // hexen boss dodging
			OVER A 4 A_Chase
			OVER C 4 A_Chase ("","", CHF_FASTCHASE) // hexen boss dodging
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 10)
			TNT1 A 0 A_JumpIfTargetInLOS("ChasePlayer")
			Goto See2
			
		DanceThenMissile:
			OVER A 2 A_FaceTarget
			OVER B 4 A_Chase ("","MissileAfterAvoid", CHF_FASTCHASE) // hexen boss dodging
			OVER A 2 A_Recoil(2)
			OVER C 4 A_Chase ("","MissileAfterAvoid", CHF_FASTCHASE) // hexen boss dodging
			OVER A 2 A_Recoil(3)
			OVER B 4 A_Chase ("","MissileAfterAvoid", CHF_FASTCHASE) // hexen boss dodging
			OVER A 2 A_FaceTarget
			OVER C 4 A_Chase ("","MissileAfterAvoid", CHF_FASTCHASE) // hexen boss dodging
			OVER A 2 A_Recoil(1)
			OVER B 4 A_Chase ("","MissileAfterAvoid", CHF_FASTCHASE) // hexen boss dodging
			OVER A 2 A_Recoil(1)
			OVER C 4 A_Chase ("","MissileAfterAvoid", CHF_FASTCHASE) // hexen boss dodging
			TNT1 A 0 A_JumpIfTargetInLOS("Melee", 300, JLOSF_DEADNOJUMP, 99, 0)
			TNT1 A 0 A_TakeInventory("EnemyMemory", 10)
			TNT1 A 0 A_JumpIfTargetInLOS("MissileAfterAvoid")
			Goto ChasePlayer			
			
	
		Missile:
			TNT1 A 0
			
			// Kinslayer check:	
			TNT1 A 0 A_JumpIf(!CheckClass("FBD_Cacodemon", AAPTR_TARGET, true), 2)
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_InfightFriendlyFireOn")	
			
			TNT1 A 0 A_TakeInventory("EnemyMemory", 30)
			TNT1 A 0 A_JumpIfCloser(300, "Melee")
			
			TNT1 A 0 A_FaceTarget
			TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), "MissileAfterAvoid")
			TNT1 A 0 A_Jump (198, "MissileAfterAvoid") // only 23% probability to side-dash before attacking. BUT in case of our target being a player, we already perform aggressive side-dashing in our Dance state, into which we get if in player's 30-degree frontal segment (those checks don't give a flying crap about *vertical* aim, purely 2d!)
			
			TNT1 A 0 A_JumpIfInventory("CacoStamina", 15, 2) //1) // max two such dodges, then cooldown
			//Goto MissileAfterAvoid // no dodging if out of juice
			OVER L 1 A_Jump(256, "MissileAfterAvoid")
			Wait
			
			// the Hexen boss dodging only works closer than 640 anyway (hardcoded in C++)
			TNT1 A 0 A_JumpIfCloser(700, "Avoid")
			
			//Goto MissileAfterAvoid
			OVER L 1 A_Jump(256, "MissileAfterAvoid")
			Wait
			
		Avoid:
			
			TNT1 A 0 A_TakeInventory("CacoStamina", 15)
			
			TNT1 A 0 A_JumpIfInTargetInventory("IsPlayer", 1, "AvoidPlayer")
			
			OVER A 6 A_Chase ("","", CHF_FASTCHASE) // hexen boss dodging //A_FastChase
			NULL A 0 A_FaceTarget
			OVER C 6 A_Chase ("","", CHF_FASTCHASE) // hexen boss dodging //A_FastChase
			NULL A 0 A_FaceTarget
			OVER A 6 A_Chase ("","", CHF_FASTCHASE) // hexen boss dodging //A_FastChase
			NULL A 0 A_FaceTarget
			OVER B 6 A_Chase ("","", CHF_FASTCHASE) // hexen boss dodging //A_FastChase

			//Goto MissileAfterAvoid
			OVER L 1 A_Jump(256, "MissileAfterAvoid")
			Wait
			
		AvoidPlayer:
			
			TNT1 A 0 A_JumpIfInTargetLOS("DanceThenMissile", 30, JLOSF_DEADNOJUMP | JLOSF_CLOSENOSIGHT, 700, 180)
			Goto ChasePlayer
			
		MissileAfterAvoid:	
			
			//DE K-keep firing-K J
			
			OVER DEJ 4
			
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
			
			OVER K 2 BRIGHT
			//lower arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
			
			OVER J 6			
			
			OVER K 2 BRIGHT
			//lower arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
			
			OVER J 4

			OVER K 2 BRIGHT
			//lower arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("VfxCacoBallBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			
			OVER J 2			
			
			TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), "SixShotBlindfire")
			TNT1 A 0 A_JumpIfTargetInLOS("SixShotAutoaimed")
			// otherwise, blindfire
		
		SixShotBlindfire:
			// not autoaimed
			// CMF_AIMOFFSET to make them travel in formation, with the same pitch			
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Minus2", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Plus1", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("FBD_CacoBall", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Plus3", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Minus1", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Plus2", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)			
			OVER K 4 BRIGHT
			Goto See
			
		SixShotAutoaimed:	
			// autoaimed, each one individually -- intersect at you.
			TNT1 A 0 A_FaceTarget
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Minus2", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, 0, CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Plus1", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0,0, CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("FBD_CacoBall", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, 0, CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Plus3", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, 0, CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Minus1", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, 0, CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("FBD_CacoBall_Plus2", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, 0, CMF_SAVEPITCH)			
			OVER K 4 BRIGHT
			Goto See
			
		Melee: // actually a limited-range lightning bolt
			TNT1 A 0
			
			TNT1 A 0 A_JumpIfInTargetInventory("GoFatality", 1, "WaitTargetsFatalityOut")
			
			TNT1 A 0 A_JumpIf(waterlevel > 0, "MissileAfterAvoid")
			
			// Kinslayer check:	
			TNT1 A 0 A_JumpIf(!CheckClass("FBD_Cacodemon", AAPTR_TARGET, true), 2)
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_InfightFriendlyFireOn")	
			
			TNT1 A 0 A_Facetarget
			OVER A 4 A_Recoil(5)
			OVER GHI 4 BRIGHT A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			TNT1 A 0 A_PlaySound("cacolord/vomit", CHAN_VOICE)			
			OVER FF 4 A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
				
			OVER I 4 BRIGHT A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)	
			OVER F 4 A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			OVER II 4 BRIGHT A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)	
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
			OVER F 4 A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			
			TNT1 A 0 A_JumpIf(waterlevel > 0, "ShortUnderwater")
			
			OVER IIIII 4 BRIGHT A_CustomMissile("CacolordLightning", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH, 0.0)
			OVER HG 8 BRIGHT
			OVER LA 6
			Goto See
			
		ShortUnderwater:
			
			OVER F 2
			TNT1 A 0 A_PlaySound("KYBFGSPR", 7)
			OVER F 1 
			"----" AAAA 0 A_CustomMissile("BUBULZ",FIXED_TO_FLOAT * user_head_scale* 33.0,0,angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			"----" AAAA 0 A_CustomMissile("ExplosionBubulz",FIXED_TO_FLOAT * user_head_scale* 33.0,0,angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE | CMF_OFFSETPITCH | CMF_SAVEPITCH)
			TNT1 A 0 A_RadiusGive("ElectricShock", 200, RGF_MONSTERS | RGF_PLAYERS) 
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_ElectrocuteSelf", 50)
			OVER F 15
			Goto Pain
		
		Pain:
			TNT1 A 0
			TNT1 A 0 A_SetUserVar("user_stun_limit", user_stun_limit - 1)
			TNT1 A 0 A_JumpIf(user_stun_limit < 0, "HadEnough")

			// Just pain			
	
			OVER L 3
			OVER L 3 A_Pain
			TNT1 A 0 A_JumpIfInventory("CacoStamina", 15, "MaybeAvoidAfterPain")
			OVER L 6
			
			//Goto See
			"----" A 1 A_Jump(256, "MissileAfterAvoid")
			Wait
			
		HadEnough:	
			"----" A 0 A_ChangeFlag("NOPAIN", 1)
			"----" A 0 A_ChangeFlag("MISSILEMORE", 1)
			"----" A 0 A_ChangeFlag("MISSILEEVENMORE", 1)
			"----" A 1 A_Jump(256, "MissileAfterAvoid")
			Wait
			
		MaybeAvoidAfterPain:
			TNT1 A 0 A_Jump (128, "Avoid")
			OVER L 6
			Goto See			
			
		Pain.Argent:
			
			//TNT1 A 0 A_ClearTarget
			TNT1 A 0 HealThing(150)
			TNT1 A 0 ACS_NamedExecuteWithResult("DisplayArgentDischarge", 35, 60, 0)	
			
			OVER L 3 A_Pain
			OVER LCB 3 
			OVER LCLBLCLB 2 A_Pain
			TNT1 A 0 A_JumpIfTargetInLOS("Missile")
			Goto See			

		Pain.Kick:
		Pain.HeavyImpact:
			TNT1 A 0 A_FaceTarget
			OVER L 6 A_Recoil(5)
			OVER L 6 A_Pain
			OVER J 10
			Goto See
			
		Pain.Cut:
		Pain.Saw:
			TNT1 A 0 A_Stop
			OVER LCLB 3
			Goto See

		// only one death but must override *ALL* the inherited caco's deaths!
		Death:
		XDeath:
		Death.SSG:
		Death.ExtremePunches:
		Death.Desintegrate:
		Death.Bfg10k: //***Che changed damage type from extreme to custom
		Death.Massacre:
		Death.SuperPlasma:
		Death.Plasma: 
		Death.Plasma2:
		Death.Electric:	
		Death.Brutal:
		Death.Blast:
		Death.Railgun:	
		Death.SniperBullet:
		Death.Bullet792:			
		Death.Minigun:
		Death.cut:
		Death.ExplosiveImpact:
		Death.FriendlyExplosion: 
		Death.saw:
		Death.Shotgun:	
			OVER L 1 A_ChangeFlag("NOGRAVITY", 1)
			OVER L 1 A_Jump(256, "Meatsplode")
			Wait
			
		Death.Fatality:
			TNT1 A 0 A_NoBlocking
			TNT1 A 0 A_Pain
			TNT1 A 0 A_JumpIfIntargetInventory("FistsSelected", 1, 1)
			Goto Death
			TNT1 A 0 A_GiveToTarget("GoFatality", 1)
			TNT1 A 0 A_FaceTarget
			TNT1 A 0 ACS_NamedExecuteWithResult("DropFatalityBonuses", 15, 15)

			TNT1 A 0 A_GiveToTarget("ErsatzFatalityBlue", 1)
			TNT1 A 0 A_ChangeFlag("NOGRAVITY", 1)
			OVER L 1 A_PAIN
			OVER LLLLLLLLLL 2 A_CustomMissile ("BlueBloodMistBig", FIXED_TO_FLOAT * user_head_scale* 40.0, 0, random (0, 360), 2, random (-20, 70))
			
			TNT1 A 0 A_ChangeFlag("CORPSE", 0) // fatalized monsters are not raiseable
			
			OVER L 1 A_Jump(256, "Meatsplode")
			Wait

		Meatsplode:
			OVER MMNNOO 1 A_CustomMissile ("BlueBloodMistBig", FIXED_TO_FLOAT * user_head_scale* 40.0, 0, random (0, 360), 2, random (-20, 70))

			TNT1 A 0 A_Scream
			TNT1 A 0 A_NoBlocking
			TNT1 A 0 A_Stop
			TNT1 A 0 A_ChangeFlag("NOGRAVITY", 1) 
			
			TNT1 A 0 A_CustomMissile ("CacoLordXDeath", 0, 0, random (0, 360), CMF_AIMDIRECTION, random (0, 160))
			OVER PQRSTUV 1 A_CustomMissile("CacolordLightning128", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, angle + Random(30, 330), CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, Random(-70, 70)) //A_CustomMissile ("BlueBloodMistBig", FIXED_TO_FLOAT * user_head_scale* 40.0, 0, random (0, 360), 2, random (-20, 70))
			TNT1 A 0 A_ChangeFlag("NOGRAVITY", 0)
			TNT1 A 0 A_FaceTarget
			TNT1 AAAAAAAAAAAA 4 A_CustomMissile("CacolordLightning128", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, angle + Random(30, 330), CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, Random(-70, 70))
			Goto RestInPieces
			
		RestInPieces:
			TNT1 A 0 A_ChangeFlag("NOGRAVITY", 1)
			TNT1 A -1 //***Che: Gibbed monsters -- ONLY the gibbed monsters -- may use this
				//   to auto-respawn on nightmare and be raised by viles.
				// Employing this on a destructible corpse results in that corpse
				//   respawning on nightmare as a corpse (or worse, as a burning hollering demon)
				// If a monster's death state spawns a destructible corpse,
				//   the respawning/raising is relegated to that corpse
				//   and the monster MUST use Stop instead
			Stop			
			
		Raise:
			TNT1 A 0
			TNT1 A 0 A_SpawnItemEx("StandaloneBlueRezSfx",0,0,0, 0,0,0, 0,SXF_NOCHECKPOSITION,0)
			TNT1 A 0 A_ChangeFlag("NOGRAVITY", 1)
			OVER V 3 A_UnSetFloorClip
			OVER UTSRQPONM 3
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_CustomizeOnRez") // it runs OnRezMapScript
				// if the map prpvides one
			Goto See
			
		FallbackRaise: // we were put into this state by the superarchvile AOE raising, our height is hopelessly kaput and we have to spawn a substitute
			"----" A 0 A_GiveInventory("RezzingNow")
			"----" A 0 A_ChangeFlag("CORPSE", 0)
			"----" A 0 A_ChangeFlag("COUNTKILL", 0)
			"----" A 0 A_ChangeFlag("SHOOTABLE", 0)
			"----" A -1 ACS_NamedExecuteWithResult("FallbackRezMkII", 606) // see _mob_list.xlsx
			Stop
			
		FallbackRezSuccess:
			TNT1 A 0 A_SpawnItemEx("StandaloneBlueRezSfx",0,0,0, 0,0,0, 0,SXF_NOCHECKPOSITION,0)
			TNT1 A 30
			Stop			
		
		
		Crush:
			TNT1 A 0
			TNT1 A 0
			TNT1 AAAAAA 0 A_SpawnItem("BodyRemovalThing")
			TNT1 A 1 A_XScream
			
			TNT1 A -1 // be rezzable
			Stop

		Pain.KillMe:
		Pain.Taunt:
			TNT1 A 0 HealThing(1)
			Goto Missile
			
		Death.fire:
		Death.Flames:
			TNT1 A 0
			TNT1 A 0 A_Playsound("props/redfire", CHAN_7)
			Goto Death
			
		Death.KillMe:
		Death.Taunt:
		Death.Avoid:
			// aggroes at you but dies from the strain while bleeding from his ass
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_PlaySeeSound") //A_PlaySound("cacolord/sight", CHAN_VOICE)
			OVER B 4 A_Facetarget
			OVER C 4 A_Recoil(-5)
			OVER ABACABAC 2
			OVER L 3 A_Pain
			OVER LLLLLMMMM 3 A_CustomMissile ("Blue_FlyingBlood", -15, 20, random (160, 200), CMF_AIMDIRECTION, random (-40, -20))
			Goto Death

		Death.Ice:
		Death.Freeze:
		Death.Frost:
		Death.IOS_Frost:
			TNT1 A 0
			TNT1 A 0 A_PlaySound("ice/shatter", CHAN_7)
			TNT1 AAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk1", FIXED_TO_FLOAT * user_head_scale* 48.0, 0, random (0, 360), 2, random (0, 160))
			TNT1 AAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk2", FIXED_TO_FLOAT * user_head_scale* 48.0, 0, random (0, 360), 2, random (0, 160))
			TNT1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk3", FIXED_TO_FLOAT * user_head_scale* 48.0, 0, random (0, 360), 2, random (40, 120))
		
			Goto Death
	}
}

ACTOR VfxCacoBallBeingPrepared
{
	Radius 6
	Height 6
	Speed 0
	FastSpeed 0
	Damage (random(0,0))
	Projectile 
	+NOINTERACTION
	+FORCEXYBILLBOARD
	RenderStyle Add
	Alpha 0.95
    damagetype Plasma
	Scale 0.3
	States
	{
		Spawn:
		Death:
			PBAL DE 1 BRIGHT
			TNT1 A 1 A_PlaySound("KYBFGSPR")
			Stop
	}
}

ACTOR VfxLightningBeingPrepared
{
	Radius 6
	Height 6
	Speed 20
	FastSpeed 0
	Damage (random(0,0))
	Projectile 
	+NOINTERACTION
	+FORCEXYBILLBOARD
	RenderStyle Add
	Alpha 0.95
    damagetype Plasma
	
	// instead of using pre-colored blue SH1K we use the *red* SHOQ and palette-shift it to a bit more muted white-bluish gradient
	Translation "175:191=192:204", "39:47=201:201"
	States
	{
		Spawn:
		Death:
			TNT1 A 1 NODELAY A_PlaySound("KYBFGSPR")
			TNT1 A 0 A_Stop
			TNT1 A 0 A_SetScale(random(0,1) ? 0.7 : -0.7, random(0,1) ? 0.7 : -0.7)
			SHOQ B 1
			SHOQ C 1
			SHOQ D 1
			SHOQ E 1
			SHOQ F 1
			SHOQ G 1
			Stop	
			
			Stop
	}
}

ACTOR FBD_CacoBall_Minus2: FBD_CacoBall {
	Speed 12 //14
	FastSpeed 16//18
}

ACTOR FBD_CacoBall_Minus1: FBD_CacoBall {
	Speed 13 //14
	FastSpeed 17//18
}

ACTOR FBD_CacoBall_Plus1: FBD_CacoBall {
	Speed 15 //14
	FastSpeed 19//18
}

ACTOR FBD_CacoBall_Plus2: FBD_CacoBall {
	Speed 16 //14
	FastSpeed 20//18
}

ACTOR FBD_CacoBall_Plus3: FBD_CacoBall {
	Speed 17 //14
	FastSpeed 21//18
}

ACTOR ElderCacolord : FBD_Cacolord 17881
{
	//$category "FBD Bosses"
	
	+BOSS
	Health 3000
	Scale 1.6
	Radius 64
	Height 128
	Tag "$CACOLORD_E"
	Obituary "$CACOLORD_E_O"
	
	SeeSound "elder_cacolord/sight"
	PainSound "elder_cacolord/pain"
	DeathSound "elder_cacolord/death"
	ActiveSound "elder_cacolord/active"	
	
	// leave the original black body un-swapped, 
	// so that we could mix these guys with regular cacolords without sowing confusion:
	Translation "168:174=[255,255,255]:[225,225,255]", "175:191=192:207"
	
	var int user_vomit;
	
	States {
		Spawn:
			OVER A 0 NODELAY ACS_NamedExecuteWithResult("FBD_RunMonster", 0, 200) // double the scale
			OVER A 0 A_SetUserVar("user_stun_limit", 16)
			OVER A 1 A_GiveInventory("CacoStamina", 150)
			Goto Stand
			
		Melee: // actually a limited-range lightning bolt
	
			TNT1 A 0
			
			TNT1 A 0 A_JumpIfInTargetInventory("GoFatality", 1, "WaitTargetsFatalityOut")
			
			// Kinslayer check:	
			TNT1 A 0 A_JumpIf(!CheckClass("FBD_Cacodemon", AAPTR_TARGET, true), 2)
			TNT1 A 0 ACS_NamedExecuteWithResult("FBD_InfightFriendlyFireOn")	
			
			TNT1 A 0 A_Facetarget
			OVER A 4 A_Recoil(-5)
			OVER GHI 4 BRIGHT A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			TNT1 A 0 A_PlaySound("cacolord/vomit", CHAN_VOICE)			
			OVER FF 4 A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
				
			OVER I 4 BRIGHT A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)	
			OVER F 4 A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			OVER II 4 BRIGHT A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)	
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
			OVER F 4 A_CustomMissile("VfxLightningBeingPrepared", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, 0, 0)
			
			TNT1 A 0 A_JumpIf(waterlevel > 0, "MeleeUnderwater")
			
			OVER IIIII 4 BRIGHT A_CustomMissile("ElderCacolordFuckYouBeam", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, 0.0)
			OVER HG 8 BRIGHT
			OVER LA 6

			

			Goto See
			
		MeleeUnderwater:
			
			OVER FFFFFFF 2 A_CustomMissile("FBD_CacoBall", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, angle + 0.1 * Random(-100, 100), CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, 0.1 * Random(-100, 100))
			OVER ED 8
			OVER LA 6
			
			Goto See
			
		MissileAfterAvoid:	
			
			//DE K-keep firing-K J
			
			OVER DEJ 8
			
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
			
			OVER K 8 BRIGHT
			//lower arms:
			TNT1 A 0 A_CustomMissile("TeleportationFog", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("TeleportationFog", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("TeleportationFog", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("TeleportationFog", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("TeleportationFog", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("TeleportationFog", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, angle, CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			
				//***Che: do NOT adjust aim if target goes out of sight or is invisible
				TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), 4)
				TNT1 A 0 A_JumpIfTargetInLOS(2)
				TNT1 A 0 A_Jump(256, 2)
				TNT1 A 0 A_FaceTarget
			
			OVER K 8 BRIGHT			
			
			TNT1 A 0 A_JumpIf(CallAcs("FBD_TargetIsInvisible"), "SixShotBlindfire")
			TNT1 A 0 A_JumpIfTargetInLOS("SixShotAutoaimed")
			// otherwise, blindfire
		
		SixShotBlindfire:
			// not autoaimed
			// CMF_AIMOFFSET to make them travel in formation, with the same pitch
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, angle, CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH)			
			OVER J 20
			Goto See

		SixShotAutoaimed:
			TNT1 A 0 A_FaceTarget
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* 32.0, 0, CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 5.0, FIXED_TO_FLOAT * user_head_scale* -32.0, 0, CMF_SAVEPITCH)
			//middle arms:
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* 42.0, 0, CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 34.0, FIXED_TO_FLOAT * user_head_scale* -42.0, 0, CMF_SAVEPITCH)
			// upper arms:
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* 40.0, 0, CMF_SAVEPITCH)
			TNT1 A 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 70.0, FIXED_TO_FLOAT * user_head_scale* -40.0, 0, CMF_SAVEPITCH)
			OVER J 20
			Goto See

		Meatsplode:
			TNT1 A 0 A_FaceTarget
			TNT1 A 0 A_SetUserVar("user_vomit", CallAcs("GetSpawnHealth", 0))
			TNT1 A 0 A_PlaySound("elder_cacolord/vomit", CHAN_VOICE)
			OVER LLLLLJJJJJEEEEEFFFFF 1 A_CustomMissile("BlueBloodMistExtraBig", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, angle + random(-16,16), CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH, random(-16,16))
			
		VomitCaclets:	
			OVER F 0 A_CustomMissile("BlueBloodMistExtraBig", FIXED_TO_FLOAT * user_head_scale* 15.0, 0, angle + random(-30,30), CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH, random(-30,30))
			OVER F 0 A_CustomMissile("CacletLauncher", FIXED_TO_FLOAT * user_head_scale* 15.0, 0, angle + random(-30,30), CMF_ABSOLUTEANGLE  | CMF_SAVEPITCH, random(-30,30))
			OVER F 1 A_SetUserVar("user_vomit", user_vomit - 100)
			OVER F 0 A_JumpIf(user_vomit <= 0, "MeatsplodeFinish")
			Loop
			
		MeatsplodeFinish:	
			
			
			OVER MMNNOO 1 A_CustomMissile ("BlueBloodMistBig", FIXED_TO_FLOAT * user_head_scale* 40.0, 0, random (0, 360), 2, random (-20, 70))
			TNT1 A 0 A_Scream
			TNT1 A 0 A_NoBlocking
			TNT1 A 0 A_ChangeFlag("NOGRAVITY", 1) 		
			TNT1 A 0 A_Stop
			TNT1 A 0 A_FaceTarget
			
			TNT1 A 0 A_CustomMissile ("CacoLordXDeath", 0, 0, random (0, 360), CMF_AIMDIRECTION, random (0, 160))
			TNT1 A 0 A_CustomMissile ("ElderCacolordExtraMeat", 50, 0, 90, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, 30)
			TNT1 A 0 A_CustomMissile ("ElderCacolordExtraMeat", 50, 0, 90, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, -30)
			TNT1 A 0 A_CustomMissile ("ElderCacolordExtraMeat", 50, 0, -90, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, 30)
			TNT1 A 0 A_CustomMissile ("ElderCacolordExtraMeat", 50, 0, -90, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, -30)
			TNT1 A 0 A_CustomMissile ("ElderCacolordExtraMeat", 50, 0, 0, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, 90)
			TNT1 A 0 A_CustomMissile ("ElderCacolordExtraMeat", 50, 0, 0, CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, -90)
			
			
			// must not hit the player (avoid the frontal arc
			OVER PQRSTUV 2 A_CustomMissile("ElderCacolordFuckYouBeam256", FIXED_TO_FLOAT * user_head_scale* 10.0, 0, angle + Random(30, 330), CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, Random(-70, 70))
			TNT1 A 0 A_ChangeFlag("NOGRAVITY", 0)
			TNT1 A 0 A_FaceTarget
			TNT1 AAAAAAA 3 A_CustomMissile("ElderCacolordFuckYouBeam256", FIXED_TO_FLOAT * user_head_scale* 33.0, 0, angle + Random(30, 330), CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, Random(-70, 70))
			//TNT1 AAAAAAA 0 A_CustomMissile ("BlueBloodMistBig", FIXED_TO_FLOAT * user_head_scale* 10.0, 0, random (0, 360), 2, random (-20, 70))
			Goto RestInPieces
	}
}

ACTOR CacolordLightning: FastProjectile
{
	Species "Cacodemons"
	Speed 500
	FastSpeed 500
	Radius 8
	Height 4
	//var int user_x;
	//var int user_y;
	//var int user_z;
	missiletype "none" 
	missileheight 8
	Species "Cacodemons"
	SeeSound "lightning/snap"
	+SKYEXPLODE
	DamageType "Plasma"
	Damage (random(10, 10)) //x5 = 50
	States {
		Spawn:
			TNT1 A 1 // limit range to 500
			TNT1 A 0 A_Stop
			
			TNT1 A 0 ACS_NamedExecuteWithResult("DrawLazorBeamMk5", 1) // a serverside script that calls a clientside script to actually draw
			
			TNT1 A 60
			Stop				
			
		Death:
		XDeath:
			TNT1 A 0 
			TNT1 A 0 A_Stop
			TNT1 A 0 A_PlaySound("lightning/hit", 6)
			
			TNT1 A 0 ACS_NamedExecuteWithResult("DrawLazorBeamMk5", 1) // a serverside script that calls a clientside script to actually draw
			
			// the visual effect is the same as cacoball's
			TNT1 A 0 A_CustomMissile ("ShoqueAzul", 3, 0, random (0, 360), 2, random (0, 360))
			EXPL A 0 A_CustomMissile ("FireBallExplosionFlames", 1, 0, random (0, 360), 2, random (0, 360))
			EXPL A 0 A_CustomMissile ("BluePlasmaFire", 1, 0, random (0, 360), 2, random (0, 360))
			TNT1 A 0 A_CustomMissile ("BDExplosionparticlesSmall", 10, 0, random (0, 180), 2, random (40, 90))
			
			TNT1 A 0 A_SetDamageType("Electric")
			TNT1 A 0 A_Explode(50, 10, 0)
			
			TNT1 AAA 1 A_SpawnItem("BlueFlare")

/*
			TNT1 A 0 A_SetUserVar("user_x", x)
			TNT1 A 0 A_SetUserVar("user_y", y)
			TNT1 A 0 A_SetUserVar("user_z", z)
			// WARPF_USECALLERANGLE is vital to preserve missile's angle because that is used
			//  by the clientside script (which is only passed one parameter: beam length)
			TNT1 A 1 A_Warp(AAPTR_TARGET,0,0,43,0,WARPF_STOP|WARPF_NOCHECKPOSITION|WARPF_USECALLERANGLE,"WarpedOk")
			
			Stop
		WarpedOk:
			TNT1 A 0 ACS_NamedExecuteWithResult("DrawLazorBeamMk4", 1) // a serverside script that calls a clientside script to actually draw
*/			
			// keep existing in case script starts delayed - it is CLIENTSIDE after all
			TNT1 A 60
			Stop	
	}
}

ACTOR CacolordLightning128: CacolordLightning
{
	Speed 128
	FastSpeed 128
}

ACTOR CacolordLightning128_5: CacolordLightning128
{
	Speed 128
	FastSpeed 128
	Damage (random(5, 5))
}

//***Che: and here we have a PROBLEM:
// the beam length is determined roughly, by calculating the distance to the originator.
// which, in case of secondary discharges, an absolutely wrong thing to do.
// so the beam goes back to the projectile that fired it... and then WAY far beyond that.
// Solution: spawn a minion monster who'd be the originator
// drawback: does NOT result in infighting since the attacker is fake and transient

ACTOR ElderCacolordSecondaryDischargesFirer
{
	MONSTER
	-COUNTKILL
	+NOINTERACTION
	+NOGRAVITY
	+NOCLIP
	-SHOOTABLE
	+NOTARGET
	+NEVERTARGET
	Radius 1
	Height 1
	States {
		Spawn:
			TNT1 AAAA 1 NODELAY A_CustomMissile("CacolordLightning128_5", 0, 0, angle + Random(-70, 70), CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, pitch + Random(-70, 70))
			TNT1 A 3
			Stop
	}
}

ACTOR ElderCacolordFuckYouBeam: FastProjectile
{
	Species "Cacodemons"
	Speed 500
	FastSpeed 500
	Radius 16
	Height 4
	//var int user_x;
	//var int user_y;
	//var int user_z;
	missiletype "none" 
	missileheight 8
	Species "Cacodemons"
	
	SeeSound "lightning/snap/low"
	
	Damage (random(40,40)) // x5 = 200
	DamageType "SuperPlasma"
	States {
		Spawn:
			TNT1 A 1 // limit range to 500
			TNT1 A 0 A_Stop
			TNT1 A 0 ACS_NamedExecuteWithResult("DrawLazorBeamMk5", 2) // a serverside script that calls a clientside script to actually draw
			TNT1 AAAA 0 A_SpawnItem("BlueFlare")
			
			// no sound: the child discharges produce it
			//TNT1 AAAA 1 A_CustomMissile("CacolordLightning128_5", 0, 0, angle + Random(-70, 70), CMF_AIMOFFSET | CMF_ABSOLUTEANGLE  | CMF_OFFSETPITCH | CMF_SAVEPITCH, pitch + Random(-70, 70))
			
			TNT1 A 0 A_SpawnItemEx("ElderCacolordSecondaryDischargesFirer",0,0,0, 0,0,0, angle,SXF_ABSOLUTEANGLE | SXF_SETMASTER | SXF_NOCHECKPOSITION | SXF_TRANSFERPITCH | SXF_SETMASTER)
			
			// keep existing in case script starts delayed - it is CLIENTSIDE after all
			TNT1 A 60
			Stop
			
		Death:
		XDeath:
			TNT1 A 0
			TNT1 A 0 A_Stop
			TNT1 A 0 A_PlaySound("lightning/hit", 6)
			
			TNT1 A 0 ACS_NamedExecuteWithResult("DrawLazorBeamMk5", 2) // a serverside script that calls a clientside script to actually draw
			
			TNT1 A 0 Bright A_JumpIf(waterlevel > 0, "Underwater")	
			TNT1 A 0 A_SpawnItem("BulletPuff")
			TNT1 A 0 A_NoBlocking
			TNT1 AAAA 0 A_SpawnItem("BlueFlare")
			TNT1 AAA 0 A_CustomMissile ("HeavyPlasmaProjectileHit", 0, 0, random (0, 360), 2, random (0, 360))
			TNT1 AAA 0 A_CustomMissile ("ExplosionParticleHeavy", 0, 0, random (0, 360), 2, random (0, 360))
			TNT1 AAA 0 A_CustomMissile ("ExplosionParticleVeryFast", 0, 0, random (0, 360), 2, random (0, 40))
			TNT1 AAA 0 A_CustomMissile ("PlasmaSmoke", 2, 0, random (0, 360), 2, random (0, 360))
	
			TNT1 A 0 A_SetDamageType("Electric")
			TNT1 A 0 A_Explode(50, 20, 0)
			
			// keep existing in case script starts delayed - it is CLIENTSIDE after all
			TNT1 A 60
			Stop	

			//Goto DoBeam
		
		Underwater:
			TNT1 A 0 A_Stop
			TNT1 A 0 A_PlaySound("KYBFGSPR", 7)
			TNT1 A 0 A_RadiusGive("ElectricShock", 160, RGF_MONSTERS | RGF_PLAYERS) 
			TNT1 A 0 A_RadiusGive("ElectricShock", 120, RGF_MONSTERS | RGF_PLAYERS) 
			TNT1 A 0 A_RadiusGive("ElectricShock", 90, RGF_MONSTERS | RGF_PLAYERS) 
			//Goto DoBeam
			
			// keep existing in case script starts delayed - it is CLIENTSIDE after all
			TNT1 A 60
			Stop	
/*
		DoBeam:
			TNT1 A 0 A_SetUserVar("user_x", x)
			TNT1 A 0 A_SetUserVar("user_y", y)
			TNT1 A 0 A_SetUserVar("user_z", z)
			// WARPF_USECALLERANGLE is vital to preserve missile's angle because that is used
			//  by the clientside script (which is only passed one parameter: beam length)
			TNT1 A 1 A_Warp(AAPTR_TARGET,0,0,86,0,WARPF_STOP|WARPF_NOCHECKPOSITION|WARPF_USECALLERANGLE,"WarpedOk")
			Stop
			
		WarpedOk:
			TNT1 A 0 ACS_NamedExecuteWithResult("DrawLazorBeamMk4", 2) // a serverside script that calls a clientside script to actually draw
			// keep existing in case script starts delayed - it is CLIENTSIDE after all
			TNT1 A 60
			Stop
*/			
	}
}

ACTOR ElderCacolordFuckYouBeam256: ElderCacolordFuckYouBeam
{
	Speed 256
	FastSpeed 256
}

ACTOR ElderCacolordExtraMeat: FastProjectile
{
	Radius 20
	Height 40
	Speed 60
	Damage 0
	States {
		Spawn:
			TNT1 A 1
		Death:
			TNT1 A 0 A_Stop
			TNT1 A 0 A_CustomMissile ("CacoLordXDeath", 0, 0, random (0, 360), CMF_AIMDIRECTION, random (0, 160))
			TNT1 A 30
			Stop
	}
}

	

ACTOR CacletLauncher: FastProjectile
{
	Radius 12
	Height 28
	Speed 20
	Damage (Random(20,20)) 
	DamageType "Kick"
	
	Translation "16:47=30:47", "232:235=181:187", "208:223=168:182", "168:183=208:223"
	var int user_success;
	
	States {
		Spawn:
			WATC HHHH 1 // travel 100 map units before trying to spawn
		KeepTrying:	
			WATC H 1 A_JumpIf(CallACS("EnoughSpaceToRezNormally", 604), "DoSpawn") // 604 = FBD_Caclet (cliff racer)
			Loop
			
		DoSpawn:
			TNT1 A 0 A_ChangeFlag("THRUACTORS", 1)  // without this, the projectile explodes immediately hitting the spawned cliff racer!
			TNT1 A 0 A_NoBlocking
			TNT1 A 0 A_SpawnItemEx("FBD_Caclet", 0,0,0, velx,vely,velz, 0,SXF_NOCHECKPOSITION | SXF_ABSOLUTEVELOCITY)
			TNT1 A 30 A_Stop
			Stop
			
		Death:
			// hit something! 
			TNT1 A 0
			TNT1 A 0 A_JumpIf(!CallAcs("FBD_SpawnInARadius", 604, 11, 0, 4), "Asplode") // radius 11, tries 4
			Stop
			
		Asplode:	
			// RipCaclet is a gore spawner supporting sfx auto-balancing. 
			// Angles given here do nothing, it spams its pieces all around 360
			TNT1 A 0 A_CustomMissile ("RipCaclet", 0, 0, 180, CMF_AIMDIRECTION, random (-30, 30))
			TNT1 A 30
			Stop
	}
}

ACTOR FBD_LightningTrail 
{
	+MISSILE
	+NOBLOCKMAP
	+NOINTERACTION
	+NOCLIP
	+NOGRAVITY
	+BRIGHT
	Radius 1
	Height 1
	Speed 0
	Damage 0
	+FORCEXYBILLBOARD
    +CLIENTSIDEONLY
	RenderStyle Add
	Alpha 0.95
	States
	{
		Spawn: 
			//***Che: variability in flipping
			TNT1 A 0 NODELAY A_SetScale(random(0,1) ? 0.7 : -0.7, random(0,1) ? 0.7 : -0.7)
			AFX1 D Random(1,2)
			AFX1 E Random(1,2)
			AFX1 F Random(1,2)
			AFX1 H Random(1,2)
			AFX1 H Random(1,2)
			AFX1 I Random(1,2)
			Stop	
	}
}

ACTOR FBD_HugeLightningTrail : FBD_LightningTrail 
{
	Translation "168:191=192:207", "48:79=80:111", "16:47=194:207"
	States
	{
		Spawn: 
			TNT1 A 0 NODELAY A_SetScale(random(0,1) ? 1.0 : -1.0, random(0,1) ? 1.0 : -1.0)
			TNT1 A 0 A_Jump(256, "Var1", "Var2", "Var3", "Var4", "Var5")
		Var1:
			LFX1 S 1
			Goto Fade
		Var2:
			LFX1 T 1
			Goto Fade
		Var3:
			LFX1 U 1
			Goto Fade
		Var4:
			LFX1 V 1
			Goto Fade
		Var5:
			LFX1 W 1
			Goto Fade
		Fade:
			"----" A 1 A_FadeOut(0.22)
			Loop
	}
}


