enum {
	DND_MWEIGHT_COMMON = 1000,
	DND_MWEIGHT_UNCOMMON = 750,
	DND_MWEIGHT_RARE1 = 600,
	DND_MWEIGHT_RARE2 = 500,
	DND_MWEIGHT_VERYRARE = 325,
	DND_MWEIGHT_EPIC = 275,
};

enum {
	DND_BLIND_LIGHT,
	DND_BLIND_HEAVY,
	DND_BLIND_PETRIFY
};

Actor IsBlinded : DnD_Boolean { }

Actor BlindCancelledSignal : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 7
}

Actor DnD_SightChecker : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_JumpIf(!ACS_NamedExecuteWithResult("DnD Can Look Around"), "Nothing")
			TNT1 A 0 A_Look
		Stop
		Nothing:
			TNT1 A 0
		Stop
	}
}

Actor DnD_BaseMonster {
	GibHealth -150
	+USEKILLSCRIPTS
	-FLOORCLIP // no view sink on liquid floors
	+DONTBLAST
	+COUNTKILL
	+CANPUSHWALLS
	+CANUSEWALLS
	+ACTIVATEMCROSS
	+CANPASS
	-SHOOTABLE
	-SOLID
	+THRUACTORS
	+USEDAMAGEEVENTSCRIPT
	
	// NoPain versions
	Painchance "Melee_NoPain", 0
	Painchance "Melee_Magic_NoPain", 0
	Painchance "Bullet_NoPain", 0
	Painchance "BulletMagicX_NoPain", 0
	Painchance "Energy_NoPain", 0
	Painchance "EnergyExp_NoPain", 0
	Painchance "Explosives_NoPain", 0
	Painchance "Magic_NoPain", 0
	Painchance "MagicFire_NoPain", 0
	Painchance "Explosives_Magic_NoPain", 0
	
	// called by crits or scripts etc. to avoid triggering the event script again
	PainChance "Special_NoPain", 0
	
	// elemental
	Painchance "Fire_NoPain", 0
	Painchance "P_Ice_NoPain", 0
	Painchance "Poison_NoPain", 0
	Painchance "Desolator_NoPain", 0
	Painchance "Emerald_NoPain", 0
	Painchance "Lightning_NoPain", 0
	
	Painchance "SoulType_NoPain", 0
	
	// Pain Forced versions
	Painchance "Melee_ForcePain", 256
	Painchance "Melee_Magic_ForcePain", 256
	Painchance "Bullet_ForcePain", 256
	Painchance "BulletMagicX_ForcePain", 256
	Painchance "Energy_ForcePain", 256
	Painchance "EnergyExp_ForcePain", 256
	Painchance "Explosives_ForcePain", 256
	Painchance "Magic_ForcePain", 256
	Painchance "MagicFire_ForcePain", 256
	Painchance "Explosives_Magic_ForcePain", 256
	
	// elemental
	Painchance "Fire_ForcePain", 256
	Painchance "P_Ice_ForcePain", 256
	Painchance "Poison_ForcePain", 256
	Painchance "Desolator_ForcePain", 256
	Painchance "Emerald_ForcePain", 256
	Painchance "Lightning_ForcePain", 256
	
	Painchance "SoulType_ForcePain", 256
	
	var int user_spawnheight;
	
	States {
		Spawn:
			// this tnt1 is needed, otherwise the game will complain it has no frames
			TNT1 A 0 NoDelay A_Jump(256, "SetInfo")
			"####" "#" 35
		Wait
		
		SpawnSetup:
			"####" "#" 0 ACS_NamedExecuteWithResult("DnD Monster Scale", args[4], args[1])
		Idle:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD Monster Idle", 0)
			"####" "#" 0 A_Jump(256, "IdleState")
			"####" "#" 35
		Wait
		
		See:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD Monster Active", 0)
			"####" "#" 0 A_Jump(256, "SeeState")
			"####" "#" 35
		Wait
		
		Pain:
			"####" "#" 0 A_GiveInventory("BlindCancelledSignal", 1)
			"####" "#" 0 A_Jump(256, "PainState")
			"####" "#" 35
		Wait
		
		Frozen:
			// in case monster got frozen during a move that made it have one of the below
			"####" "#" 0 A_UnsetReflectiveInvulnerable
			"####" "#" 0 A_SetSolid
			"####" "#" 0 A_SetShootable
		FrozenLoop:
			"####" "###" 4 A_SpawnItemEx("FreezeGlitter", frandom(-radius, radius) / 2, frandom(-radius, radius) / 2, frandom(10, height / 2))
			"####" "###" 0 A_SpawnItemEx("ColdSmoke", frandom(-radius, radius) / 2, frandom(-radius, radius) / 2, frandom(24, height + 16) / 2, frandom(-1.25, 1.25), frandom(-1.25, 1.25), frandom(-0.75, 0.75))
			"####" "#" 1 A_JumpIfInventory("DnD_FreezeTimer", 1, "FrozenLoop")
		Goto See
		
		GravdisFling:
			// looping sounds should be stopped
			"####" "#" 0 A_Pain
			"####" "#" 0 A_StopSound(CHAN_WEAPON)
			"####" "#" 0 A_StopSound(5)
			"####" "#" 0 A_StopSound(6)
			"####" "#" 0 A_StopSound(7)
			"####" "#" 0 A_ChangeFlag("NOPAIN", 1)
		GravdisLoopStart:
			"####" "#" 1 A_JumpIfInventory("GravdisDebuff", 1, "GravdisLoop")
		Goto GravdisEnd
		GravdisLoop:
			"####" "##" 3 A_SpawnItemEx("GravdisParticle", frandom(-radius, radius), frandom(-radius, radius), frandom(0, -8), 0, 0, frandom(-16, -2))
		Goto GravdisLoopStart
		GravdisEnd:
			"####" "#" 1 ACS_NamedExecuteWithResult("DnD Toggle NoPain")
		Goto See
	
		Death:
			"####" "#" 0 A_StopSound(CHAN_ITEM)
			"####" "#" 0 A_Jump(256, "DeathState")
			"####" "#" 35
		Wait
		XDeath:
		Death.Explosives:
			"####" "#" 0 A_StopSound(CHAN_ITEM)
			"####" "#" 0 A_Jump(256, "XDeathState")
			"####" "#" 35
		Wait
		
		
		/*
		Damage types from spells and stuff affecting monsters go here
		*/
		Death.BookOfTheDead:
			"####" "#" 0 A_GiveInventory("BookofDeadCausedDeath", 1)
		Goto Death
		
		Death.MagicSealing:
			"####" "#" 0 A_StopSound(CHAN_ITEM)
			"####" "#" 0 A_Stop
			"####" "#" 0 A_ChangeFlag("NOGRAVITY", 1)
			"####" "#" 0 A_GiveInventory("DnD_DeathEffectBlock", 1)
			"####" "#" 0 A_ChangeFlag("NOCLIP", 1) // this is needed so monsters with crash state do not cancel out of this one
			"####" "#" 0 A_SpawnItemEx("DemonSealKanji", 0, 0, height / 3, 0, 0, 0, 0, SXF_NOCHECKPOSITION)
			"####" "#" 0 A_SpawnItemEx("DemonSealWhoosh2", 0,0,6, 0,0,0, 0, SXF_NOCHECKPOSITION)
			"####" "#" 0 A_SpawnItemEx("DemonSealWhoosh", 0,0,6, 0,0,0, 0, SXF_NOCHECKPOSITION)
			"####" "#" 0 A_SpawnItemEx("SealedDemonFX", 0, 0, 6, 0, 0, 2, 0, SXF_NOCHECKPOSITION)
			"####" "#" 0 A_PlaySound ("jpcpplasmarifle/seal", CHAN_AUTO, 1, 0, 0.8)
			"####" "#" 0 A_SetTranslucent (0.85, 0)
			"####" "#" 0 A_Fall
			"####" "#" 0 A_KillMaster
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "######" 1 Light("FDOfudaSealingGlow1") A_SetScale (scalex * 0.92, scaley * 0.97)
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "#####" 1 Light("FDOfudaSealingGlow2") A_SetScale (scalex * 0.80, scaley * 0.95)
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "######" 1 Light("FDOfudaSealingGlow3") A_SetScale (scalex * 0.88, scaley * 0.93)
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "#######" 1 Light("FDOfudaSealingGlow4") A_SetScale (scalex * 0.84, scaley * 0.85)
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "#####" 1 Light("FDOfudaSealingGlow5") A_SetScale (scalex * 0.80, scaley * 0.74)
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "#####" 1 Light("FDOfudaSealingGlow6") A_SetScale (scalex * 0.78, scaley * 0.62)
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "####" 1 Light("FDOfudaSealingGlow7") A_SetScale (scalex * 0.72, scaley * 0.55)
			"####" "#" 0 A_FadeTo (0, 0.1, 0)
			"####" "####" 1 Light("FDOfudaSealingGlow8") A_SetScale (scalex * 0.50, scaley * 0.50) // 42 tics
		Stop
		Death.Emerald:
			"####" "#" 0 A_StopSound(CHAN_ITEM)
			"####" "#" 0 A_Stop
			"####" "#" 0 A_Scream
			"####" "#" 0 A_NoBlocking
			"####" "#" 0 ACS_NamedExecuteAlways("DnD Emerald Death")
			"####" "#" 0 A_KillMaster
			"####" "#" 0 A_GiveInventory("DnD_DeathEffectBlock", 1)
			"####" "######" 1  A_SetScale (scalex * 1.03, scaley * 0.97)
			"####" "#####" 1 A_SetScale (scalex * 1.03, scaley * 0.95)
			"####" "######" 1 A_SetScale (scalex * 1.03, scaley * 0.93)
			"####" "#######" 1 A_SetScale (scalex, scaley * 0.85)
			"####" "#####" 1 A_SetScale (scalex, scaley * 0.74)
			"####" "#####" 1 A_SetScale (scalex * 1.05, 0.028)
			"####" "####" 1 A_SetScale (scalex * 1.06, 0.024)
			"####" "####" 1 A_SetScale (scalex * 1.07, 0.02) // 42 tics
			TNT1 A 6
		Stop
		Death.Ice:
		Death.P_Ice:
			"####" "#" 0 A_StopSound(CHAN_ITEM)
			"----" "#" 1 A_KillMaster
			"----" "###" 0 A_SpawnItemEx("WhiteParticleSpawner", 0, 0, 32, 0, 0, 0, 0, 128)
			"----" "#" 0 ACS_NamedExecuteWithResult("DnD Monster Kill Ice Chunks", radius, user_spawnheight)
			"----" "#" 1 A_GiveInventory("DnD_IceDeathToken", 1)
			TNT1 A 5
		Stop
	}
}

