// ACCURACY OF 69 MEANS ITS A CRIT!
const int DND_CRITTOKEN = 69;

const int DND_ATK_PRIMARY = 1;
const int DND_ATK_SECONDARY = 2;
const int DND_ATK_OTHER_DIR = 4;

/*
// Copy to all monsters (until cleaner solution is found)
		Death.Melee_Magic:
		Death.Melee_MagicFull:
		Death.Magic:
		Death.MagicFull:
		Death.Explosives_Magic:
		Death.Explosives_MagicFull:
		Death.MagicFire:
		Death.MagicFireFull:
		Death.SoulType:
		Death.SoulTypeFull:
			TNT1 A 0 A_GiveInventory("MagicCausedDeath", 1)
		Goto Death
		Death.BookOfTheDead:
			TNT1 A 0 A_GiveInventory("BookofDeadCausedDeath", 1)
		Goto Death
*/

enum {
	PUP_HOMINGNOREFLECT,
	PUP_EXPLOSIVEIGNORERESIST,
	PUP_SLAINENEMIESRIP,
	PUP_FORBIDARMOR,
	PUP_LUCKYCRITS,
	PUP_PELLETSFIRECIRCLE,
	PUP_KNOCKBACKIMMUNE,
	PUP_CURSEIMMUNITY,
	PUP_PAINSHAREDWITHPETS,
	PUP_SOULWEPSDOFULL,
	PUP_SPELLSDOFULL,
	PUP_POISONTICSTWICE
};

// every 10 points contribute 0.0001%
const float accuracy_factor = 0.00001;
// variable "score" is representing explosion radius
const float exprad_factor = 0.01;
const int DND_SHARED_ITEM_SCRIPT = 999;

enum {
	DND_SPECIAL_RESEARCH = 1,
	DND_SPECIAL_ORB = 2,
	DND_SPECIAL_TALENTCAPSULE = 4,
	DND_SPECIAL_ELIXIR = 8,
	DND_SPECIAL_CHARM = 16
};

actor DND_DroppedItem {
	+LOOKALLAROUND
	+NOTIMEFREEZE
	MONSTER
	-COUNTKILL
	-SOLID
	-SHOOTABLE
	-TELESTOMP
	+NOTELEPORT
	+DONTBLAST
	+SEEINVISIBLE
	+DONTGIB
	Health 0
	Radius 1
	Height 1
}

Actor GrabbyHandIcon {
	Scale 0.5
	Height 2
	Radius 1
	+CLIENTSIDEONLY
	+NOINTERACTION
	var int user_z;
	States {
		Spawn:
			TNT1 A 0 NoDelay A_SetUserVar("user_z", 0)
		SpawnLoop:
			TNT1 A 0 A_JumpIf(user_z >= 35, "GoAway")
			GRBY A 1 A_ChangeVelocity(0, 0, sin(user_z * 360 / 35), CVF_REPLACE)
			TNT1 A 0 A_SetUserVar("user_z", user_z + 1)
		Loop
		GoAway:
			GRBY A 1
		Stop
	}
}

Actor GrabbyHandCooldown : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 35
}

