-- Storage for last summon --


-- Base Summon Spell --

Base_SummonSpell = Base_Object:New({

	SpecialChance = Growth_Linear:New({ A = 0, B = 50 }),
	Count = Growth_Linear:New({ A = 2 / 49.0, B = 1 }),
	TargetCount = Growth_Linear:New({ A = 0, B = 1 }),
	SummonTargetCount = Growth_Linear:New({ A = 1 / 49.0, B = 1 }),
	ResistAll = Growth_Linear:New({ A = 0.5, B = 0.5 }),
	ResistAllSummonPowerScale = 0.2,
	DamageRange = 0.1,

	ApplyCost = function(self, Source, Level, Result)
		Result.Source.Mana = -self.ManaCost:Result(Level)

		return Result
	end,

	CanUse = function(self, Level, Source)
		return Source.Mana >= self.ManaCost:Result(Level)
	end,

	GetRoll = function(self, Summon, Source, Result, SpecialPointer, Count)

		-- Assign summon from buff
		if Result.SummonBuff ~= nil then
			Summon.Summon = Result.SummonBuff
			return Result.SummonBuff == SpecialPointer and 1 or 1000
		end

		-- Randomly choose
		return Random.GetInt(1, 100)
	end,

	GetResistAll = function(self, Source, Level, ShowFractions)
		local Scalar = 1 + (Source.SummonPower * 0.01 - 1) * self.ResistAllSummonPowerScale
		return self.ResistAll:ModifiedResult(Level, Scalar, 0, ShowFractions and RoundDown1)
	end,

	GetMaxResistAll = function(self, Source, Level, ShowFractions)
		return math.min(75 + Source.EternalWard, MAX_RESISTANCE)
	end,

	GetHealth = function(self, Source, Level)
		return self.Health:ModifiedResult(Level, Source.SummonPower * 0.01)
	end,

	GetMana = function(self, Source, Level)
		return self.Mana:ModifiedResult(Level, Source.SummonPower * 0.01)
	end,

	GetArmor = function(self, Source, Level, ShowFractions)
		return self.Armor:ModifiedResult(Level, Source.SummonPower * 0.01, 0, ShowFractions and RoundDown1)
	end,

	GetLimit = function(self, Source, Level, ShowFractions)
		return self.Limit:ModifiedResult(Level, 1, Source.SummonLimit, ShowFractions and RoundDown2)
	end,

	GetTargetCount = function(self, Source, Level, ShowFractions)
		return self.TargetCount:Result(Level, ShowFractions and RoundDown2)
	end,

	GetSummonTargetCount = function(self, Source, Level, ShowFractions)
		return self.SummonTargetCount:ModifiedResult(Level, 1, Source.TargetCount, ShowFractions and RoundDown2)
	end,

	GetDamage = function(self, Source, Level)
		local Damage = self.Damage:ModifiedResult(Level, Source.SummonPower * 0.01)
		return math.ceil(Damage * (1 - self.DamageRange)), math.ceil(Damage * (1 + self.DamageRange))
	end,

	GetBuffLevel = function(self, Source, Level)
		return self.BuffLevel:ModifiedResult(Level, Source.SummonPower * 0.01)
	end,

	GetDamageText = function(self, Source, Item)
		local MinDamage, MaxDamage = self:GetDamage(Source, Item.Level)
		local DamageText
		if Item.MoreInfo == true then
			DamageText = FormatSI((MinDamage + MaxDamage) / 2) .. " avg"
		else
			DamageText = FormatSI(MinDamage) .. "-" .. FormatSI(MaxDamage)
		end

		return "[c green]" .. DamageText .. "[c white] " .. self.DamageTypeName .. " damage\n"
	end,

	GetHealthText = function(self, Source, Item)
		return "[c green]" .. FormatSI(self:GetHealth(Source, Item.Level)) .. "[c white] HP\n"
	end,

	GetArmorText = function(self, Source, Item)
		return "[c green]" .. FormatSI(self:GetArmor(Source, Item.Level, Item.MoreInfo)) .. "[c white] armor\n"
	end,

	GetResistanceText = function(self, Source, Item)
		return
			"[c green]+" .. FormatSI(self:GetResistAll(Source, Item.Level, Item.MoreInfo)) .. "%[c white] resist all (" ..
			"[c green]" .. self:GetMaxResistAll(Source, Item.Level) .. "%[c white] max)\n"
	end,

	GetTargetText = function(self, Source, Item)
		return "[c green]" .. self:GetSummonTargetCount(Source, Item.Level, Item.MoreInfo) .. "[c white] target count\n"
	end,

	GetMaximumText = function(self, Source, Item)
		return "Can summon a maximum of [c green]" .. self:GetLimit(Source, Item.Level, Item.MoreInfo) .. "[c white]\n"
	end,

	GetCostText = function(self, Source, Item)
		return "Costs [c light_blue]" .. FormatSI(self.ManaCost:Result(Item.Level)) .. "[c white] MP\n\n"
	end,

	GetHelpText = function(self, Source, Item)
		return "[c yellow]Restores " .. self.ObjectName .. "s to full at summon limit"
	end,

	GetInfo = function(self, Source, Item)
		return
			self:GetCountText(Source, Item) ..
			self:GetDamageText(Source, Item) ..
			self:GetHealthText(Source, Item) ..
			self:GetArmorText(Source, Item) ..
			self:GetResistanceText(Source, Item) ..
			self:GetTargetText(Source, Item) ..
			self:GetChanceText(Source, Item) ..
			self:GetMaximumText(Source, Item) ..
			self:GetCostText(Source, Item) ..
			self:GetHelpText(Source, Item)
	end,

	PlaySound = function(self)
		Audio.Play("summon0.ogg")
	end,
})

