Files
wnsrc/gamemodes/darkrp/plugins/willardskills/libs/sh_skill.lua
lifestorm 6a58f406b1 Upload
2024-08-04 23:54:45 +03:00

451 lines
12 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
ix.skill = ix.skill or {}
ix.skill.list = ix.skill.list or {}
ix.skill.scale = ix.skill.scale or {}
ix.skill.MAX_SKILL = 50
if (SERVER) then
ix.log.AddType("skillsGetSkill", function(client, name)
return string.format("%s has selected the %s skill.", client:GetName(), name)
end)
ix.log.AddType("skillsRemovedSkill", function(client, name, oldXP)
if (oldXP > 0) then
return string.format("%s has removed the %s skill (experience was: %d).", client:GetName(), name, oldXP)
else
return string.format("%s has removed the %s skill.", client:GetName(), name)
end
end)
ix.log.AddType("skillLevelUp", function(client, name, newExp)
return string.format("%s has gained level %d in the %s skill.", client:GetName(), newExp, name)
end)
end
ix.char.RegisterVar("skill", {
default = {},
isLocal = true,
bNoDisplay = true,
field = "skills",
fieldType = ix.type.text,
OnSet = function(character, skillID, level)
if (!skillID) then
ErrorNoHalt("Attempted to set level but no skillID was provided!")
return
end
local skill = ix.skill:Find(skillID)
if (!skill) then
ErrorNoHalt("Attempted to set level on invalid skill "..skillID.."!")
return
end
if (!level) then
level = character:GetSkill(skill.uniqueID) + 1
end
level = math.floor(level)
if (level < 0 or level > ix.skill.MAX_SKILL) then
ErrorNoHalt("Attempted to set invalid level '"..level.."' on "..skill.name.."'.")
return
end
local skills = character:GetSkill()
local totalLevel = character:GetTotalSkillLevel()
local currentLevel = skills[skill.uniqueID] or 0
if (currentLevel <= level and totalLevel - currentLevel + level > ix.config.Get("MaxTotalSkill")) then
ErrorNoHalt("Attempted to add level "..skill.name.." above total skill level!")
return
end
local client = character:GetPlayer()
if (IsValid(client) and (skills[skill.uniqueID] or 0) < level) then
ix.log.Add(client, "skillLevelUp", skill.name, level)
if (character:GetSkillAutoLevel(skill.uniqueID)) then
client:NotifyLocalized("levelGained", skill.name, character:GetSkill(skill.uniqueID) + 1)
end
net.Start("ixSkillLevelUpSound")
net.Send(client)
end
if (level > 0) then
skills[skill.uniqueID] = level
else
skills[skill.uniqueID] = nil
end
character.vars.skill = skills
if (IsValid(client)) then
net.Start("ixCharacterSkill")
net.WriteUInt(character:GetID(), 32)
net.WriteString(skill.uniqueID)
net.WriteUInt(skills[skill.uniqueID] or 0, 8)
net.Send(client)
end
if (level == ix.skill.MAX_SKILL) then
character:SetSkillStoredExp(skill.uniqueID)
end
end,
OnGet = function(character, skillID)
local skills = character.vars.skill or {}
if (skillID) then
if (!ix.skill:Find(skillID)) then
ErrorNoHalt("Attempted to get skill level in invalid skill "..skillID..".")
end
return skills[skillID] != nil and skills[skillID] or 0
else
return skills
end
end,
OnValidate = function(self, value, data, client)
if (value != nil) then
if (istable(value)) then
local count = 0
for _, v in pairs(value) do
count = count + v
end
if (count > 10) then
return false, "unknownError"
end
else
return false, "unknownError"
end
end
end,
OnAdjust = function(self, client, data, value, newData)
newData.skill = value
end
})
ix.char.RegisterVar("skillAutoLevel", {
default = {},
isLocal = true,
bNoDisplay = true,
field = "skills_autolevel",
fieldType = ix.type.text,
OnSet = function(character, skillID)
if (!skillID) then
ErrorNoHalt("Attempted to set experience but no skillID was provided!")
return
end
local skill = ix.skill:Find(skillID)
if (!skill) then
ErrorNoHalt("Attempted to set experience on invalid skill "..skillID.."!")
return
end
local skills = character:GetSkillAutoLevel()
skills[skill.uniqueID] = !skills[skill.uniqueID]
character.vars.skillAutoLevel = skills
-- Level skill if possible
if (skills[skill.uniqueID] == true) then
character:LevelUpSkill(skill.uniqueID)
end
local client = character:GetPlayer()
if (IsValid(client)) then
net.Start("ixCharacterSkillAutoLevel")
net.WriteUInt(character:GetID(), 32)
net.WriteString(skill.uniqueID)
net.WriteBool(skills[skill.uniqueID])
net.Send(client)
end
end,
OnGet = function(character, skillID)
local skills = character.vars.skillAutoLevel or {}
if (skillID) then
return skills[skillID] != nil and skills[skillID] or false
else
return skills
end
end
})
ix.char.RegisterVar("skillStoredExp", {
default = {},
isLocal = true,
bNoDisplay = true,
field = "skills_storedexp",
fieldType = ix.type.text,
OnSet = function(character, skillID, exp)
if (!skillID) then
ErrorNoHalt("Attempted to set stored experience but no skillID was provided!")
return
end
local skill = ix.skill:Find(skillID)
if (!skill) then
ErrorNoHalt("Attempted to set stored experience on invalid skill "..skillID.."!")
return
end
local skills = character:GetSkillStoredExp()
if (character:GetSkill(skill.uniqueID) >= ix.skill.MAX_SKILL) then
skills[skill.uniqueID] = nil
elseif (isbool(exp)) then
if (!skills[skill.uniqueID] or skills[skill.uniqueID] < 1000) then
ErrorNoHalt("Attempted to level "..skill.name.." without enough stored experience!")
return
end
skills[skill.uniqueID] = math.max(skills[skill.uniqueID] - 1000, 0)
if (skills[skill.uniqueID] == 0 or character:GetSkill(skill.uniqueID) >= ix.skill.MAX_SKILL) then
skills[skill.uniqueID] = nil
end
else
exp = exp and math.floor(exp)
if (!exp or exp < 0) then
ErrorNoHalt("Attempted to set "..skill.name.." to invalid stored experience ("..(exp or "nil")..")!")
return
end
if (character:GetSkill(skill.uniqueID) >= ix.skill.MAX_SKILL) then
ErrorNoHalt("Attempted to add stored experience to "..skill.name.." which is max level already!")
return
end
if (skills[skill.uniqueID] and skills[skill.uniqueID] + exp >= 2000) then
ErrorNoHalt("Attempted to add stored experience to "..skill.name.." above total stored experience ceiling!")
end
skills[skill.uniqueID] = math.min((skills[skill.uniqueID] or 0) + exp, 1999)
end
character.vars.skillStoredExp = skills
local client = character:GetPlayer()
if (IsValid(client)) then
net.Start("ixCharacterSkillStoredExp")
net.WriteUInt(character:GetID(), 32)
net.WriteString(skill.uniqueID)
net.WriteInt(skills[skill.uniqueID] or -1, 32)
net.Send(client)
end
end,
OnGet = function(character, skillID)
local skills = character.vars.skillStoredExp or {}
if (skillID) then
return skills[skillID] != nil and skills[skillID] or 0
else
return skills
end
end
})
if (CLIENT) then
net.Receive("ixCharacterSkill", function()
local id = net.ReadUInt(32)
local character = ix.char.loaded[id]
if (character) then
local skill = net.ReadString()
local level = net.ReadUInt(8)
local skills = character:GetSkill()
skills[skill] = (level != 0 and level) or nil
character.vars.skill = skills
if (IsValid(ix.gui.skills)) then
ix.gui.skills.skillPanels[skill].skillLevel:SetText("Skill Level: "..character:GetSkillLevel(skill).."/"..ix.skill.MAX_SKILL)
end
end
end)
net.Receive("ixCharacterSkillAutoLevel", function()
local id = net.ReadUInt(32)
local character = ix.char.loaded[id]
if (character) then
local skill = net.ReadString()
local skillAutoLevel = character:GetSkillAutoLevel()
skillAutoLevel[skill] = net.ReadBool()
character.vars.skillAutoLevel = skillAutoLevel
if (IsValid(ix.gui.skills)) then
ix.gui.skills.skillPanels[skill].autoLevel.autoLevel = skillAutoLevel[skill]
end
end
end)
net.Receive("ixCharacterSkillStoredExp", function()
local id = net.ReadUInt(32)
local character = ix.char.loaded[id]
if (character) then
local skill = net.ReadString()
local exp = net.ReadInt(32)
local skillStoredExp = character:GetSkillStoredExp()
skillStoredExp[skill] = (exp != -1 and exp) or nil
character.vars.skillStoredExp = skillStoredExp
if (IsValid(ix.gui.skills)) then
local progress = math.Clamp(character:GetSkillStoredExp(skill) / 1000, 0, 1)
ix.gui.skills.skillPanels[skill].progressBar.progress = progress
ix.gui.skills.skillPanels[skill].processLabel:SetupText(character)
end
end
end)
local levelCD = 0
net.Receive("ixSkillLevelUpSound", function()
if (levelCD < CurTime()) then
surface.PlaySound("willardnetworks/skills/levelup.mp3")
levelCD = CurTime() + 5
end
end)
else
util.AddNetworkString("ixCharacterSkill")
util.AddNetworkString("ixCharacterSkillAutoLevel")
util.AddNetworkString("ixCharacterSkillStoredExp")
util.AddNetworkString("ixSkillLevelUp")
util.AddNetworkString("ixSkillSetAutoLevel")
util.AddNetworkString("ixSkillLevelUpSound")
net.Receive("ixSkillLevelUp", function(len, ply)
local character = ply:GetCharacter()
local skill = net.ReadString()
if (character and character:CanLevelSkill(skill)) then
character:LevelUpSkill(skill)
end
end)
net.Receive("ixSkillSetAutoLevel", function(len, ply)
local character = ply:GetCharacter()
local skill = net.ReadString()
if (character) then
character:SetSkillAutoLevel(skill)
end
end)
end
function ix.skill:RegisterSkill(uniqueID, data)
if (!uniqueID or type(uniqueID) != "string") then
ErrorNoHalt("Attempted to register skill without valid uniqueID.")
return
end
data.uniqueID = uniqueID
data.name = data.name or "Unknown"
data.description = data.description or "No description given."
data.actions = data.actions or {}
data.attributes = data.attributes or {}
data.scale = data.scale or {}
ix.skill.list[uniqueID] = data
end
function ix.skill:RegisterSkillAction(skillID, action)
local skill = self:Find(skillID)
if (!skill) then return end
for k, v in ipairs(skill.actions) do
if (v.uniqueID == action.uniqueID) then
skill.actions[k] = action
return
end
end
skill.actions[#skill.actions + 1] = action
end
function ix.skill:RegisterAttribute(skillID, attribute)
local skill = self:Find(skillID)
if (!skill) then return end
for k, v in ipairs(skill.attributes) do
if (v.uniqueID == attribute.uniqueID) then
skill.attributes[k] = attribute
return
end
end
skill.attributes[#skill.attributes + 1] = attribute
end
function ix.skill:RegisterSkillScale(skillID, uniqueID, data)
local skill = self:Find(skillID)
if (!skill) then return end
data.uniqueID = uniqueID
data.name = data.name or "Unknown"
data.description = data.description or "No description given."
data.minLevel = data.minLevel or 0
data.maxLevel = data.maxLevel or self.MAX_SKILL
data.minValue = data.minValue or 0
data.increase = data.increase or 1
data.digits = data.digits or 0
data.skill = skill.uniqueID
if (ix.skill.scale[uniqueID]) then
for k, v in ipairs(skill.scale) do
if v.uniqueID == uniqueID then
skill.scale[k] = data
end
end
else
skill.scale[#skill.scale + 1] = data
end
ix.skill.scale[uniqueID] = data
-- Register "non-recipe" for current skill scale
local RECIPE = ix.recipe:New()
RECIPE.uniqueID = "skillscale_"..uniqueID
RECIPE.name = "Current "..data.name
RECIPE.category = "Level Unlocks"
RECIPE.noIngredients = true
RECIPE.skillScale = true
RECIPE.skillScaleID = uniqueID
RECIPE.level = 0
RECIPE.skill = skillID
RECIPE:Register()
end
function ix.skill:Find(skill)
-- finds a skill based on input by stripping caps on input and looking through DB recursive
if (ix.skill.list[skill]) then
return ix.skill.list[skill]
else
skill = string.utf8lower(skill)
for _, data in pairs(ix.skill.list) do
if (string.find(string.utf8lower(data.name), skill)) then
return data
end
end
end
end