const int item_look_dist = 80;
const int item_pickup_dist = 32;
Actor InventoryBase : DnD_DroppedItem {
	Radius 20
	Height 24
	States {
		SpawnInit:
			"####" "#" 0 ACS_NamedExecuteAlways("DnD Remove Check Special", 0, mass, DND_SPECIAL_CHARM)
			"####" "#" 1 Bright
			"####" "#" 24 Bright ACS_NamedExecuteAlways("DnD Item Linger Check")
			"####" "#" 1 Bright A_Jump(256, "SpawnLoop")
		Wait
		
		SpawnLoop:
		Idle:
			"####" "#" 1 Bright A_LookEx(LOF_NOSOUNDCHECK, 0, item_look_dist, 0, 360, "CheckPickup")
		Loop
		
		See:
		CheckPickup:
			"####" "#" 1 Bright A_JumpIfCloser(item_look_dist, "Grabby")
		CheckPickupNext:
			"####" "#" 1 Bright A_JumpIfCloser(item_pickup_dist, "Pickup")
			"####" "#" 1 Bright A_Jump(256, "SpawnLoop")
		Wait
		Grabby:
			"####" "#" 1 Bright A_JumpIfInventory("GrabbyHandCooldown", 1, "CheckPickupNext")
			"####" "#" 0 Bright A_GiveInventory("GrabbyHandCooldown", 1)
			"####" "#" 0 Bright ACS_NamedExecuteAlways("DnD Spawn Grabby", 0, DND_SPECIAL_CHARM)
		Goto CheckPickupNext
		
		Pickup:
			"####" "#" 0 Bright A_JumpIfInventory("DnD_IntermissionState", 1, "PickupFail")
			"####" "#" 1 Bright A_JumpIf(ACS_NamedExecuteWithResult("DnD Check Special Match", DND_SPECIAL_CHARM), "PickupCheck2")
		goto PickupFail

		PickupFail:
			"####" "#" 1 Bright
			"####" "#" 1 Bright A_Jump(256, "SpawnLoop")
		Wait
		
		PickupCheck2:
			// Check if player has remaining inventory space
			"####" "#" 0 A_JumpIf(ACS_NamedExecuteWithResult("DnD Player Has Spot For Item", mass - 1), "PickupSuccess")
		Goto PickupShowItem
		
		PickupShowItem:
			"####" "#" 0 A_JumpIfInTargetInventory("DnD_PlayerViewsItem", 1, "PickupFail")
			"####" "#" 0 A_JumpIfInTargetInventory("ShowingMenu", 1, "PickupFail")
			"####" "#" 0 A_GiveToTarget("DnD_PlayerViewsItem", 1)
			"####" "#" 0 ACS_NamedExecuteAlways("DnD Preview Item", 0, mass - 1, ACS_NamedExecuteWithResult("DnD Get Target"))
		Goto PickupFail
		
		PickupSuccess:
			TNT1 A 8 ACS_NamedExecuteAlways("DnD Charm Pickup", 0, mass - 1)
		stop
	}
}

Actor DnD_SharedItem {
	Height 48
	Radius 20
	Translation Ice
	Renderstyle Translucent
	+USESPECIAL
	+DONTBLAST
	+DONTSPLASH
}

Actor DND_Activator : CustomInventory {
	inventory.maxamount 1
	+INVENTORY.ALWAYSPICKUP
	+INVENTORY.AUTOACTIVATE
}

Actor DnD_Info : Inventory {
	inventory.maxamount 0x7FFFFFFF
}

Actor DnD_Kills : Inventory {
	inventory.maxamount 0x7FFFFFFF
}

Actor DnD_ScrollState : Inventory {
	inventory.maxamount 1000
}

Actor DropItemCooldown : PowerDamage {
	powerup.duration -1
	damagefactor "normal", 1.0
}

Actor DnD_Boolean : Inventory {
	inventory.maxamount 1
}

Actor DnD_ErrorNumber : Inventory {
	inventory.maxamount 3
}

Actor Mo_Died : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 9
}

Actor InfiniteProtectionBase : PowerProtection {
	damagefactor "normal", 1.0
	powerup.duration 0x7FFFFFFF
}

Actor DnD_FakeDamager {
	PROJECTILE
	+DONTBLAST
	+MTHRUSPECIES
	States {
		Spawn:
			TNT1 A 1
		Stop
		Death:
			TNT1 A 1
		Stop
	}
}

Actor BaseExplosionDamage // this is necessary, calling A_Explode in actor can cause unwanted effects.
{
	Speed 0
	Height 4
	Radius 4
	Damage (0)
	+MISSILE
	+DONTBLAST
	+NOBLOCKMAP
	+NOGRAVITY
	+THRUACTORS
	+DONTSPLASH
	-TELESTOMP
	States
	{
		Spawn:
			TNT1 A 0
			TNT1 A 1
		Stop
	}
}

/*Actor DnD_DamageReceived : Inventory {
	inventory.maxamount 0x7FFFFFFF
}*/

Actor DnD_DamageFade : Inventory {
	+INVENTORY.UNDROPPABLE
	inventory.maxamount 0x7FFFFFFF
}

Actor ReloadSignal : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 4
}

Actor ForceWeaponRemove : DnD_Boolean { }

Actor NoRewardsGiven : DnD_Boolean { }
Actor StartOnly : DnD_Boolean { }