-- Demonic Conjuring --

Skill_DemonicConjuring = Base_SummonSpell:New({

	ObjectName = "demon",
	DamageTypeName = "fire",
	ManaCost = Growth_Polynomial:New({ E = 2, A = 0.1, B = 10, C = 25 }),
	SkillLevel = Growth_Linear:New({ A = 1, B = 1 }),
	Limit = Growth_Linear:New({ A = 3 / 49.0, B = 1 }),
	Health = Growth_Linear:New({ A = 20, B = 100 }),
	Armor = Growth_Linear:New({ A = 0.1, B = 1.1 }),
	BuffLevel = Growth_Polynomial:New({ E = 1, A = 1, B = 1, C = 2 }),
	SlowBuffLevel = Growth_Linear:New({ A = 30 / 49.0 , B = 20 }),
	Damage = Growth_Polynomial:New({ A = 0.3, B = 10.6, C = 20, E = 2 }),
	Monster = Monsters[23],
	SpecialMonster = Monsters[39],

	GetCountText = function(self, Source, Item)
		local Count = self.Count:ModifiedResult(Item.Level, 1, Source.TargetCount, Item.MoreInfo and RoundDown2)
		local Plural = Count ~= 1 and "s" or ""

		return "Summon [c green]" .. Count .. "[c white] " .. self.ObjectName .. Plural .. " with\n"
	end,

	GetChanceText = function(self, Source, Item)
		return "[c green]" .. self.SpecialChance:Result(Item.Level) .. "%[c white] chance to summon an ice imp that deals cold damage and slows\n"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)

		-- Get summon count
		local Count
		if Result.SummonBuff ~= nil then
			Count = 1
		else
			Count = math.min(self.Count:ModifiedResult(Level, 1, Source.TargetCount), BATTLE_LIMIT)
		end

		Result.Summons = {}
		for i = 1, Count do
			Result.Summons[i] = {}
			Result.Summons[i].SpellID = self.Item.ID
			Result.Summons[i].ID = self.Monster.ID
			Result.Summons[i].SkillLevel = math.min(self.SkillLevel:Result(Level), MAX_SKILL_LEVEL)
			Result.Summons[i].Health = self:GetHealth(Source, Level)
			Result.Summons[i].MinDamage, Result.Summons[i].MaxDamage = self:GetDamage(Source, Level)
			Result.Summons[i].Armor = self:GetArmor(Source, Level)
			Result.Summons[i].ResistAll = self:GetResistAll(Source, Level)
			Result.Summons[i].MaxResistAll = self:GetMaxResistAll(Source, Level)
			Result.Summons[i].SummonBuff = Buff_SummonDemon.Pointer
			Result.Summons[i].Duration = -1
			Result.Summons[i].TargetCount = self:GetSummonTargetCount(Source, Level) - 1
			Result.Summons[i].BattleSpeed = Source.SummonBattleSpeed

			-- Limit monster summons to 1
			if Source.MonsterID == 0 then
				Result.Summons[i].Limit = self:GetLimit(Source, Level)
			else
				Result.Summons[i].Limit = 1
			end

			-- Pick type
			local Roll = self:GetRoll(Result.Summons[i], Source, Result, Buff_SummonIceImp.Pointer, Count)
			if Roll <= self.SpecialChance:Result(Level) then
				Result.Summons[i].ID = self.SpecialMonster.ID
				Result.Summons[i].SummonBuff = Buff_SummonIceImp.Pointer
			end

			-- Set skill level based on type
			if Result.Summons[i].SummonBuff == Buff_SummonIceImp.Pointer then
				Result.Summons[i].SkillLevel = math.min(self.SkillLevel:Result(Level), MAX_SKILL_LEVEL)
				Result.Summons[i].BuffLevel = self.SlowBuffLevel:Result(Level)
			else
				Result.Summons[i].SkillLevel = math.min(self.SkillLevel:Result(Level), MAX_SKILL_LEVEL)
				Result.Summons[i].BuffLevel = self:GetBuffLevel(Source, Level)
			end
		end

		WeaponProc(Source, Target, Result, true)

		return Result
	end,
})