Actor DnD_IceDeathToken : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_GiveInventory("DnD_DeathEffectBlock", 1)
			TNT1 A 0 A_CheckFlag("BOSSDEATH", "DoBossDeath")
		FreezeChunks:
			TNT1 A 0 A_PlaySound("misc/icebreak", CHAN_BODY)
			TNT1 A 0 A_NoBlocking
		Stop
		DoBossDeath:
			TNT1 A 0 A_BossDeath
		Goto FreezeChunks
	}
}

Actor DnD_DeathEffectBlock : DnD_Boolean { }

// inherit melee if monster can ONLY do melee
Actor DnD_BaseMeleeMonster_NoRes : DnD_BaseMonster {
	Stamina 1
	States {
		Melee:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD On Monster Attack", 0)
			"####" "#" 0 A_Jump(256, "MeleeState")
			"####" "#" 35
		Wait
	}
}

Actor DnD_BaseMeleeMonster : DnD_BaseMeleeMonster_NoRes {
	Stamina 1
	States {
		Raise:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD On Revive", 0)
			"####" "#" 0 A_Jump(256, "RaiseState")
			"####" "#" 35
		Wait
	}
}

// inherit ranged if monster can ONLY do ranged
Actor DnD_BaseRangedMonster_NoRes : DnD_BaseMonster {
	States {
		Missile:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD On Monster Attack", 0)
			"####" "#" 0 A_Jump(256, "MissileState")
			"####" "#" 35
		Wait
	}
}