Actor P_Slot1Replaced : DnD_Boolean { }
Actor P_Slot2Replaced : DnD_Boolean { }
Actor P_Slot3Replaced : DnD_Boolean { }
Actor P_Slot3XReplaced : DnD_Boolean { }
Actor P_Slot4Replaced : DnD_Boolean { }
Actor P_Slot5Replaced : DnD_Boolean { }
Actor P_Slot6Replaced : DnD_Boolean { }
Actor P_Slot7Replaced : DnD_Boolean { }

Actor P_Slot1Luxury : DnD_Boolean { }
Actor P_Slot2Luxury : DnD_Boolean { }
Actor P_Slot3Luxury : DnD_Boolean { }
Actor P_Slot4Luxury : DnD_Boolean { }
Actor P_Slot5Luxury : DnD_Boolean { }
Actor P_Slot6Luxury : DnD_Boolean { }
Actor P_Slot7Luxury : DnD_Boolean { }
Actor P_Slot8Luxury : DnD_Boolean { }

Actor Reloading : DnD_Boolean { }

Actor P_PlasmaFire : DnD_Boolean { }
Actor P_GreenFire : DnD_Boolean { }
Actor P_PurpleFire : DnD_Boolean { }
Actor P_RedFire : DnD_Boolean { }
Actor P_GrayFire : DnD_Boolean { }

Actor P_Frozen : DnD_Boolean { }
Actor P_StepTaken : DnD_Boolean { }
Actor P_Invulnerable : DnD_Boolean { }
Actor TempWeaponReady : DnD_Boolean { }

Actor RoundsSurvived : Ammo
{
	inventory.amount 1
	inventory.maxamount 0xFFFFFF
	ammo.backpackamount 0
	ammo.backpackmaxamount 0
	+IGNORESKILL
}

Actor DnD_PTotalLevel : inventory {
	inventory.maxamount 6400
}

Actor P_Damage : Ammo {
	inventory.amount 1
	inventory.maxamount 0x7FFFFFFF
	ammo.backpackamount 0
	ammo.backpackmaxamount 0x7FFFFFFF
	+IGNORESKILL
}

Actor LevelToken : Inventory
{
	inventory.maxamount 1
}

Actor SetMyLives : Inventory
{
	inventory.maxamount 1
}

Actor NoDrop : Inventory
{
	inventory.maxamount 1
}

Actor ShockWaveCounter : Ammo
{
	inventory.amount 1
	inventory.maxamount 100
	ammo.backpackamount 0
	ammo.backpackmaxamount 100
	inventory.icon "STTPRCNT"
	+IGNORESKILL
}

Actor CurrentLives : Ammo
{
	inventory.amount 1
	inventory.maxamount 9
	ammo.backpackamount 0
	ammo.backpackmaxamount 0
	+IGNORESKILL
}

Actor TipBoxOpen : PowerDamage {
	powerup.duration -6
	damagefactor "normal", 1.0
}

Actor UseWeaponTips : Ammo {
  Inventory.MaxAmount 1
  +UNDROPPABLE
  Ammo.BackpackAmount 0
  Ammo.BackpackMaxAmount 1
}

Actor ParsingData : DnD_Boolean { }

Actor WeaponZoom : DnD_Boolean { }
Actor WeaponZoomCooldown : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 15
}

Actor DnD_PressedUse : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 5
}

Actor DnD_WaitNextItemPick : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 15
}

Actor AutoPickCooldown : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 21
}

Actor DnD_PlayerViewsItem : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 9
}

Actor InTradeView : DnD_Boolean { }

Actor DnD_TradeAcceptWindow : DnD_Boolean { }

ACTOR ProjBullet : FastProjectile {
	Radius 1
	Height 1
	Damage (random(1, 3) * 5)
	Stamina 3 // phys + hitscan
	DamageType "PhysicalHitscan"
	Speed 128
	Scale 0.1
	RenderStyle Add
	Alpha 0.85
	PROJECTILE
	+FORCEXYBILLBOARD
	States {
		Spawn:
			TNT1 A 0
			TRAC A -1 Bright
		Stop
		Death:
			TNT1 A 1
			TNT1 A 1 A_SpawnItemEx("NewBulletPuff")
		Stop
		XDeath:
			TNT1 A 1 A_SpawnItemEx("RealBlood", 0, 0, 0, 0, 0, 0, 0, SXF_NOCHECKPOSITION | SXF_TRANSFERTRANSLATION)
		Stop
	}
}

