Skills from TRP profile

This commit is contained in:
Gonçalo Correia 2026-04-11 19:38:19 +01:00
parent ce1c6768e1
commit 9e629aec31
4 changed files with 161 additions and 24 deletions

6
.idea/vcs.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View file

@ -1,5 +1,5 @@
-- AltSystem Data Definitions -- AltSystem Data Definitions
-- Contains dummy skill data, item options, defense options, and modifier constants. -- Contains skill data (fetched from TRP3 profile), item options, defense options, and modifier constants.
AltSystem = AltSystem or {} AltSystem = AltSystem or {}
AltSystem.Data = {} AltSystem.Data = {}
@ -12,18 +12,88 @@ AltSystem.Data.SkillLevels = {
["Master"] = 4, ["Master"] = 4,
} }
-- Dummy skill data: each skill has a name, icon, and level -- The "Unskilled" entry is always the first (default) skill
AltSystem.Data.Skills = { local UNSKILLED_ENTRY = { name = "Unskilled", level = "Unskilled", modifier = -4 }
{ name = "Swordsmanship", icon = "Interface\\Icons\\INV_Sword_04", level = "Expert" },
{ name = "Archery", icon = "Interface\\Icons\\INV_Weapon_Bow_05", level = "Adept" }, -- Default/fallback skill list used when no TRP3 profile skills are found
{ name = "Fire Magic", icon = "Interface\\Icons\\Spell_Fire_FlameBolt", level = "Master" }, local DEFAULT_SKILLS = {
{ name = "Healing", icon = "Interface\\Icons\\Spell_Holy_FlashHeal", level = "Novice" }, { name = "Unskilled", level = "Unskilled", modifier = -4 },
{ name = "Stealth", icon = "Interface\\Icons\\Ability_Stealth", level = "Adept" }, { name = "Novice Skill", level = "Novice", modifier = -2 },
{ name = "Adept Skill", level = "Adept", modifier = 0 },
{ name = "Expert Skill", level = "Expert", modifier = 2 },
{ name = "Master Skill", level = "Master", modifier = 4 },
} }
-- Pre-compute modifier for each skill based on its level -- Parse the skill level from the right-side text of a TRP3 personality trait.
for _, skill in ipairs(AltSystem.Data.Skills) do -- The level keyword must appear at the start of the string; anything after it is ignored.
skill.modifier = AltSystem.Data.SkillLevels[skill.level] or 0 -- Returns the level string and modifier, or nil if not recognized.
local function ParseSkillLevel(rightText)
if not rightText or rightText == "" then return nil, nil end
-- Trim leading/trailing whitespace
local trimmed = rightText:match("^%s*(.-)%s*$")
if not trimmed or trimmed == "" then return nil, nil end
-- Check if the text starts with a recognized level keyword
for _, levelName in ipairs({"Master", "Expert", "Adept", "Novice"}) do
if trimmed == levelName or trimmed:match("^" .. levelName .. "[%s%p]") then
return levelName, AltSystem.Data.SkillLevels[levelName]
end
end
return nil, nil
end
-- Fetch skills from the current TRP3 profile's personality traits.
-- Returns an array of skill entries, always starting with "Unskilled".
-- Falls back to the default list if no profile or no valid skills are found.
function AltSystem.Data:RefreshSkills()
local skills = {}
-- Always add Unskilled as the first entry
table.insert(skills, { name = UNSKILLED_ENTRY.name, level = UNSKILLED_ENTRY.level, modifier = UNSKILLED_ENTRY.modifier })
local foundAny = false
-- Try to read personality traits from the active TRP3 profile
if TRP3_API and TRP3_API.profile and TRP3_API.profile.getData then
local ok, characteristics = pcall(TRP3_API.profile.getData, "player/characteristics")
if ok and characteristics and characteristics.PS then
for _, trait in ipairs(characteristics.PS) do
local skillName = trait.LT
local rightText = trait.RT
if skillName and skillName ~= "" then
local level, modifier = ParseSkillLevel(rightText)
if level and modifier then
foundAny = true
table.insert(skills, {
name = skillName,
level = level,
modifier = modifier,
})
end
end
end
end
end
-- If no valid skills were found, use the default fallback list (skip first "Unskilled" since we already added it)
if not foundAny then
skills = {}
for _, skill in ipairs(DEFAULT_SKILLS) do
table.insert(skills, { name = skill.name, level = skill.level, modifier = skill.modifier })
end
end
AltSystem.Data.Skills = skills
return skills
end
-- Initialize with the default skill list
AltSystem.Data.Skills = {}
for _, skill in ipairs(DEFAULT_SKILLS) do
table.insert(AltSystem.Data.Skills, { name = skill.name, level = skill.level, modifier = skill.modifier })
end end
-- Item options: name and modifier (first entry = no item) -- Item options: name and modifier (first entry = no item)

75
UI.lua
View file

