-- Base Spell --

Base_Spell = Base_Skill:New({

	ManaCost = Growth_Polynomial:New({ E = 2 }),

	GenerateDamage = function(self, Source, Level)
		return Random.GetInt(self:GetMinDamage(Source, Level), self:GetMaxDamage(Source, Level))
	end,

	GetDamage = function(self, Source, Level)
		return self.Damage:ModifiedResult(Level, self:GetPower(Source, Level))
	end,

	GetBuffLevel = function(self, Source, Level)
		return self.BuffLevel:ModifiedResult(Level, self:GetPower(Source, Level))
	end,

	GetBuffDamage = function(self, Source, Level)
		return math.floor(self:GetBuffLevel(Source, Level)) * math.floor(self:GetDuration(Source, Level))
	end,

	GetMinDamage = function(self, Source, Level)
		local Damage = self:GetDamage(Source, Level)

		return math.max(Damage - math.floor(Damage * self.Damage.Range), 0)
	end,

	GetMaxDamage = function(self, Source, Level)
		local Damage = self:GetDamage(Source, Level)

		return Damage + math.floor(Damage * self.Damage.Range)
	end,

	GetDamageText = function(self, Source, Item)
		if Item.MoreInfo == true then
			return "[c green]" .. FormatSI(self:GetDamage(Source, Item.Level)) .. " [c green]avg[c white]"
		else
			return "[c green]" .. FormatSI(self:GetMinDamage(Source, Item.Level)) .. "-" .. FormatSI(self:GetMaxDamage(Source, Item.Level)) .. "[c white]"
		end
	end,

	GetChance = function(self, Source, Level)
		return self.Chance:Result(Level)
	end,

	GetPower = function(self, Source, Level)
		return Source[self.AttributeName .. "Power"] * 0.01 * Source.SpellDamage * 0.01
	end,

	GetManaCost = function(self, Source, Level)
		return self.ManaCost:Result(Level)
	end,

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

		return Result
	end,

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

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		return false
	end,

	Use = function(self, Level, Duration, Source, Target, Result)
		local Damage = self:GenerateDamage(Source, Level)
		Damage = math.floor(Damage * Target.GetDamageReduction(self.Item.DamageType))
		Damage = math.max(Damage, 0)

		Result.Target.DamageType = self.Item.DamageType
		Result.Target.Health = -Damage

		self:Proc(Random.GetInt(1, 100), Level, Duration, Source, Target, Result)
		WeaponProc(Source, Target, Result, true)

		return Result
	end
})

-- Rejuvenation --

