Reviewed-on: #1 Co-authored-by: Gonçalo Correia <goncalojoaocorreia@gmail.com> Co-committed-by: Gonçalo Correia <goncalojoaocorreia@gmail.com>
246 lines
8.2 KiB
Lua
Executable file
246 lines
8.2 KiB
Lua
Executable file
-- AltSystem Roll Logic
|
|
-- Handles /roll 20, captures the result, and applies modifiers.
|
|
|
|
AltSystem = AltSystem or {}
|
|
|
|
local pendingRollType = nil -- "attack" or "defense"
|
|
local pendingPetRoll = nil -- { rollType, mainRollValue } when awaiting pet/summon roll
|
|
|
|
-- Get the TRP3 character first name, falling back to the WoW unit name
|
|
local function GetCharacterName()
|
|
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.FN and characteristics.FN ~= "" then
|
|
return characteristics.FN
|
|
end
|
|
end
|
|
return UnitName("player")
|
|
end
|
|
|
|
-- Build the modifier description string for the announce message
|
|
local function BuildModifierString(modifiers)
|
|
local parts = {}
|
|
for _, mod in ipairs(modifiers) do
|
|
local sign = mod.value >= 0 and "+" or ""
|
|
table.insert(parts, sign .. mod.value .. " (" .. mod.name .. ")")
|
|
end
|
|
return table.concat(parts, " ")
|
|
end
|
|
|
|
-- Build the log message string (always uses the non-emote format with character name)
|
|
local function BuildLogMessage(rollValue, modifiers, total)
|
|
local name = GetCharacterName()
|
|
local modStr = BuildModifierString(modifiers)
|
|
if modStr ~= "" then
|
|
return name .. " rolled " .. rollValue .. " " .. modStr .. " = " .. total
|
|
else
|
|
return name .. " rolled " .. rollValue .. " = " .. total
|
|
end
|
|
end
|
|
|
|
-- Build the critical roll log message
|
|
local function BuildCriticalLogMessage(isCriticalSuccess)
|
|
local name = GetCharacterName()
|
|
if isCriticalSuccess then
|
|
return name .. " rolled a Critical Success!"
|
|
else
|
|
return name .. " rolled a Critical Failure!"
|
|
end
|
|
end
|
|
|
|
-- Add an entry to the roll log and refresh the UI
|
|
local function AddLogEntry(text)
|
|
local rollLog = AltSystem.State.rollLog
|
|
table.insert(rollLog, { text = text, timestamp = time() })
|
|
-- Cap at 100 entries
|
|
if #rollLog > 100 then
|
|
table.remove(rollLog, 1)
|
|
end
|
|
-- Refresh the log panel if it exists
|
|
if AltSystem.RefreshLogPanel then
|
|
AltSystem:RefreshLogPanel()
|
|
end
|
|
end
|
|
|
|
-- Send a message to the given channel.
|
|
local function SendToChannel(msg, channel)
|
|
SendChatMessage(msg, channel)
|
|
end
|
|
|
|
-- Announce the roll result to the selected chat channel
|
|
local function AnnounceRoll(rollValue, modifiers, total)
|
|
if not AltSystem.State.announceEnabled then return end
|
|
|
|
local channelDef = AltSystem.AnnounceChannels[AltSystem.State.announceChannelIndex]
|
|
if not channelDef then return end
|
|
|
|
local isEmote = channelDef.channel == "EMOTE"
|
|
local modStr = BuildModifierString(modifiers)
|
|
|
|
local msg
|
|
if isEmote then
|
|
if modStr ~= "" then
|
|
msg = "rolled " .. rollValue .. " " .. modStr .. " = " .. total
|
|
else
|
|
msg = "rolled " .. rollValue .. " = " .. total
|
|
end
|
|
else
|
|
local name = GetCharacterName()
|
|
if modStr ~= "" then
|
|
msg = name .. " rolled " .. rollValue .. " " .. modStr .. " = " .. total
|
|
else
|
|
msg = name .. " rolled " .. rollValue .. " = " .. total
|
|
end
|
|
end
|
|
|
|
SendToChannel(msg, channelDef.channel)
|
|
end
|
|
|
|
-- Announce a critical roll result
|
|
local function AnnounceCritical(isCriticalSuccess)
|
|
if not AltSystem.State.announceEnabled then return end
|
|
|
|
local channelDef = AltSystem.AnnounceChannels[AltSystem.State.announceChannelIndex]
|
|
if not channelDef then return end
|
|
|
|
local critText = isCriticalSuccess and "rolled a Critical Success!" or "rolled a Critical Failure!"
|
|
local msg
|
|
if channelDef.channel == "EMOTE" then
|
|
msg = critText
|
|
else
|
|
msg = GetCharacterName() .. " " .. critText
|
|
end
|
|
|
|
SendToChannel(msg, channelDef.channel)
|
|
end
|
|
|
|
-- Perform a roll: triggers the WoW native /roll 20 command
|
|
function AltSystem:PerformRoll(rollType)
|
|
pendingPetRoll = nil
|
|
pendingRollType = rollType
|
|
RandomRoll(1, 20)
|
|
end
|
|
|
|
-- Listen for the system message that contains the roll result
|
|
local rollListener = CreateFrame("Frame")
|
|
rollListener:RegisterEvent("CHAT_MSG_SYSTEM")
|
|
|
|
rollListener:SetScript("OnEvent", function(self, event, message)
|
|
-- Phase 2: waiting for pet/summon roll result (1-5)
|
|
if pendingPetRoll then
|
|
local petRoller, petRoll = message:match("(.+) rolls (%d+) %(1%-5%)")
|
|
if not petRoll then return end
|
|
if petRoller ~= UnitName("player") then return end
|
|
|
|
local petValue = tonumber(petRoll)
|
|
local info = pendingPetRoll
|
|
pendingPetRoll = nil
|
|
|
|
AltSystem:CalculateAndDisplayResult(info.rollType, info.mainRollValue, petValue)
|
|
return
|
|
end
|
|
|
|
-- Phase 1: waiting for main roll result (1-20)
|
|
if not pendingRollType then return end
|
|
|
|
-- Match the roll result pattern: "PlayerName rolls X (1-20)"
|
|
local roller, roll = message:match("(.+) rolls (%d+) %(1%-20%)")
|
|
if not roll then return end
|
|
if roller ~= UnitName("player") then return end
|
|
|
|
local rollValue = tonumber(roll)
|
|
local rollType = pendingRollType
|
|
pendingRollType = nil
|
|
|
|
-- If pet/summon is enabled, trigger a second roll (1-5)
|
|
if AltSystem.State.petSummonEnabled then
|
|
pendingPetRoll = { rollType = rollType, mainRollValue = rollValue }
|
|
RandomRoll(1, 5)
|
|
return
|
|
end
|
|
|
|
AltSystem:CalculateAndDisplayResult(rollType, rollValue)
|
|
end)
|
|
|
|
-- Calculate the final result based on the roll type and selected modifiers
|
|
function AltSystem:CalculateAndDisplayResult(rollType, rollValue, petRollValue)
|
|
-- Critical rolls bypass normal calculation
|
|
if rollValue == 1 then
|
|
AddLogEntry(BuildCriticalLogMessage(false))
|
|
AnnounceCritical(false)
|
|
return
|
|
elseif rollValue == 20 then
|
|
AddLogEntry(BuildCriticalLogMessage(true))
|
|
AnnounceCritical(true)
|
|
return
|
|
end
|
|
|
|
local state = AltSystem.State
|
|
local skill = AltSystem.Data.Skills[state.selectedSkillIndex]
|
|
local item = AltSystem.Data.Items[state.selectedItemIndex]
|
|
|
|
local skillMod = skill and skill.modifier or 0
|
|
local itemMod = item and item.modifier or 0
|
|
|
|
local total = rollValue
|
|
|
|
local modifiers = {}
|
|
|
|
local isBaseRoll = skill and skill.name == "Base roll"
|
|
|
|
local petMod = petRollValue or 0
|
|
|
|
if rollType == "attack" then
|
|
-- Attack Roll = roll + skill modifier + item modifier + pet/summon modifier
|
|
total = rollValue + skillMod + itemMod + petMod
|
|
|
|
if not isBaseRoll then
|
|
table.insert(modifiers, { name = skill and skill.name or "Skill", value = skillMod })
|
|
end
|
|
if itemMod ~= 0 then
|
|
table.insert(modifiers, { name = item and (item.label or item.name) or "Item", value = itemMod })
|
|
end
|
|
if petMod ~= 0 then
|
|
table.insert(modifiers, { name = "Pet", value = petMod })
|
|
end
|
|
|
|
elseif rollType == "defense" then
|
|
-- Defense Roll = roll + skill modifier + item modifier + defense modifier + shield modifier
|
|
local defense = AltSystem.Data.Defenses[state.selectedDefenseIndex]
|
|
local defenseMod = defense and defense.modifier or 0
|
|
local shieldMod = state.shieldEnabled and AltSystem.Data.ShieldModifier or 0
|
|
|
|
total = rollValue + skillMod + itemMod + defenseMod + shieldMod + petMod
|
|
|
|
if not isBaseRoll then
|
|
table.insert(modifiers, { name = skill and skill.name or "Skill", value = skillMod })
|
|
end
|
|
if itemMod ~= 0 then
|
|
table.insert(modifiers, { name = item and (item.label or item.name) or "Item", value = itemMod })
|
|
end
|
|
if defenseMod ~= 0 then
|
|
table.insert(modifiers, { name = defense and (defense.label or defense.name) or "Armor", value = defenseMod })
|
|
end
|
|
if shieldMod ~= 0 then
|
|
table.insert(modifiers, { name = "Shield", value = shieldMod })
|
|
end
|
|
if petMod ~= 0 then
|
|
table.insert(modifiers, { name = "Pet", value = petMod })
|
|
end
|
|
end
|
|
|
|
-- Add to log (always, regardless of announce setting)
|
|
AddLogEntry(BuildLogMessage(rollValue, modifiers, total))
|
|
|
|
-- Announce to chat (if enabled)
|
|
AnnounceRoll(rollValue, modifiers, total)
|
|
end
|
|
|
|
-- Format a modifier value with sign
|
|
function FormatModifier(value)
|
|
if value >= 0 then
|
|
return "+" .. value
|
|
else
|
|
return tostring(value)
|
|
end
|
|
end
|