Actor DnD_Intermission : DnD_Boolean { }

Actor DND_ACK : PowerDamage { 
	damagefactor "normal", 1.0
	powerup.duration 4
}

Actor DND_ACKLoop : DnD_Boolean { }

Actor DnD_ActorWorking : DnD_Boolean { }

enum {
	SHI_STIMPACK,
	SHI_MEDKIT,
	SHI_BACKPACK
};

enum {
	BONUS_KILL,
	BONUS_ITEM,
	BONUS_SECRET,
	BONUS_BONUS
};

Actor DnD_KillBonusShower : DnD_Activator {
	States {
		Pickup:
			//TNT1 A 0 A_GiveInventory("DnD_ShowKillBonus", 1)
			TNT1 A 0 ACS_NamedExecuteAlways("DnD Bonus Message Show", 0, BONUS_KILL)
		Stop
	}
}

Actor DnD_ItemBonusShower : DnD_Activator {
	States {
		Pickup:
			//TNT1 A 0 A_GiveInventory("DnD_ShowItemBonus", 1)
			TNT1 A 0 ACS_NamedExecuteAlways("DnD Bonus Message Show", 0, BONUS_ITEM)
		Stop
	}
}

Actor DnD_SecretBonusShower : DnD_Activator {
	States {
		Pickup:
			//TNT1 A 0 A_GiveInventory("DnD_ShowSecretBonus", 1)
			TNT1 A 0 ACS_NamedExecuteAlways("DnD Bonus Message Show", 0, BONUS_SECRET)
		Stop
	}
}

Actor DnD_BonusBonusShower : DnD_Activator {
	States {
		Pickup:
			//TNT1 A 0 A_GiveInventory("DnD_ShowBonusBonus", 1)
			TNT1 A 0 ACS_NamedExecuteAlways("DnD Bonus Message Show", 0, BONUS_BONUS)
		Stop
	}
}

Actor DnD_ExpCredit_Timer : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 55
}

Actor DnD_Exp_Counter : Inventory {
	inventory.maxamount 0x7FFFFFFF
}

Actor DnD_Credit_Counter : Inventory {
	inventory.maxamount 0x7FFFFFFF
}

Actor DnD_Hit_Cooldown : PowerProtection {
	damagefactor "normal", 1.0
	powerup.duration 9
}

Actor DnD_Hit_CombatTimer : PowerProtection {
	damagefactor "normal", 1
	powerup.duration -3
}

Actor MarkAsReflected : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_SetDamageType("Reflection")
		Stop
	}
}

enum {
	DND_PELLETACTOR_HSSG
};

enum {
	DND_STACKEDITEM_ORB,
	DND_STACKEDITEM_CHESTKEY,
	DND_STACKEDITEM_TOKEN
};

Actor IMGONE : PowerInvisibility {
	Powerup.Duration -60
	Powerup.Strength 80
	Powerup.Mode "Opaque"
}

Actor DontAttack : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_GiveInventory("IMGONE", 1)
		Stop
	}
}

Actor DontAttackRemove : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 A_TakeInventory("IMGONE", 1)
		Stop
	}
}

Actor MonsterKilledByPlayer : DnD_Boolean { }

Actor DnD_TauntCooldown : PowerProtection {
	damagefactor "normal", 1.0
	powerup.duration 85
}

Actor ProjectileHelper {
	Species "Player"
	// Try MISSILE here to see if puffs can get pointers transferred to them properly on spawn
	+NOINTERACTION
	States {
		Spawn:
			TNT1 A 5
		Stop
	}
}

Actor DnD_Weapon_FrameChecker : Inventory {
	inventory.maxamount 0x7FFFFFFF
}

Actor DnD_EnemySlatedForRemoval : DnD_Boolean { }

Actor DnD_ResurrectChecker : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 ACS_NamedExecuteAlways("DnD Resurrect Checker", 0, 35 * 5, -1) // delay and who, -1 is activator
		Stop
	}
}

Actor DnD_ResurrectMonster : DnD_Activator {
	States {
		Pickup:
			TNT1 A 0 Thing_Raise(0)
		Stop
	}
}

Actor DnD_WeaponSwapCheck : PowerDamage {
	damagefactor "normal", 1.0
	powerup.duration 3
}