Actor DnD_BaseRangedMonster : DnD_BaseRangedMonster_NoRes {
	States {
		Raise:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD On Revive", 0)
			"####" "#" 0 A_Jump(256, "RaiseState")
			"####" "#" 35
		Wait
	}
}

// inherit this if the monster is supposed to have both attack types, melee and ranged!
Actor DnD_BaseHybridMonster_NoRes : DnD_BaseMonster {
	Stamina 1
	States {
		Melee:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD On Monster Attack", 0)
			"####" "#" 0 A_Jump(256, "MeleeState")
			"####" "#" 35
		Wait
		Missile:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD On Monster Attack", 0)
			"####" "#" 0 A_Jump(256, "MissileState")
			"####" "#" 35
		Wait
	}
}

Actor DnD_BaseHybridMonster : DnD_BaseHybridMonster_NoRes {
	Stamina 1
	States {
		Raise:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD On Revive", 0)
			"####" "#" 0 A_Jump(256, "RaiseState")
			"####" "#" 35
		Wait
	}
}

Actor DnD_ArchVileBase : DnD_BaseRangedMonster_NoRes {
	Stamina 1
	States {
		Heal:
			"####" "#" 0 A_Jump(256, "HealState")
			"####" "#" 35
		Wait
	}
}

Actor DnD_ArchVilePassiveBase : DnD_BaseMonster {
	Stamina 1
	States {
		Heal:
			"####" "#" 0 A_Jump(256, "HealState")
			"####" "#" 35
		Wait
	}
}