-- Raise Dead --

Skill_RaiseDead = Base_SummonSpell:New({

	ObjectName = "skeleton",
	DamageTypeName = "physical",
	ManaCost = Growth_Polynomial:New({ E = 2, A = 0.1, B = 10, C = 15 }),
	SkillLevel = Growth_Linear:New({ A = 1, B = 1 }),
	HealPower = Growth_Linear:New({ A = 0, B = 100 }),
	Limit = Growth_Linear:New({ A = 4 / 49.0, B = 2 }),
	Health = Growth_Linear:New({ A = 19, B = 50 }),
	Mana = Growth_Linear:New({ A = 30, B = 30 }),
	Armor = Growth_Linear:New({ A = 0.07, B = 1 }),
	MinDamage = Growth_Polynomial:New({ A = 0.25, B = 10, C = 10, E = 2 }),
	MaxDamage = Growth_Polynomial:New({ A = 0.25, B = 10, C = 15, E = 2 }),
	Damage = Growth_Polynomial:New({ A = 0.25, B = 10, C = 12.5, E = 2 }),
	HealSummonPowerScale = 0.5,
	SpecialDamage = 0.85,
	Monster = Monsters[20],
	SpecialMonster = Monsters[21],

	CanTarget = function(self, Source, Target, First)
		return Target.Corpse > 0 and Target.Health == 0
	end,

	GetCountText = function(self, Source, Item)
		local Count = self.Count:ModifiedResult(Item.Level, 1, Source.TargetCount, Item.MoreInfo and RoundDown2)
		local Plural = Count ~= 1 and "s" or ""

		return "Raise [c green]" .. Count .. "[c white] " .. self.ObjectName .. Plural .. " from a corpse with\n"
	end,

	GetChanceText = function(self, Source, Item)
		return
			"[c green]" .. self.SpecialChance:Result(Item.Level) .. "%[c white] " ..
			"chance to summon a skeleton priest that can heal and has [c green]" .. FormatSI(self:GetMana(Source, Item.Level)) .. "[c white] MP " ..
			"but only deals [c green]" .. math.floor(self.SpecialDamage * 100) .. "%[c white] damage\n"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)

		-- Get summon count
		local Count
		if Result.SummonBuff ~= nil then
			Count = 1
		else
			Count = math.min(self.Count:ModifiedResult(Level, 1, Source.TargetCount), BATTLE_LIMIT)
		end

		Result.Summons = {}
		for i = 1, Count do
			Result.Summons[i] = {}
			Result.Summons[i].SpellID = self.Item.ID
			Result.Summons[i].ID = self.Monster.ID
			Result.Summons[i].Health = self:GetHealth(Source, Level)
			Result.Summons[i].MinDamage, Result.Summons[i].MaxDamage = self:GetDamage(Source, Level)
			Result.Summons[i].Armor = self:GetArmor(Source, Level)
			Result.Summons[i].ResistAll = self:GetResistAll(Source, Level)
			Result.Summons[i].MaxResistAll = self:GetMaxResistAll(Source, Level)
			Result.Summons[i].Limit = self:GetLimit(Source, Level)
			Result.Summons[i].SkillLevel = math.min(self.SkillLevel:Result(Level), MAX_SKILL_LEVEL)
			Result.Summons[i].HealPower = self.HealPower:ModifiedResult(Level, 1, (Source.SummonPower - 100) * self.HealSummonPowerScale)
			Result.Summons[i].Duration = -1
			Result.Summons[i].TargetCount = self:GetSummonTargetCount(Source, Level) - 1
			Result.Summons[i].SummonBuff = Buff_SummonSkeleton.Pointer
			Result.Summons[i].BattleSpeed = Source.SummonBattleSpeed

			-- Pick type
			local Roll = self:GetRoll(Result.Summons[i], Source, Result, Buff_SummonSkeletonPriest.Pointer, Count)
			if Roll <= self.SpecialChance:Result(Level) then
				Result.Summons[i].ID = self.SpecialMonster.ID
				Result.Summons[i].Mana = self:GetMana(Source, Level)
				Result.Summons[i].SummonBuff = Buff_SummonSkeletonPriest.Pointer
				Result.Summons[i].MinDamage = math.ceil(Result.Summons[i].MinDamage * self.SpecialDamage)
				Result.Summons[i].MaxDamage = math.ceil(Result.Summons[i].MaxDamage * self.SpecialDamage)
			end
		end

		Result.Target.Corpse = -1
		WeaponProc(Source, Target, Result, true)

		return Result
	end,
})
