-- Base Skill --

Base_Skill = Base_Object:New({

	TargetCount = Growth_Linear:New({ A = 0, B = 1 }),

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

	GetTargetText = function(self, Source, Item)
		local TargetID = Items[Item.ID].TargetID
		local TargetType = Targets[TargetID].Singular
		local TargetCount = self:GetTargetCount(Source, Item.Level, Item.MoreInfo)
		if TargetCount ~= 1 then
			TargetType = Targets[TargetID].Plural
		end

		return "[c green]" .. TargetCount .. "[c white] " .. TargetType
	end,

	GetDuration = function(self, Source, Level, ShowFractions)
		local Scalar = self.AttributeName and Source[self.AttributeName .. "Duration"] * 0.01 or 1
		return self.Duration:ModifiedResult(Level, Scalar, 0, ShowFractions and RoundDown2 or RoundDown1)
	end,
})

-- Bounty Hunt --

Skill_BountyHunt = Base_Skill:New({

	GetInfo = function(self, Source, Item)
		return "Attack a fugitive and attempt to claim their bounty\n\n[c yellow]Can use anywhere"
	end,

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

		return Result
	end,
})

-- Dodge --

Skill_Dodge = Base_Skill:New({

	Duration = Growth_Linear:New({ A = 2 / 49.0, B = 1 }),
	Evasion = Growth_Diminishing:New({ A = 56, B = 19.5, C = 50 }),
	StaminaGain = Buff_Dodge.StaminaGain,

	GetInfo = function(self, Source, Item)
		return
			"Gain [c green]" .. self.Evasion:Result(Item.Level) .. "%[c white] evasion for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Gain [c green]" .. math.floor(self.StaminaGain * 100) .. "%[c yellow] stamina [c white]for each attack dodged"
	end,

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

		return Result
	end,

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

-- Flee --

Skill_Flee = Base_Skill:New({

	Duration = Growth_Linear:New({ A = -4.5 / 49.0, B = 5 }),
	Chance = Growth_Diminishing:New({ A = 100, B = 32.5, C = 35 }),
	FatigueLevel = 30,
	MissMultiplier = 25,

	CanUse = function(self, Level, Source)
		if not Source.BossBattle then
			return true
		end
		return Source.BossBattle and Source.GoldStolen == 0
	end,

	GetAttempts = function(self, Source)
		if Source.Server == false then
			return 0
		end

		if Source.BattleID ~= nil and Battles[Source.BattleID] ~= nil then
			local Storage = Battles[Source.BattleID]
			if Storage[Source.ID] ~= nil then
				return Storage[Source.ID].FleeAttempts
			end
		end

		return 0
	end,

	GetChance = function(self, Source, Level)
		local ExtraChance = self:GetAttempts(Source) * self.MissMultiplier
		local Chance = math.min(self.Chance:Result(Level) + ExtraChance, 100)

		return Chance
	end,

	GetInfo = function(self, Source, Item)
		return
			"[c green]" .. self:GetChance(Source, Item.Level) .. "%[c white] chance to run away from battle\n" ..
			"Chance to flee goes up by [c green]" .. self.MissMultiplier .. "%[c white] after a failed attempt\n" ..
			"Causes [c yellow]fatigue [c white]for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n\n" ..
			"[c yellow]Unusable in boss battles after [c yellow]pickpocketing"
	end,

	ApplyCost = function(self, Source, Level, Result)
		Result.Source.Buff = Buff_Slowed.Pointer
		Result.Source.BuffLevel = self.FatigueLevel
		Result.Source.BuffDuration = self:GetDuration(Source, Level, true)

		return Result
	end,

	Proc = function(self, Roll, Level, Duration, Source, Target, Result)
		local Storage = Battles[Source.BattleID]
		if Storage[Source.ID] == nil then
			Storage[Source.ID] = { FleeAttempts = 0 }
		elseif Storage[Source.ID].FleeAttempts == nil then
			Storage[Source.ID].FleeAttempts = 0
		end

		if Roll <= self:GetChance(Source, Level) then
			Result.Target.Flee = true
			return true
		end

		Storage[Source.ID].FleeAttempts = Storage[Source.ID].FleeAttempts + 1

		return false
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		self:Proc(Random.GetInt(1, 100), Level, Duration, Source, Target, Result)

		return Result
	end,

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

-- Hunt --

Skill_Hunt = Base_Skill:New({

	Gold = Growth_Diminishing:New({ A = 56, B = 19.5, C = 10 }),

	GetInfo = function(self, Source, Item)
		local GoldPercent = self.Gold:Result(Item.Level)

		return
			"Attack another player and get [c green]" .. GoldPercent .. "%[c white] of their gold for a kill. " ..
			"If you die, you will lose [c green]" .. GoldPercent .. "%[c white] gold plus your bounty\n\n" ..
			"[c yellow]Must be in a PVP zone to use"
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		Result.Target.Hunt = self.Gold:Result(Level) * 0.01

		return Result
	end,
})

-- Parry --

Skill_Parry = Base_Skill:New({

	Duration = Growth_Linear:New({ A = 2.5 / 49.0, B = 0.5 }),
	DamageReduction = Growth_Diminishing:New({ A = 64.5, B = 30, C = 50 }),
	StaminaGain = Buff_Parry.StaminaGain,

	GetInfo = function(self, Source, Item)
		return
			"Block [c green]" .. self.DamageReduction:Result(Item.Level) .. "%[c white] attack damage for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds\n" ..
			"Gain [c green]" .. math.floor(self.StaminaGain * 100) .. "%[c yellow] stamina [c white]for each attack blocked\n" ..
			"Attackers are stunned for [c green]" .. Buff_Parry.StunDuration .. "[c white] second"
	end,

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

		return Result
	end,

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

-- Pickpocket --

Skill_Pickpocket = Base_Skill:New({

	TargetCount = Growth_Linear:New({ A = 1 / 49.0, B = 1 }),
	Chance = Growth_Diminishing:New({ A = 61, B = 50, C = 20 }),
	Gold = Growth_Diminishing:New({ A = 185, B = 101, C = 15 }),
	PlayerMultiplier = 0.2,

	GetChance = function(self, Source, Level)
		return math.min(100, math.floor(self.Chance:Result(Level) * self:GetMultiplier(Source)))
	end,

	GetGold = function(self, Level)
		return self.Gold:Result(Level, RoundDown1)
	end,

	GetGoldPlayer = function(self, Level)
		return self:GetGold(Level) * self.PlayerMultiplier
	end,

	GetMultiplier = function(self, Source)
		return Source.BattleSpeed / (math.abs(Source.BattleSpeed) + 500) * 6.0
	end,

	GetInfo = function(self, Source, Item)
		local TargetText = self:GetTargetText(Source, Item)

		return
			"[c green]" .. self:GetChance(Source, Item.Level) .. "%[c white] chance to steal [c green]" .. self:GetGold(Item.Level) .. "%][c white] gold from " .. TargetText .. "\n\n" ..
			"[c yellow]Steals [c green]" .. self:GetGoldPlayer(Item.Level) .. "%[c yellow] from players\n" ..
			"[c yellow]Chance modified by battle speed"
	end,

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

		if Roll <= self:GetChance(Source, Level) then
			local GoldAvailable = Target.Gold
			local GoldAmount
			if Target.MonsterID > 0 then
				GoldAmount = math.ceil(GoldAvailable * self:GetGold(Level) * 0.01)
			else
				GoldAmount = math.ceil(GoldAvailable * self:GetGoldPlayer(Level) * 0.01)
			end

			if GoldAmount <= Target.Gold then
				Result.Target.Gold = -GoldAmount
				Result.Source.GoldStolen = GoldAmount
			else
				Result.Target.Gold = 0
				Result.Source.GoldStolen = 0
			end

			return true
		else
			Result.Target.Miss = true
		end

		return false
	end,

	CanUse = function(self, Level, Source)
		return not Source.ZoneOnCooldown
	end,

	Use = function(self, Level, Duration, Source, Target, Result, Priority)
		self:Proc(Random.GetInt(1, 100), Level, Duration, Source, Target, Result)

		return Result
	end,
})

-- Taunt --

Skill_Taunt = Base_Skill:New({

	TargetCount = Growth_Linear:New({ A = 6 / 49.0, B = 2 }),
	Duration = Growth_Linear:New({ A = 2 / 49.0, B = 3 }),
	Spiky = Growth_Linear:New({ A = 300 / 49.0, B = 100 }),
	Evasion = Growth_Linear:New({ A = 50 / 49.0, B = 25 }),

	GetInfo = function(self, Source, Item)
		return
			"Taunt " .. self:GetTargetText(Source, Item) .. " for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds, forcing them to attack you " ..
			"while reducing their evasion by [c green]" .. self.Evasion:Result(Item.Level) .. "%[c white]\n" ..
			"Increase damage return power by [c green]" .. self.Spiky:Result(Item.Level) .. "%[c white] for [c green]" .. self:GetDuration(Source, Item.Level, true) .. "[c white] seconds"
	end,

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

		Result.Source.Buff = Buff_Spiky.Pointer
		Result.Source.BuffLevel = self.Spiky:Result(Level)
		Result.Source.BuffDuration = self:GetDuration(Source, Level, true)

		return Result
	end,

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