@ -10,6 +10,22 @@ local PADDING = 12
local ROW_HEIGHT = 30 local ROW_HEIGHT = 30
local LABEL_WIDTH = 80 local LABEL_WIDTH = 80
-- Helper: Build the skill option list from current AltSystem.Data.Skills
local function BuildSkillOptions()
local options = {}
for _, skill in ipairs(AltSystem.Data.Skills) do
local sign = skill.modifier >= 0 and "+" or ""
local text
if skill.level == "Unskilled" then
text = skill.name .. " (" .. sign .. skill.modifier .. ")"
else
text = skill.name .. " (" .. skill.level .. " " .. sign .. skill.modifier .. ")"
end
table.insert(options, { text = text })
end
return options
end
-- Helper: Create a modern dropdown (WowStyle1DropdownTemplate) -- Helper: Create a modern dropdown (WowStyle1DropdownTemplate)
local function CreateDropdown(parent, name, yOffset, labelText, options, defaultIndex, onSelect) local function CreateDropdown(parent, name, yOffset, labelText, options, defaultIndex, onSelect)
local label = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal") local label = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
@ -38,7 +54,7 @@ local function CreateDropdown(parent, name, yOffset, labelText, options, default
end end
end) end)
return dropdown return dropdown, function() return selectedIndex end, function(idx) selectedIndex = idx end
end end
function AltSystem:CreateMainFrame() function AltSystem:CreateMainFrame()
@ -66,20 +82,19 @@ function AltSystem:CreateMainFrame()
------------------------- -------------------------
-- Skill dropdown -- Skill dropdown
------------------------- -------------------------
local skillOptions = {} local skillOptions = BuildSkillOptions()
for _, skill in ipairs(AltSystem.Data.Skills) do
local levelMod = skill.modifier
local sign = levelMod >= 0 and "+" or ""
table.insert(skillOptions, {
text = skill.name .. " (" .. skill.level .. " " .. sign .. levelMod .. ")",
icon = skill.icon,
})
end
CreateDropdown(f, "AltSystemSkillDropdown", yPos, "Skill:", skillOptions, AltSystem.State.selectedSkillIndex, local skillDropdown, getSkillIndex, setSkillIndex = CreateDropdown(
f, "AltSystemSkillDropdown", yPos, "Skill:", skillOptions,
AltSystem.State.selectedSkillIndex,
function(index) function(index)
AltSystem.State.selectedSkillIndex = index AltSystem.State.selectedSkillIndex = index
end) end)
-- Store references for refreshing
AltSystem.SkillDropdown = skillDropdown
AltSystem.GetSkillIndex = getSkillIndex
AltSystem.SetSkillIndex = setSkillIndex
yPos = yPos - ROW_HEIGHT - 8 yPos = yPos - ROW_HEIGHT - 8
------------------------- -------------------------
@ -149,7 +164,7 @@ function AltSystem:CreateMainFrame()
local attackBtn = CreateFrame("Button", "AltSystemAttackRollBtn", f, "UIPanelButtonTemplate") local attackBtn = CreateFrame("Button", "AltSystemAttackRollBtn", f, "UIPanelButtonTemplate")
attackBtn:SetSize(btnWidth, 28) attackBtn:SetSize(btnWidth, 28)
attackBtn:SetPoint("TOPLEFT", f, "TOPLEFT", PADDING, yPos) attackBtn:SetPoint("TOPLEFT", f, "TOPLEFT", PADDING, yPos)
attackBtn:SetText("Attack Roll") attackBtn:SetText("Attack/Skill Roll")
local defenseBtn = CreateFrame("Button", "AltSystemDefenseRollBtn", f, "UIPanelButtonTemplate") local defenseBtn = CreateFrame("Button", "AltSystemDefenseRollBtn", f, "UIPanelButtonTemplate")
defenseBtn:SetSize(btnWidth, 28) defenseBtn:SetSize(btnWidth, 28)
@ -182,9 +197,45 @@ function AltSystem:CreateMainFrame()
AltSystem:PerformRoll("defense") AltSystem:PerformRoll("defense")
end) end)
-- Refresh skills from TRP3 profile each time the window is shown
f:SetScript("OnShow", function()
AltSystem:RefreshSkillDropdown()
end)
f:Hide() f:Hide()
AltSystem.MainFrame = f AltSystem.MainFrame = f
end end
-- Refresh the skill dropdown with current TRP3 profile data
function AltSystem:RefreshSkillDropdown()
AltSystem.Data:RefreshSkills()
-- Reset selection to 1 (Unskilled) since the skill list may have changed
AltSystem.State.selectedSkillIndex = 1
if AltSystem.SetSkillIndex then
AltSystem.SetSkillIndex(1)
end
-- Rebuild the dropdown menu with the new skill list
if AltSystem.SkillDropdown then
local skillOptions = BuildSkillOptions()
AltSystem.SkillDropdown:SetupMenu(function(dropdown, rootDescription)
for i, option in ipairs(skillOptions) do
rootDescription:CreateRadio(
option.text,
function(data) return data == AltSystem.State.selectedSkillIndex end,
function(data)
AltSystem.State.selectedSkillIndex = data
if AltSystem.SetSkillIndex then
AltSystem.SetSkillIndex(data)
end
end,
i
)
end
end)
end
end
-- Create the frame on file load so it's ready when Init runs -- Create the frame on file load so it's ready when Init runs
AltSystem:CreateMainFrame() AltSystem:CreateMainFrame()

View file

@ -1 +1,11 @@
# Feature: Skills # Feature: Skills
- The selectable skills should come from the currently active TRP profile
- The skills are defined in the TRP profile as 'Personality traits'
- For each trait:
- the left field represents the skill name
- the right field represents the skill level as a string (Novice, Adept, Expert, Master)
- should the right field have anything after the level, it is to be ignored
- should a skill have no recognizable level, it should be omitted from the list
- The list should have a default selected value of "Unskilled" which corresponds to a -4 modifier
- In case no skills are found in the profile, or no profile is selected, a default list should be displayed
- Unskilled, Novice Skill, Adept Skill, Expert Skill, Master Skill