Spell_Rejuvenation = Base_Spell:New({

	AttributeName = "Heal",
	TargetCount = Growth_Linear:New({ A = 6 / 49.0, B = 1 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.25, B = 5, C = 5 }),
	BuffLevel = Growth_Polynomial:New({ E = 3.50, A = 0.0015, B = 5, C = 5 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.HealDuration }),

	GetPower = function(self, Source, Level)
		return Source[self.AttributeName .. "Power"] * 0.01
	end,

	GetInfo = function(self, Source, Item)
		local HealValue
		if Item.MoreInfo == true then
			HealValue = FormatSI(self:GetBuffLevel(Source, Item.Level)) .. "[c white] stacking HPS"
		else
			HealValue = FormatSI(self:GetBuffDamage(Source, Item.Level)) .. "[c white] stacking HP over [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds"
		end

		return
			"Heal " .. self:GetTargetText(Source, Item) .. " for [c green]" .. HealValue .. "\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Healing.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Heal --

Spell_Heal = Base_Spell:New({

	AttributeName = "Heal",
	TargetCount = Growth_Linear:New({ A = 3 / 49.0, B = 1 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.25, B = 15, C = 15 }),
	Heal = Growth_Polynomial:New({ E = 3, A = 0.025, B = 50, C = 50 }),

	GetPower = function(self, Source, Level)
		return Source[self.AttributeName .. "Power"] * 0.01
	end,

	GetHeal = function(self, Source, Level)
		return self.Heal:ModifiedResult(Level, self:GetPower(Source, Level))
	end,

	GetInfo = function(self, Source, Item)
		return
			"Heal " .. self:GetTargetText(Source, Item) .. " for [c green]" .. FormatSI(self:GetHeal(Source, Item.Level)) .. "[c white] HP\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Health = self:GetHeal(Source, Level)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Sanctuary --

Spell_Sanctuary = Base_Spell:New({

	AttributeName = "Heal",
	TargetCount = Growth_Linear:New({ A = 4 / 49.0, B = 3 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.5, B = 10, C = 25 }),
	BuffLevel = Growth_Linear:New({ A = 49 / 49.0, B = 1 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.SanctuaryDuration }),
	HealPowerScale = 0.5,

	GetPower = function(self, Source, Level)
		return (100 + self.HealPowerScale * (Source.HealPower - 100)) * 0.01
	end,

	GetHeal = function(self, Source, Level)
		return math.floor(Buff_Sanctuary.Heal * self:GetBuffLevel(Source, Level))
	end,

	GetTotalHeal = function(self, Source, Level)
		return math.floor(self:GetHeal(Source, Level)) * math.floor(self:GetDuration(Source, Level, true))
	end,

	GetArmor = function(self, Source, Level)
		return math.floor(Buff_Sanctuary.Armor * self:GetBuffLevel(Source, Level))
	end,

	GetDamageBlock = function(self, Source, Level)
		return math.floor(Buff_Sanctuary.DamageBlock * self:GetBuffLevel(Source, Level))
	end,

	GetInfo = function(self, Source, Item)
		local HealValue
		if Item.MoreInfo == true then
			HealValue = FormatSI(self:GetHeal(Source, Item.Level)) .. "[c white] stacking HPS"
		else
			HealValue = FormatSI(self:GetTotalHeal(Source, Item.Level)) .. "[c white] stacking HP"
		end

		return
			"Imbue " .. self:GetTargetText(Source, Item) ..
			" with sanctuary for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds, " ..
			"granting [c green]" .. FormatSI(self:GetArmor(Source, Item.Level)) .. "[c white] armor, " ..
			"[c green]" .. FormatSI(self:GetDamageBlock(Source, Item.Level)) .. "[c white] damage block and [c green]" .. HealValue .. "[c white]\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Sanctuary.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Resurrect --

Spell_Resurrect = Base_Spell:New({

	TargetCount = Growth_Linear:New({ A = 5 / 49.0, B = 1 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.25, B = 25, C = 200 }),
	Heal = Growth_Polynomial:New({ E = 3, A = 0.025, B = 25, C = 100 }),
	Mana = Growth_Polynomial:New({ E = 3, A = 0.025, B = 25, C = 100 }),
	Stamina = Growth_Linear:New({ A = 100 / 49.0, B = 0 }),

	GetHeal = function(self, Source, Level)
		return self.Heal:ModifiedResult(Level, Source.HealPower * 0.01)
	end,

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

	GetStamina = function(self, Source, Level)
		return self.Stamina:Result(Level)
	end,

	GetInfo = function(self, Source, Item)
		return
			"Resurrect " .. self:GetTargetText(Source, Item) ..
			", giving them [c green]" .. FormatSI(self:GetHeal(Source, Item.Level)) .. "[c white] HP, " ..
			"[c green]" .. FormatSI(self:GetMana(Source, Item.Level)) .. "[c white] MP, and " ..
			"[c green]" .. self:GetStamina(Source, Item.Level) .. "%[c white] [c yellow]stamina\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP\n\n" ..
			"[c yellow]Can be used outside of battle"
	end,

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

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Health = self:GetHeal(Source, Level)
		Result.Target.Mana = self:GetMana(Source, Level)
		Result.Target.Stamina = self:GetStamina(Source, Level) * 0.01
		Result.Target.Corpse = 1
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Empower --

Spell_Empower = Base_Spell:New({

	TargetCount = Growth_Linear:New({ A = 5 / 49.0, B = 3 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.25, B = 20, C = 100 }),
	BuffLevel = Growth_Linear:New({ A = 85 / 49.0, B = 15 }),
	Duration = Growth_Linear:New({ A = 0, B = 10 }),

	GetBuffLevel = function(self, Source, Level)
		return self.BuffLevel:Result(Level)
	end,

	GetInfo = function(self, Source, Item)
		return
			"Empower " .. self:GetTargetText(Source, Item) ..
			" with [c green]" .. self:GetBuffLevel(Source, Item.Level) .. "%[c white] attack power for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Empowered.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Hasten --

Spell_Hasten = Base_Spell:New({

	TargetCount = Growth_Linear:New({ A = 5 / 49.0, B = 3 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.25, B = 20, C = 100 }),
	BuffLevel = Growth_Linear:New({ A = 75 / 49.0, B = 25 }),
	Duration = Growth_Linear:New({ A = 0, B = 10 }),

	GetBuffLevel = function(self, Source, Level)
		return self.BuffLevel:Result(Level)
	end,

	GetInfo = function(self, Source, Item)
		return
			"Hasten " .. self:GetTargetText(Source, Item) ..
			" with [c green]" .. self:GetBuffLevel(Source, Item.Level) .. "%[c white] battle speed for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Hasted.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Magic Barrier --

Spell_MagicBarrier = Base_Spell:New({

	AttributeName = "Mana",
	TargetCount = Growth_Linear:New({ A = 6 / 49.0, B = 1 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.25, B = 10, C = 25 }),
	BuffLevel = Growth_Polynomial:New({ E = 4, A = 0.0015, B = 40, C = 120 }),
	Duration = Growth_Linear:New({ A = 30 / 49.0, B = 10.0 }),

	GetPower = function(self, Source, Level)
		return Source[self.AttributeName .. "Power"] * 0.01
	end,

	GetInfo = function(self, Source, Item)
		return
			"Create a magic shield around " .. self:GetTargetText(Source, Item) .. " that absorbs [c green]" .. FormatSI(self:GetBuffLevel(Source, Item.Level)) .. "[c white] attack damage\n" ..
			"Lasts [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP\n\n" ..
			"[c yellow]Shield increased with mana power\n"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Shielded.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Light --

Spell_Light = Base_Spell:New({

	ManaCost = Base_Spell.ManaCost:New({ A = 0.25, B = 5, C = 50 }),
	LightID = Growth_Linear:New({ A = 1, B = 100, Max = 149 }),
	Duration = Growth_Polynomial:New({ E = 2, A = 0.1399, B = 5.0, C = 20.0 }),

	GetInfo = function(self, Source, Item)
		return
			"Emit magic light for [c green]" .. FormatDuration(math.floor(self:GetDuration(Source, Item.Level))) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Light.Pointer
		Result.Target.BuffLevel = math.min(self.LightID:Result(Level), self.LightID.Max)
		Result.Target.BuffDuration = math.floor(self:GetDuration(Source, Level))
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Base Single Target Spell --

local Base_Single = Base_Spell:New({

	TargetCount = Growth_Linear:New({ A = 2 / 49.0, B = 1 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.24 }),
})

-- Spark --

Spell_Spark = Base_Single:New({

	AttributeName = "Lightning",
	ManaCost = Base_Single.ManaCost:New({ B = 5, C = 10 }),
	Chance = Growth_Linear:New({ A = 40 / 49.0, B = 30 }),
	Duration = Growth_Linear:New({ A = 3 / 49.0, B = 1 }),
	Damage = Growth_Polynomial:New({ A = 0.002, B = 25, C = 40, E = 3.95, Range = 0.3 }),

	GetInfo = function(self, Source, Item)
		return
			"Shock " .. self:GetTargetText(Source, Item) ..
			" for " .. self:GetDamageText(Source, Item) .. " lightning damage with a [c green]" .. self:GetChance(Source, Item.Level) .. "%[c white] chance to stun for " ..
			"[c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		if Roll <= self:GetChance(Source, Level) then
			Result.Target.Buff = Buff_Stunned.Pointer
			Result.Target.BuffLevel = 1
			Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
			return true
		end

		return false
	end,

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

-- Icicle --

Spell_Icicle = Base_Single:New({

	AttributeName = "Cold",
	ManaCost = Base_Single.ManaCost:New({ B = 5, C = 15 }),
	Slow = Growth_Linear:New({ A = 10 / 49.0, B = 30 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.ColdDuration }),
	Damage = Growth_Polynomial:New({ A = 0.002, B = 20, C = 35, E = 3.95, Range = 0.1 }),
	IceImpDamage = Growth_Linear:New({ A = 135 / 49.0, B = 15 }),

	GetInfo = function(self, Source, Item)
		return
			"Pierce " .. self:GetTargetText(Source, Item) .. " for " .. self:GetDamageText(Source, Item) .. " cold damage\n" ..
			"Slows by [c green]" .. self.Slow:Result(Item.Level) .. "%[c white] for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Slowed enemies take [c green]" .. self.IceImpDamage:Result(Item.Level) .. "%[c white] more damage from ice imps\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		Result.Target.Buff = Buff_Slowed.Pointer
		Result.Target.BuffLevel = self.Slow:Result(Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		Result.Target.BuffModifier = self.IceImpDamage:Result(Level)

		return true
	end,

	PlaySound = function(self)
		Audio.Play("ice" .. Random.GetInt(0, 1) .. ".ogg", 0.4)
	end,
})

-- Ignite --

Spell_Ignite = Base_Single:New({

	AttributeName = "Fire",
	ManaCost = Base_Single.ManaCost:New({ B = 9, C = 30 }),
	BuffLevel = Growth_Polynomial:New({ A = 0.0012, B = 10, C = 50, E = 3.4 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.FireDuration }),

	GetInfo = function(self, Source, Item)
		local DamageValue
		if Item.MoreInfo == true then
			DamageValue = FormatSI(self:GetBuffLevel(Source, Item.Level)) .. "[c white] stacking fire DPS"
		else
			DamageValue = FormatSI(self:GetBuffDamage(Source, Item.Level)) .. "[c white] stacking fire damage over [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds"
		end

		return
			"Ignite " .. self:GetTargetText(Source, Item) .. " and deal [c green]" .. DamageValue .. "\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Burning.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Poison Touch --

Spell_PoisonTouch = Base_Single:New({

	AttributeName = "Poison",
	ManaCost = Base_Single.ManaCost:New({ B = 8, C = 20 }),
	BuffLevel = Growth_Polynomial:New({ A = 0.001, B = 6, C = 10, E = 3.4 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.PoisonDuration }),
	SkeletonDamage = Growth_Linear:New({ A = 75 / 49.0, B = 25 }),

	GetInfo = function(self, Source, Item)
		local DamageValue
		if Item.MoreInfo == true then
			DamageValue = FormatSI(self:GetBuffLevel(Source, Item.Level)) .. "[c white] stacking poison DPS"
		else
			DamageValue = FormatSI(self:GetBuffDamage(Source, Item.Level)) .. "[c white] stacking poison damage over [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds"
		end

		return
			"Infuse venom into " .. self:GetTargetText(Source, Item) .. ", dealing [c green]" .. DamageValue .. "\n" ..
			"Poison touched enemies take [c green]" .. self.SkeletonDamage:Result(Item.Level) .. "%[c white] more damage from skeletons\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP\n\n" ..
			"[c yellow]Heal power is reduced when poisoned"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Poisoned.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		Result.Target.BuffModifier = self.SkeletonDamage:Result(Level)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Base Multi Target Spell --

local Base_Multi = Base_Spell:New({

	TargetCount = Growth_Linear:New({ A = 2 / 49.0, B = 3 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.30 }),
	Damage = Growth_Polynomial:New({ E = 2.5, A = 0.75 }),
})

-- Fireball --

Spell_Fireball = Base_Multi:New({

	AttributeName = "Fire",
	ManaCost = Base_Multi.ManaCost:New({ B = 10, C = 50 }),
	Damage = Base_Multi.Damage:New({ A = 0.8, B = 24, C = 60, E = 2.5, Range = 0.2 }),

	GetInfo = function(self, Source, Item)
		return
			"Hurl a flaming ball at " .. self:GetTargetText(Source, Item) .. " for [c green]" .. self:GetDamageText(Source, Item) .. "[c white] fire damage\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	PlaySound = function(self)
		Audio.Play("blast" .. Random.GetInt(0, 1) .. ".ogg")
	end,
})

-- Base All Target Spell --

local Base_All = Base_Spell:New({

	TargetCount = Growth_Linear:New({ A = 4 / 49.0, B = 4 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.35 }),
	Damage = Growth_Polynomial:New({ E = 2.25, A = 1.3 }),
})

-- Fire Blast --

Spell_FireBlast = Base_All:New({

	AttributeName = "Fire",
	ManaCost = Base_All.ManaCost:New({ B = 20, C = 160 }),
	BuffLevel = Growth_Polynomial:New({ A = 0.001, B = 5, C = 10, E = 3.4 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.FireDuration }),
	Damage = Base_All.Damage:New({ B = 35, C = 150, Range = 0.2 }),

	GetInfo = function(self, Source, Item)
		local DamageValue
		if Item.MoreInfo == true then
			DamageValue = FormatSI(self:GetBuffLevel(Source, Item.Level)) .. "[c white] stacking fire DPS"
		else
			DamageValue = FormatSI(self:GetBuffDamage(Source, Item.Level)) .. "[c white] stacking fire damage over [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds"
		end

		return
			"Blast " .. self:GetTargetText(Source, Item) .. " for [c green]" .. self:GetDamageText(Source, Item) .. "[c white] fire damage, then igniting them for [c green]" .. DamageValue .. "\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	PlaySound = function(self)
		Audio.Play("blast" .. Random.GetInt(0, 1) .. ".ogg")
	end,

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		Result.Target.Buff = Buff_Burning.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)

		return true
	end,
})

-- Ice Nova --

Spell_IceNova = Base_All:New({

	AttributeName = "Cold",
	ManaCost = Base_All.ManaCost:New({ B = 20, C = 180 }),
	Slow = Growth_Linear:New({ A = 30 / 49.0, B = 20 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.ColdDuration }),
	Damage = Base_All.Damage:New({ B = 25, C = 125, Range = 0.15 }),
	IceImpDamage = Growth_Linear:New({ A = 175 / 49.0, B = 25 }),

	GetInfo = function(self, Source, Item)
		return
			"Summon an icy explosion, hitting " .. self:GetTargetText(Source, Item) ..
			" for [c green]" .. self:GetDamageText(Source, Item) .. "[c white] cold damage that slows by [c green]" .. self.Slow:Result(Item.Level) .. "%[c white] for " ..
			"[c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Slowed enemies take [c green]" .. self.IceImpDamage:Result(Item.Level) .. "%[c white] more damage from ice imps\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		Result.Target.Buff = Buff_Slowed.Pointer
		Result.Target.BuffLevel = self.Slow:Result(Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		Result.Target.BuffModifier = self.IceImpDamage:Result(Level)

		return true
	end,

	PlaySound = function(self)
		Audio.Play("blast" .. Random.GetInt(0, 1) .. ".ogg")
	end,
})

-- Chain Lightning --

Spell_ChainLightning = Base_All:New({

	AttributeName = "Lightning",
	ManaCost = Base_All.ManaCost:New({ B = 18, C = 190 }),
	Chance = Growth_Linear:New({ A = 40 / 49.0, B = 35 }),
	Duration = Growth_Linear:New({ A = 3 / 49.0, B = 2 }),
	Damage = Base_All.Damage:New({ B = 30, C = 170, Range = 0.35 }),

	GetInfo = function(self, Source, Item)
		return
			"Summon a powerful bolt of energy, hitting " .. self:GetTargetText(Source, Item) ..
			" for [c green]" .. self:GetDamageText(Source, Item) .. "[c white] lightning damage with a [c green]" .. self:GetChance(Source, Item.Level) .. "%[c white] chance to stun for " ..
			"[c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		if Roll <= self:GetChance(Source, Level) then
			Result.Target.Buff = Buff_Stunned.Pointer
			Result.Target.BuffLevel = 1
			Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
			return true
		end

		return false
	end,

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

-- Rupture --

Spell_Rupture = Base_All:New({

	AttributeName = "Poison",
	ManaCost = Base_All.ManaCost:New({ B = 25, C = 230 }),
	BuffLevel = Growth_Polynomial:New({ A = 0.002, B = 10, C = 20, E = 3.74 }),
	Duration = Growth_Linear:New({ A = 0, B = Game.PoisonDuration }),
	Damage = Base_All.Damage:New({ E = 2.5, A = 1.35, B = 35, C = 130, Range = 0.2 }),
	SkeletonDamage = Growth_Linear:New({ A = 150 / 49.0, B = 50 }),

	GetPower = function(self, Source, Level)
		return Source.PhysicalPower * 0.01 * Source.SpellDamage * 0.01
	end,

	GetBuffLevel = function(self, Source, Level)
		return self.BuffLevel:ModifiedResult(Level, self:GetBuffPower(Source, Level))
	end,

	GetBuffPower = function(self, Source, Level)
		return Source[self.AttributeName .. "Power"] * 0.01 * Source.SpellDamage * 0.01
	end,

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

	GetInfo = function(self, Source, Item)
		local DamageValue
		if Item.MoreInfo == true then
			DamageValue = FormatSI(self:GetBuffLevel(Source, Item.Level)) .. "[c white] stacking poison DPS"
		else
			DamageValue = FormatSI(self:GetBuffDamage(Source, Item.Level)) .. "[c white] stacking poison damage over [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds"
		end

		return
			"Explode a corpse, dealing [c green]" .. self:GetDamageText(Source, Item) .. "[c white] physical damage and releasing noxious gas, " ..
			"covering " .. self:GetTargetText(Source, Item) .. " that deals [c green]" .. DamageValue .. "\n" ..
			"Covered enemies take [c green]" .. self.SkeletonDamage:Result(Item.Level) .. "%[c white] more damage from skeletons\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		if Target.Health == 0 then
			Result.Target.Corpse = -1
		else
			Result.Target.Buff = Buff_Poisoned.Pointer
			Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
			Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
			Result.Target.BuffModifier = self.SkeletonDamage:Result(Level)
		end

		return true
	end,

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

-- Base Debuff Spell --

Base_Debuff = Base_Spell:New({

	TargetCount = Growth_Linear:New({ A = 6 / 49.0, B = 2 }),
	ManaCost = Base_Spell.ManaCost:New({ A = 0.25 }),
	Duration = Growth_Linear:New({ A = 5 / 49.0, B = 5.0 }),

	GetPower = function(self, Source, Level)
		return 1
	end,
})

-- Enfeeble --

Spell_Enfeeble = Base_Debuff:New({

	ManaCost = Base_Debuff.ManaCost:New({ B = 10, C = 10 }),
	BuffLevel = Growth_Diminishing:New({ A = 150, B = 97, C = 25 }),

	GetInfo = function(self, Source, Item)
		return
			"Cripple " .. self:GetTargetText(Source, Item) ..
			", reducing their attack damage by [c green]" .. self:GetBuffLevel(Source, Item.Level) .. "%[c white] for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Weak.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Flay --

Spell_Flay = Base_Debuff:New({

	ManaCost = Base_Debuff.ManaCost:New({ B = 10, C = 20 }),
	BuffLevel = Growth_Diminishing:New({ A = 200, B = 100, C = 15 }),

	GetInfo = function(self, Source, Item)
		return
			"Strip the skin of " .. self:GetTargetText(Source, Item) ..
			", reducing their elemental resistances by [c green]" .. self:GetBuffLevel(Source, Item.Level) .. "%[c white] for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP\n\n" ..
			"[c yellow]Attracts summons"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Flayed.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		Result.Target.BuffPriority = Priority
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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

-- Fracture --

Spell_Fracture = Base_Debuff:New({

	ManaCost = Base_Debuff.ManaCost:New({ B = 10, C = 40 }),
	BuffLevel = Growth_Diminishing:New({ A = 200, B = 100, C = 15 }),

	GetInfo = function(self, Source, Item)
		return
			"Decimate the defenses of " .. self:GetTargetText(Source, Item) ..
			", reducing their physical, poison, and bleed resistances by [c green]" .. self:GetBuffLevel(Source, Item.Level) .. "%[c white] for " ..
			"[c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Costs [c light_blue]" .. self:GetManaCost(Source, Item.Level) .. "[c white] MP\n\n" ..
			"[c yellow]Attracts summons"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Buff = Buff_Fractured.Pointer
		Result.Target.BuffLevel = self:GetBuffLevel(Source, Level)
		Result.Target.BuffDuration = self:GetDuration(Source, Level, true)
		Result.Target.BuffPriority = Priority
		WeaponProc(Source, Target, Result, true)

		return Result
	end,

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