Actor DnD_ArchVileHybridBase : DnD_BaseHybridMonster_NoRes {
	Stamina 1
	States {
		Heal:
			"####" "#" 0 A_Jump(256, "HealState")
			"####" "#" 35
		Wait
	}
}

// inherit melee if monster can ONLY do melee and is a boss creature -- SM or Cyber (not ressurectable)
Actor DnD_BaseMeleeBoss : DnD_BaseMeleeMonster_NoRes {
	Stamina 1
	GibHealth -500
	+NEVERRESPAWN
	+NOFEAR
}

// inherit ranged if monster can ONLY do ranged and is a boss
Actor DnD_BaseRangedBoss : DnD_BaseRangedMonster_NoRes {
	GibHealth -200
	+NEVERRESPAWN
	+NOFEAR
}

// inherit this if the monster is supposed to have both attack types, melee and ranged!
Actor DnD_BaseHybridBoss : DnD_BaseHybridMonster_NoRes {
	Stamina 1
	GibHealth -200
	+NEVERRESPAWN
	+NOFEAR
}

Actor DnD_MonsterSetupDone : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_ChangeFlag("SHOOTABLE", 1)
			TNT1 A 0 A_ChangeFlag("SOLID", 1)
			TNT1 A 0 A_ChangeFlag("THRUACTORS", 0)
		Stop
	}
}

Actor DnD_UnsetShootable : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_ChangeFlag("SHOOTABLE", 0)
		Stop
	}
}

Actor Monster_Chaos_Check : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_Jump(128, "SkipChaos")
		ChaosAttack:
			TNT1 A 0 A_Jump(128, "HomingSmall")
			TNT1 A 0 A_CustomMissile("ChaosBolt", frandom(height / 2, 3 * height / 4), frandom(-radius / 2, radius / 2), frandom(-9, 9), 0, frandom(-4.5, 4.5))
		Stop
		HomingSmall:
			TNT1 A 0 A_CustomMissile("ChaosBolt_Seeking", frandom(height / 2, 3 * height / 4), frandom(-radius / 2, radius / 2), frandom(-9, 9), 0, frandom(-4.5, 4.5))
		Stop
		
		SkipChaos:
			TNT1 A 0
		Stop
	}
}

Actor Monster_Chaos_Check_Medium : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_Jump(64, "SkipChaos")
			TNT1 AA 0 A_CustomMissile("ChaosBolt", frandom(height / 2, 3 * height / 4), frandom(-radius / 2, radius / 2), frandom(-9, 9), 0, frandom(-4.5, 4.5))
			TNT1 A 0 A_CustomMissile("ChaosBolt_Seeking", frandom(height / 2, 3 * height / 4), frandom(-radius / 2, radius / 2), frandom(-9, 9), 0, frandom(-4.5, 4.5))
		Stop
		
		SkipChaos:
			TNT1 A 0
		Stop
	}
}

