2025-06-07 22:50:13 -04:00
|
|
|
---@diagnostic disable: duplicate-set-field
|
2025-04-28 09:17:43 -04:00
|
|
|
Skills = Skills or {}
|
2025-06-22 21:11:25 -05:00
|
|
|
Skills.All = Skills.All or {}
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- XP Cache for performance
|
2025-12-23 19:27:27 -05:00
|
|
|
local cachedXp = {}
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Default skill object: currentXP (0 to required), level
|
2025-12-23 19:27:27 -05:00
|
|
|
local defaultSkills = { currentXP = 0, level = 1 }
|
|
|
|
|
|
|
|
|
|
function Skills.GetResourceName()
|
|
|
|
|
return "default"
|
|
|
|
|
end
|
2025-06-24 03:18:38 -05:00
|
|
|
|
2025-06-23 00:56:49 -05:00
|
|
|
-- Helper function to get or create a skill object
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param src number
|
|
|
|
|
---@param skillName string
|
|
|
|
|
---@return table
|
2025-06-23 00:56:49 -05:00
|
|
|
local function getOrCreateSkill(src, skillName)
|
2025-12-23 19:27:27 -05:00
|
|
|
if not src or not skillName then return table.clone(defaultSkills) end
|
2025-06-23 00:56:49 -05:00
|
|
|
|
|
|
|
|
local playerSkills = Framework.GetPlayerMetadata(src, "community_bridge_skills") or {}
|
|
|
|
|
if not playerSkills[skillName] then
|
2025-12-23 19:27:27 -05:00
|
|
|
playerSkills[skillName] = table.clone(defaultSkills)
|
2025-06-23 00:56:49 -05:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
return playerSkills[skillName]
|
|
|
|
|
end
|
|
|
|
|
|
2025-12-23 19:27:27 -05:00
|
|
|
---Calculate XP required for a level using RuneScape algorithm (with caching)
|
|
|
|
|
---@param level number
|
|
|
|
|
---@return number
|
|
|
|
|
function Skills.GetXPForLevel(level)
|
2025-06-24 03:18:38 -05:00
|
|
|
if not level or level < 1 then return 0 end
|
|
|
|
|
if level == 1 then return 0 end -- Level 1 requires 0 XP
|
2025-06-19 15:25:35 -04:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Check cache first
|
2025-12-23 19:27:27 -05:00
|
|
|
if cachedXp[level] then
|
|
|
|
|
return cachedXp[level]
|
2025-06-24 03:18:38 -05:00
|
|
|
end
|
2025-06-19 15:25:35 -04:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Calculate and cache
|
2025-06-22 21:11:25 -05:00
|
|
|
local xp = 0
|
|
|
|
|
for n = 1, level - 1 do
|
2025-06-24 03:18:38 -05:00
|
|
|
xp = xp + math.floor(n + 300 * (2 ^ (n / 7)))
|
2025-06-19 15:25:35 -04:00
|
|
|
end
|
2025-06-24 03:18:38 -05:00
|
|
|
local result = math.floor(xp / 4)
|
2025-12-23 19:27:27 -05:00
|
|
|
cachedXp[level] = result
|
2025-06-19 15:25:35 -04:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
return result
|
2025-06-19 15:25:35 -04:00
|
|
|
end
|
|
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Create a skill (for initialization)
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param name string
|
|
|
|
|
---@param maxLevel number
|
|
|
|
|
---@param baseXP number
|
|
|
|
|
---@return table
|
|
|
|
|
function Skills.Create(name, maxLevel, baseXP)
|
|
|
|
|
if not name then return {} end
|
2025-06-24 03:18:38 -05:00
|
|
|
Skills.All[name] = { name = name, maxLevel = maxLevel or 99, baseXP = baseXP or 50 }
|
|
|
|
|
return Skills.All[name]
|
2025-04-28 09:17:43 -04:00
|
|
|
end
|
|
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Get player's current level
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param src number
|
|
|
|
|
---@param skillName string
|
|
|
|
|
---@return number
|
|
|
|
|
function Skills.GetSkillLevel(src, skillName)
|
2025-06-22 22:06:05 -05:00
|
|
|
if not src or not skillName then return 1 end
|
2025-06-23 00:56:49 -05:00
|
|
|
local skill = getOrCreateSkill(src, skillName)
|
2025-06-22 22:06:05 -05:00
|
|
|
return skill.level or 1
|
|
|
|
|
end
|
|
|
|
|
|
2025-12-23 19:27:27 -05:00
|
|
|
-- returns scaled XP based on player level
|
|
|
|
|
---@param baseXP number
|
|
|
|
|
---@param playerLevel number
|
|
|
|
|
---@return integer
|
|
|
|
|
function Skills.GetScaledXP(baseXP, playerLevel)
|
2025-06-24 03:18:38 -05:00
|
|
|
return math.floor(baseXP * (1 + playerLevel * 0.05))
|
|
|
|
|
end
|
|
|
|
|
-- Get current XP (0 to required XP for current level)
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param src number
|
|
|
|
|
---@param skillName string
|
|
|
|
|
---@return number
|
|
|
|
|
function Skills.GetXP(src, skillName)
|
2025-06-24 03:18:38 -05:00
|
|
|
if not src or not skillName then return 0 end
|
|
|
|
|
local skill = getOrCreateSkill(src, skillName)
|
|
|
|
|
local currentXP = skill.currentXP or 0
|
|
|
|
|
return currentXP
|
|
|
|
|
end
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Get XP required to complete the current level
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param level number
|
|
|
|
|
---@return number
|
|
|
|
|
function Skills.GetXPRequiredForLevel(level)
|
2025-06-24 03:18:38 -05:00
|
|
|
if not level or level < 1 then return 0 end
|
|
|
|
|
if level == 1 then return 83 end -- Level 1 to 2 requires 83 XP
|
2025-06-24 04:02:38 -05:00
|
|
|
return Skills.GetXPForLevel(level)
|
2025-04-28 09:17:43 -04:00
|
|
|
end
|
|
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Add XP and handle level ups
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param src number
|
|
|
|
|
---@param skillName string
|
|
|
|
|
---@param xp number
|
|
|
|
|
---@return boolean, number, number
|
|
|
|
|
function Skills.AddXP(src, skillName, xp)
|
|
|
|
|
if not src or not skillName then return false, 0, 0 end
|
2025-06-19 15:25:35 -04:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
if not xp or xp <= 0 then
|
|
|
|
|
xp = Skills.GetScaledXP(50, Skills.GetSkillLevel(src, skillName))
|
2025-06-22 22:06:05 -05:00
|
|
|
end
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-22 22:06:05 -05:00
|
|
|
local playerSkills = Framework.GetPlayerMetadata(src, "community_bridge_skills") or {}
|
2025-06-24 03:18:38 -05:00
|
|
|
local skill = playerSkills[skillName]
|
|
|
|
|
if not skill then
|
2025-12-23 19:27:27 -05:00
|
|
|
skill = table.clone(defaultSkills)
|
2025-06-24 03:18:38 -05:00
|
|
|
playerSkills[skillName] = skill
|
|
|
|
|
end
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
local oldLevel = skill.level or 1
|
|
|
|
|
local currentXP = skill.currentXP or 0
|
|
|
|
|
|
2025-12-23 19:27:27 -05:00
|
|
|
currentXP = currentXP + xp
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 04:02:38 -05:00
|
|
|
local xpNeeded = Skills.GetXPRequiredForLevel(oldLevel + 1)
|
|
|
|
|
if currentXP >= xpNeeded then
|
2025-06-30 02:07:20 -05:00
|
|
|
currentXP = currentXP - xpNeeded
|
2025-06-24 04:02:38 -05:00
|
|
|
oldLevel = oldLevel + 1
|
2025-06-23 00:56:49 -05:00
|
|
|
end
|
|
|
|
|
|
2025-06-24 04:02:38 -05:00
|
|
|
skill.level = oldLevel
|
2025-06-24 03:18:38 -05:00
|
|
|
skill.currentXP = currentXP
|
2025-06-22 22:06:05 -05:00
|
|
|
playerSkills[skillName] = skill
|
2025-06-24 03:18:38 -05:00
|
|
|
|
2025-06-22 22:06:05 -05:00
|
|
|
Framework.SetPlayerMetadata(src, "community_bridge_skills", playerSkills)
|
|
|
|
|
|
2025-06-24 04:02:38 -05:00
|
|
|
return true, oldLevel, currentXP
|
2025-06-24 03:18:38 -05:00
|
|
|
end
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Set skill level directly (resets currentXP to 0)
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param src number
|
|
|
|
|
---@param skillName string
|
|
|
|
|
---@param level number
|
|
|
|
|
---@return boolean
|
|
|
|
|
function Skills.SetSkillLevel(src, skillName, level)
|
2025-06-24 03:18:38 -05:00
|
|
|
if not src or not skillName or not level or level < 1 then return false end
|
2025-06-19 15:25:35 -04:00
|
|
|
|
2025-06-22 21:11:25 -05:00
|
|
|
local playerSkills = Framework.GetPlayerMetadata(src, "community_bridge_skills") or {}
|
2025-12-23 19:27:27 -05:00
|
|
|
local skill = playerSkills[skillName] or table.clone(defaultSkills)
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
level = math.min(math.max(1, level), 99)
|
|
|
|
|
skill.level = level
|
|
|
|
|
skill.currentXP = 0
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-19 15:25:35 -04:00
|
|
|
playerSkills[skillName] = skill
|
|
|
|
|
Framework.SetPlayerMetadata(src, "community_bridge_skills", playerSkills)
|
|
|
|
|
return true
|
2025-05-10 00:01:56 -04:00
|
|
|
end
|
|
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
-- Set current XP directly
|
2025-12-23 19:27:27 -05:00
|
|
|
---@param src number
|
|
|
|
|
---@param skillName string
|
|
|
|
|
---@param xp number
|
|
|
|
|
---@return boolean
|
|
|
|
|
function Skills.SetXP(src, skillName, xp)
|
2025-06-24 03:18:38 -05:00
|
|
|
if not src or not skillName or not xp or xp < 0 then return false end
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
local playerSkills = Framework.GetPlayerMetadata(src, "community_bridge_skills") or {}
|
2025-12-23 19:27:27 -05:00
|
|
|
local skill = playerSkills[skillName] or table.clone(defaultSkills)
|
2025-06-23 00:56:49 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
skill.currentXP = xp
|
|
|
|
|
playerSkills[skillName] = skill
|
2025-06-22 22:06:05 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
Framework.SetPlayerMetadata(src, "community_bridge_skills", playerSkills)
|
|
|
|
|
return true
|
2025-06-23 00:56:49 -05:00
|
|
|
end
|
2025-06-22 22:06:05 -05:00
|
|
|
|
2025-06-24 03:18:38 -05:00
|
|
|
return Skills
|