

const float FIXED_TO_FLOAT = 0.0000152587890625; // 1 / 65536.0
const float FLOAT_TO_FIXED = 65536.0;
const float FIXED_TO_ANGLE = 0.0054931640625; // 360.0 / 65536.0
const float ANGLE_TO_FIXED = 182.04444444444444; // 65536.0 / 360.0

const int CHE_HORRIBLESCREAM = 1;
const int CHE_NAG = 2; // nag for NPCs / frustration like "if I find you" for enemies
const int CHE_WATCHIT = 3; // NPC skedaddle from playaer's line of fire
const int CHE_STAYING = 4; // NPC confirms stay put order
const int CHE_FOLLOWING = 5; // NPC confirms follow order
const int CHE_FREED = 6; // a captured marine is freed
const int CHE_TRIUMPH = 7; // on killing his target
const int CHE_HAVEATTHEE = 8; // *not* the see sound, managed manually!

const int CHE_NPC = 0;
const int CHE_ATHENA = 1;
const int CHE_TRAITOR = 2;
const int CHE_MARADEUR_1 = 3;
const int CHE_MARADEUR_2 = 4;
const int CHE_MARADEUR_3 = 5;


ACTOR AbstractCorpse { //***Che: provides methods used for robust raising, nothing more
	
	damagefactor "TeleportRemover", 1000.0
	
	//damagefactor "RezSuccess", 999.0
	
	//damagefactor "AoeRaise", 1000.0
	
	-COUNTKILL
	-NEVERTARGET // NPCs should not aggro at this
	
	
	
	// must NOT set the CORPSE flag -- that's something each descendant decides on its own
	
    States 
	{
		XDeath.TeleportRemover:
		Death.TeleportRemover:
			"----" A 0
			"----" A 0 A_ChangeFlag("SOLID", 0)
			"----" A 0 A_ChangeFlag("SHOOTABLE", 0)
			"----" A -1 ACS_NamedExecuteAlways("RespawnCorpseAfter60sIfNightmare", 0, 0, 0, 0)

		FallbackRezSuccess:
			"----" A 0
			"----" A 0 A_ChangeFlag("CORPSE", 0)
			"----" A 0 A_ChangeFlag("SOLID", 0)
			"----" A 0 A_ChangeFlag("SHOOTABLE", 0)
			"----" A 0 A_JumpIfInventory("RezzingNow", 1, "OnRezSfx")
			
			// Oops, not *our* rez success -- we were hit by another actor rezzing, standing on top of us.
			// Must have been an epic pile of corpses.
			// Pretend to vanish but stay and keep being raiseable
			"----" A 0 A_ChangeFlag("CORPSE", 1)
			"----" AAAAAAAAAA 4 A_FadeOut(0.1, 0)
			TNT1 A -1 ACS_NamedExecuteAlways("RespawnCorpseAfter60sIfNightmare", 0, 0, 0, 0)
			
		OnRezSfx:
			// knight, baron, duke, belphegor and cacodemon corpses must replace this method with one that has appropriate blood color
			TNT1 AAA 3 A_CustomMissile ("BloodMistBig", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAA 3 A_CustomMissile ("FBD_Bloodmist", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAAA 3 A_CustomMissile ("BloodMistSmall", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 A 30
			Stop
		FadeOutAndVanish:
			"----" AAAAAAAAAA 4 A_FadeOut(0.1)
			Stop
		Death.Freeze: //***Che
		Death.Ice:
		Death.Frost:
		Death.IOS_Frost:
			TNT1 A 0 A_NoBlocking
			TNT1 A 0 A_PlaySound ("ice/crackle/short")
			TNT1 AAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk1", 12, 0, random (0, 360), 2, random (0, 160))
			TNT1 AAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk2", 12, 0, random (0, 360), 2, random (0, 160))
			
			// size 2x
			TNT1 AAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk2b", 12, 0, random (0, 360), 2, random (0, 160))
			
			TNT1 AAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk3", 12, 0, random (0, 360), 2, random (40, 120))
			TNT1 A 1
			//***Che: prevent the game engine from auto-respawning this gibbed corpse on nightmare as a corpse
			// while allowiing archviles raising it (they only check for the CORPSE flag)
			// and respawning via script on nightmare
			TNT1 A 0 A_ChangeFlag("CORPSE", 1)
			TNT1 A 0 A_ChangeFlag("ISMONSTER", 0)
			TNT1 A -1 ACS_NamedExecuteAlways("RespawnCorpseAfter60sIfNightmare", 0, 0, 0, 0) 
			Stop			
	}
}


Actor StandaloneRezSfx // to be used by monsters themselves in their Raise state
{
	Radius 4
	+NOGRAVITY
	+FLOAT
	+NOINTERACTION
	+NOCLIP
	States
	{
		Spawn:
			TNT1 A 0 NODELAY A_JumpIfInTargetInventory("IAmSfestMonster", 1, 1)
			Goto Sfx
			TNT1 A 0 A_GiveInventory("IAmSfestMonster", 1)
		Sfx:
			TNT1 AAA 3 A_CustomMissile ("BloodMistBig", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAA 3 A_CustomMissile ("FBD_Bloodmist", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAAA 3 A_CustomMissile ("BloodMistSmall", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 A 30
			Stop
	}
}


Actor StandaloneGreenRezSfx: StandaloneRezSfx
{
	States
	{
		Spawn:
			TNT1 A 0 NODELAY A_JumpIfInTargetInventory("IAmSfestMonster", 1, 1)
			Goto Sfx
			TNT1 A 0 A_GiveInventory("IAmSfestMonster", 1)
		Sfx:
			TNT1 AAA 3 A_CustomMissile ("GreenBloodMistBig", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAA 3 A_CustomMissile ("GreenBloodMist", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAAA 3 A_CustomMissile ("GreenBloodMistSmall", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 A 30
			Stop
	}
}


Actor StandaloneBlueRezSfx: StandaloneRezSfx
{
	States
	{
		Spawn:
			TNT1 A 0 NODELAY A_JumpIfInTargetInventory("IAmSfestMonster", 1, 1)
			Goto Sfx
			TNT1 A 0 A_GiveInventory("IAmSfestMonster", 1)
		Sfx:
			TNT1 AAA 3 A_CustomMissile ("BlueBloodMistBig", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAA 3 A_CustomMissile ("BlueBloodMist", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 AAAAA 3 A_CustomMissile ("BlueBloodMistSmall", 20, 0, random (0, 360), 2, random (30, 90))
			TNT1 A 30
			Stop
	}
}	


ACTOR AbstractDyingGuy { //***Che: provides freeze deaths, nothing more
	
	damagefactor "TeleportRemover", 1000.0
	States
	{
		Death.Freeze:
		Death.Ice:
		Death.Frost:
		Death.IOS_Frost:
			TNT1 A 0 A_NoBlocking
			//TNT1 A 0 ACS_NamedExecuteWithResult("DeleteHeadboxMkII") // *some* are inherited from this!
			TNT1 A 0 A_StopSound(CHAN_VOICE)
			TNT1 A 0 A_PlaySound ("ice/crackle/short")
			TNT1 AAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk1", Random(12,40), 0, random (0, 360), 2, random (0, 160))
			TNT1 AAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk2", Random(12,40), 0, random (0, 360), 2, random (0, 160))
			
			// size 2x
			TNT1 AAAAAAAAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk2b", Random(12,40), 0, random (0, 360), 2, random (0, 160))
			
			TNT1 AAAAAAAAAAAAAA 0 A_CustomMissile ("XIceChunk3", Random(12,40), 0, random (0, 360), 2, random (40, 120))
			TNT1 A 1 A_Jump(256, "XDeath")
			Wait
	
	}
}




ACTOR CheDebugMarker 
{
	+NOINTERACTION
	Radius 1
	Height 1
	States
	{
		Spawn:
			KYDB B 35 BRIGHT
			KYDB BBBBBBBBBB 4 BRIGHT A_FadeOut(0.1)
			Stop
	}
}


ACTOR CheDebugMarkerQuestion: CheDebugMarker 
{
	States
	{
		Spawn:
			KYDB C 35 BRIGHT
			KYDB CCCCCCCCCC 4 BRIGHT A_FadeOut(0.1)
			Stop
	}
}

ACTOR CheDebugMarkerPass: CheDebugMarker 
{
	States
	{
		Spawn:
			KYDB D 35 BRIGHT
			KYDB DDDDDDDDDD 4 BRIGHT A_FadeOut(0.1)
			Stop
	}
}

ACTOR CheDebugMarkerFail: CheDebugMarker 
{
	States
	{
		Spawn:
			KYDB E 35 BRIGHT
			KYDB EEEEEEEEEE 4 BRIGHT A_FadeOut(0.1)
			Stop
	}
}	

Actor AbstractItemAdder: FastProjectile // used by items to spawn other items nearby
{
	+SERVERSIDEONLY
	
	Speed 50
	Radius 20
	Height 2
	Decal None
	DamageType None
	Damage (Random(0, 0))
	+THRUACTORS
	+THRUGHOST
	+GHOST
	+THRUSPECIES
	+SKYEXPLODE	
	States
	{
		Spawn:
			TNT1 A 1
//tnt1 A 0 A_Log("aia fired")			
		Death:
			TNT1 A 0 A_Stop
			TNT1 A 0 A_JumpIf(CallAcs("GetDistanceToTarget") < 16 || (z - floorz) > 48, "Vanish")
			TNT1 A 0 A_Warp(AAPTR_DEFAULT, 0,0,floorz - z) // drop to the floor
			TNT1 A 1 A_JumpIf(true, "AddItem")
			Wait
		Vanish:
//tnt1 A 0 A_Log("aia failed")
//tnt1 A 0 A_Log(z)
//tnt1 A 0 A_Log(floorz)
//KYDB E -1 BRIGHT
			TNT1 A 1
			Stop
			
		AddItem: // override this abstract method to actually add an item
			KYDB C 30 BRIGHT
			Stop
	}
}

Actor AbstractPotpourriChecker // various size checkers inherit from this,
	// used by the ACS scripts checking if there is room to spawn a *bigger* monster on potpourri
{
	MONSTER
	-COUNTKILL
	+NOTARGET
	+NEVERTARGET
	-FRIENDLY
	+THRUGHOST
	States
	{
		Spawn:
			TNT1 A 1
			TNT1 A -1
	}
}

Actor AbstractSpaceChecker: AbstractPotpourriChecker
{
	Species "FBD_Checker"
	+THRUSPECIES
	States
	{
		Spawn:
			TNT1 A 2 // for robustness they are ato-terminating although the script that spams them is guaranteed to delete them
			Stop
	}	
}

Actor AbstractBossCubeSpawner 
	/* 
		Spawner's job is making sure monster doesn't spawn
		on someone's head or overhanging a drop
		or in any other condition that prevents him moveing.
		
		These are used in Chebskies-EDAY maps 313 and 32
		and rely heavily on map scripts of those maps to spawn them
		(it is the cube-managing ACS script that sets spawner's tracer pointer to the boss cube
		and the user_stid variable to the TID that the spawned monster should have)
		
		Flying monsters, *obviously*, do not need such spawners.
	*/	
{
	MONSTER // is spawned via ACS, which sets the pointers required (the tracer pointer). SpawnItemEx is of no concern.
	+SERVERSIDEONLY
	+NOBLOCKMAP // Is excluded from passive collision detection. 
		// Nothing else can run into a NOBLOCKMAP actor but the actor himself can run into others.
	-COUNTKILL
	-SHOOTABLE
	+NOTARGET
	+NEVERTARGET
	-FRIENDLY
	+THRUGHOST
	+NODROPOFF

	Speed 3
	FastSpeed 3
	
	Radius 16 // the basic checker is used for minor monsters
	Height 60
	Mass 100
	Health 100
	
	MaxStepHeight 24
	MaxDropOffHeight 24
	
	var int user_x; 
	var int user_y;
	var int user_stid; // set the summons' TID to:
	
	PainSound "KYBOCUB1"
	
	States
	{
		Spawn:
			// doesn't fucking work
			//TNT1 A 0 NODELAY A_SetUserVar("user_x", x)
			TNT1 A 1
			TNT1 A 0 A_SetAngle(angle + random(-30, 30))
			//TNT1 A 0 A_SpawnItemEx("CheDebugMarker",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION)
			TNT1 A 0 A_SetUserVar("user_x", x)
			TNT1 A 0 A_SetUserVar("user_y", y) 
			
			// By some *unfathomable* reason just three steps are NOT enough, no movement is performed.
			// Why then does it work with more steps? A mystery.
			TNT1 AAAAAAAAAAAAAAAAAA 0 A_Wander // try moving. Will not happen if stuck.
			
			// calculate integer deltas
			TNT1 A 0 A_SetUserVar("user_x", user_x - x)
			TNT1 A 0 A_SetUserVar("user_y", user_y - y)
			TNT1 A 0 A_JumpIf(user_x != 0 || user_y != 0, "Success")
			Stop			
		Success:	
			TNT1 A 0 ACS_NamedExecuteWithResult("OnBossCubeSuccess") // map script (eday313, eday32)
			TNT1 A 0 A_Scream
			TNT1 A 1 A_Jump(256, "DoSummon")
			Wait
		DoSummon:
			// to be overridden by the ancestor's method
			TNT1 A 0 A_GiveInventory("SummonsCount", 1, AAPTR_TRACER) // obsolete now but too lazy to change all the spawner classes
			TNT1 A 0 A_SpawnItemEx("TeleportationFog")
			TNT1 A 1 A_SpawnItemEx("DyingZombieman",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0,user_stid)
			Stop
	}
}
/*
Actor VileBossCubeSpawner: AbstractBossCubeSpawner
{
	Radius 20
	Height 56
	States
	{
		DoSummon:	
			TNT1 A 0 A_GiveInventory("SummonsCount", 1, AAPTR_TRACER)
			TNT1 A 0 A_SpawnItemEx("TeleportationFog")
			TNT1 A 1 A_SpawnItemEx("FBD_Archvile",0,0,0,0,0,0,0,SXF_NOCHECKPOSITION,0,user_stid)
			Stop
	}
}
*/

ACTOR ZandronumBaronBall // from zandronum.pk3
{
	Game Doom
	SpawnID 154
	Radius 6
	Height 16
	Speed 15
	FastSpeed 20
	Damage 8
	Projectile 
	+RANDOMIZE
	RenderStyle Add
	Alpha 1
	SeeSound "baron/attack"
	DeathSound "baron/shotx"
	Decal "BaronScorch"
	States
	{
		Spawn:
			BAL7 AB 4 BRIGHT
			Loop
		Death:
			BAL7 CDE 6 BRIGHT
			Stop
	}
}

ACTOR AbstractParticle
{
	Game Doom
	Radius 1
	Height 1
	Speed 3
    PROJECTILE //***Che includes +NOBLOCKMAP
	+NOGRAVITY
	+FORCEXYBILLBOARD
    +CLIENTSIDEONLY
	+THRUACTORS
	+DOOMBOUNCE
	RenderStyle Add
    Damage 0
	Gravity 0
	States
	{
		Spawn:
			TNT1 A 1
			TNT1 A 1 A_JumpIf(waterlevel > 1, "Bubble")
			TNT1 A 1
			Stop
		Bubble:
			TNT1 A 2 A_CustomMissile("BUBULZ",0,0, 0,CMF_AIMDIRECTION | CMF_ABSOLUTEPITCH, pitch)
			Stop
	}
}