Actor Monster_Chaos_Check_Big : DnD_Activator {
	States {
		Pickup:
			TNT1 AAA 0 A_CustomMissile("ChaosBolt", frandom(height / 2, 3 * height / 4), frandom(-radius / 2, radius / 2), frandom(-9, 9), 0, frandom(-4.5, 4.5))
			TNT1 AA 0 A_CustomMissile("ChaosBolt_Seeking", frandom(height / 2, 3 * height / 4), frandom(-radius / 2, radius / 2), frandom(-9, 9), 0, frandom(-4.5, 4.5))
		Stop
	}
}

Actor ChaosBolt {
	Speed 32
	Projectile
	Height 16
	Radius 8
	Scale 0.75
	Damage (random(15, 24))
	DamageType "Chaos"
	SeeSound "ChaosBolt/Fire"
	DeathSound "ChaosBolt/Hit"
	Renderstyle Add
	+PIERCEARMOR
	
	States {
		Spawn:
			CHAO ABCD 3 Bright A_SpawnItemEx("ChaosBolt_Trail")
		Loop
		Death:
			CHAO EFGHI 3 Bright
		Stop
	}
}

Actor ChaosBolt_Seeking : ChaosBolt {
	Speed 16
	+SEEKERMISSILE
	States {
		Spawn:
			CHAO ABCD 3 Bright A_SpawnItemEx("ChaosBolt_Trail")
			TNT1 A 0 A_ScaleVelocity(1.5)
		SpawnLoop:
			CHAO A 3 Bright A_SeekerMissile(75, 75, SMF_PRECISE)
			TNT1 A 0 A_SpawnItemEx("ChaosBolt_Trail")
			CHAO B 3 Bright A_SeekerMissile(75, 75, SMF_PRECISE)
			TNT1 A 0 A_SpawnItemEx("ChaosBolt_Trail")
			CHAO C 3 Bright A_SeekerMissile(75, 75, SMF_PRECISE)
			TNT1 A 0 A_SpawnItemEx("ChaosBolt_Trail")
			CHAO D 3 Bright A_SeekerMissile(75, 75, SMF_PRECISE)
			TNT1 A 0 A_SpawnItemEx("ChaosBolt_Trail")
		Loop
	}
}

Actor ChaosBolt_Trail {
	Renderstyle Add
	Alpha 1.0
	Scale 0.25
	+NOINTERACTION
	+CLIENTSIDEONLY
	States {
		Spawn:
			TNT1 A 2
		SpawnLoop:
			OGLP C 1 Bright A_FadeOut(0.0875)
		Loop
	}
}

Actor DnD_HurtToken : PowerProtection {
	damagefactor "normal", 1.0
	powerup.duration 3
}

enum {
	DND_MHR_PERIODIC,
	DND_MHR_DURATION
};

// Stealth monster replacer

ACTOR StealthArachnotron_DnD : RandomSpawner replaces StealthArachnotron
{
	Dropitem "Arachnotron"
}

ACTOR StealthArchvile_DnD : RandomSpawner replaces StealthArchvile
{
	Dropitem "Archvile"
}

ACTOR StealthBaron_DnD : RandomSpawner replaces StealthBaron
{
	Dropitem "BaronOfHell"
}

ACTOR StealthCacodemon_DnD : RandomSpawner replaces StealthCacodemon
{
	Dropitem "Cacodemon"
}

ACTOR StealthChaingunGuy_DnD : RandomSpawner replaces StealthChaingunGuy
{
	Dropitem "ChaingunGuy"
}

ACTOR StealthDemon_DnD : RandomSpawner replaces StealthDemon
{
	Dropitem "Demon"
}

ACTOR StealthHellKnight_DnD : RandomSpawner replaces StealthHellKnight
{
	Dropitem "HellKnight"
}

ACTOR StealthDoomImp_DnD : RandomSpawner replaces StealthDoomImp
{
	Dropitem "Doomimp"
}

ACTOR StealthFatso_DnD : RandomSpawner replaces StealthFatso
{
	Dropitem "Fatso"
}

ACTOR StealthRevenant_DnD : RandomSpawner replaces StealthRevenant
{
	Dropitem "Revenant"
}

ACTOR StealthShotgunGuy_DnD : RandomSpawner replaces StealthShotgunGuy
{
	Dropitem "ShotgunGuy"
}

ACTOR StealthZombieMan_DnD : RandomSpawner replaces StealthZombieMan
{
	Dropitem "ZombieMan"
}
