Módulo:Equipinfo
Saltar para a navegação
Saltar para a pesquisa
A documentação para este módulo pode ser criada na página Módulo:Equipinfo/doc
local trim = mw.text.trim
local cargo = mw.ext.cargo
---A cached version of the current frame, the interface to the parser.
local currentFrame
---Holds the arguments from the template call.
local args_table
local isDebug
local debugStr = ''
---Return the l10n string associated with the `key`. Supplemental information can be passed via the replacement parameters `data1` and `data2`.
---@param key string
---@param data1 string
---@param data2 string
---@return string
local function l10n(key, data1, data2)
return currentFrame:expandTemplate{ title = 'localization/long', args = { 'getEquipInfo', key, ['$data1$'] = data1, ['$data2$'] = data2 } }
end
---Return a trimmed version of the value of the template parameter with the specified `key`.
---Return `nil` if the parameter is empty or unset.
---@param key string|number
---@return string|nil
local function getArg(key)
local value = args_table[key]
if not value then
return nil
end
value = trim(value)
if value == '' then
return nil
end
return value
end
---Split the `str` on each `div` in it and return the result as a table.
---Original version credit: http://richard.warburton.it. This version trims each substring.
---@param div string
---@param str string
---@return table|boolean
local function explode(div,str)
if (div=='') then return false end
local pos,arr = 0,{}
-- for each divider found
for st,sp in function() return string.find(str,div,pos,true) end do
arr[#arr + 1] = trim(string.sub(str,pos,st-1)) -- Attach chars left of current divider
pos = sp + 1 -- Jump past current divider
end
arr[#arr + 1] = trim(string.sub(str,pos)) -- Attach chars right of last divider
return arr
end
---Round the `number` on a number of digits specified by `dec`.
---@param x number
---@param dec number
---@return number
local function round(x, dec)
local factor = 10^(dec or 0)
return math.floor(x * factor + 0.5) / factor
end
---Return a string of all possible stats, comma-separated
---@return string
local getStatList = function()
return 'ccdryLight, cciceBarrier, ccwetLight, accCalendar, accCompass, accCritterGuide, accDepthMeter, accDivingHelm, accDreamCatcher, accFishFinder, accFishingBobber, accFishingLine, accFlipper, accJarOfSouls, accLavaFishing, accMerman, accOreFinder, accRunSpeed, accStopwatch, accTackleBox, accThirdEye, accWatch, accWeatherRadio, aggro, ammoCost75, ammoCost80, arcticDivingGear, armorPenetration, arrowDamage, arrowDamageAdditiveStack, autoActuator, autoJump, autoPaint, autoReuseGlove, blackBelt, blockRange, boneGloveItem, brainOfConfusionItem, buffImmune, bulletDamage, canFloatInWater, CanSeeInvisibleBlocks, carpet, chiselSpeed, chloroAmmoCost80, cordage, counterWeight, dashType, dd2Accessory, desertBoots, discount, dontHurtCritters, dontHurtNature, dontStarveShader, empressBrooch, endurance, equipmentBasedLuckBonus, equippedAnyTileRangeAcc, equippedAnyTileSpeedAcc, equippedAnyWallSpeedAcc, extraFall, fireWalk, fishingSkill, flowerBoots, goldRing, gravControl2, hasCreditsSceneMusicBox, hasJumpOption_Blizzard, hasJumpOption_Cloud, hasJumpOption_Fart, hasJumpOption_Sail, hasJumpOption_Sandstorm, hasLuck_LuckyCoin, hasLuck_LuckyHorseshoe, hasLuckyCoin, hasLucyTheAxe, hasMagiluminescence, hasMoltenQuiver, hasPaladinShield, honeyCombItem, huntressAmmoCost90, iceSkate, InfoAccMechShowWires, jumpBoost, jumpSpeedBoost, kbGlove, killClothier, killGuide, lavaMax, lavaRose, lifeRegen, longInvince, magicCrit, magicCuffs, magicDamage, magicQuiver, magmaStone, manaCost, manaFlower, manaMagnet, manaRegenBonus, manaRegenDelayBonus, maxMinions, maxTurrets, meleeCrit, meleeDamage, meleeScaleGlove, meleeSpeed, minionDamage, minionKB, moonLordLegs, moveSpeed, nightVision, noFallDmg, noKnockback, npcTypeNoAggro, panic, pickSpeed, preventAllItemPickups, pStone, rangedCrit, rangedDamage, remoteVisionForDrone, rocketBoots, rocketDamage, rulerGrid, rulerLine, scope, shimmerImmune, shinyStone, skyStoneEffects, slowFall, spikedBoots, sporeSac, starCloakItem, starCloakItem_beeCloakOverrideItem, starCloakItem_manaCloakOverrideItem, starCloakItem_starVeilOverrideItem, statManaMax2, strongBees, tileRangeX, tileRangeY, treasureMagnet, vanityRocketBoots, volatileGelatin, waterWalk, waterWalk2, whipRangeMultiplier, wolfAcc, yoyoGlove, yoyoString'
end
---Apply formatting to a single value.
---Return a table `{ data1, data2 }`, where:
---* `data1` holds the actual value, formatted
---* `data2` holds supplemental information, the nature of which depends on the `stat`:
--- * For most basic ± stats, it simply is empty if `data1` is negative, and not empty otherwise.
--- * For `accRunSpeed` and `desertDash`, it is the value wrapped in {{mph}}.
--- * For `buffImmune` (list of buffs), `counterWeight` (list of projectiles), and `npcTypeNoAggro` (list of npcs), it holds the number of items in the `data1` list.
---@param statvalues table The entire data table.
---@param stat string The stat name whose value is to be formatted.
---@return table|nil
local function formatStatValue(statvalues, stat)
local value = statvalues[stat] -- retrieve value from data table
if value == nil or value == '' then
return { nil }
end
if stat == 'accRunSpeed' then
-- pixels/tick → tiles/sec
local tps = round(value * 3.75, 2)
local mph = currentFrame:expandTemplate{ title = 'mph', args = { tps .. 'tiles' } }
return { tps, mph }
elseif stat == 'buffImmune' then
-- buff id → name
local valueList = explode('¤', value)
for i, buffId in ipairs(valueList) do
valueList[i] = currentFrame:expandTemplate{ title = 'exclusive icon link', args = { currentFrame:expandTemplate{ title = 'getBuffInfo', args = { buffId, 'name', lang='en' } } } }
end
return { table.concat(valueList, ', '), #valueList }
elseif stat == 'counterWeight' then
-- projectile id → name
local valueList = explode('¤', value)
for i, projectileId in ipairs(valueList) do
valueList[i] = currentFrame:expandTemplate{ title = 'exclusive icon link', args = { currentFrame:expandTemplate{ title = 'projectileNameFromId', args = { projectileId, lang='en' } } } }
end
return { table.concat(valueList, ', '), #valueList }
elseif stat == 'desertBoots' then
-- pixels/tick → tiles/sec
local tps = round(statvalues['accRunSpeed'] * 1.75 * 3.75, 2)
local mph = currentFrame:expandTemplate{ title = 'mph', args = { tps .. 'tiles' } }
return { tps, mph }
elseif stat == 'hasMagiluminescence' then
-- pixels/tick → tiles/sec
local tps = round(3 * 1.15 * 3.75, 2) -- default accRunSpeed is 3
local mph = currentFrame:expandTemplate{ title = 'mph', args = { tps .. 'tiles' } }
return { tps, mph }
elseif stat == 'lavaMax' then
-- ticks → {{duration}}
return { currentFrame:expandTemplate{ title = 'duration', args = { value/60 } } }
elseif stat == 'lifeRegen' then
-- half
return { value/2 }
elseif stat == 'allDamage' or stat == 'magicDamage' or stat == 'meleeDamage' or stat == 'minionDamage' or stat == 'rangedDamage' or stat == 'arrowDamage' or stat == 'bulletDamage' or stat == 'rocketDamage' or stat == 'meleeSpeed' or stat == 'moveSpeed' or stat == 'pickSpeed' or stat == 'manaCost' or stat == 'endurance' or stat == 'arrowDamageAdditiveStack' or stat == 'whipRangeMultiplier' then
-- decimal → {{percent}}
return { currentFrame:expandTemplate{ title = 'percent', args = { value } } }
elseif stat == 'allCrit' or stat == 'magicCrit' or stat == 'meleeCrit' or stat == 'rangedCrit' then
-- {{percent}}
return { currentFrame:expandTemplate{ title = 'percent', args = { value/100 } } } -- {{percent}} multiplies the input by 100
elseif stat == 'npcTypeNoAggro' then
-- npc id → name
local valueList = explode('¤', value)
for i, npcId in ipairs(valueList) do
valueList[i] = currentFrame:expandTemplate{ title = 'exclusive icon link', args = { currentFrame:expandTemplate{ title = 'npcNameFromId', args = { npcId, lang='en' } } } }
end
return { table.concat(valueList, ', '), #valueList }
end
-- no format
return { value }
end
---Return a table with the l10n key name and the formatted value of the `stat`.
---@param statvalues table The entire data table.
---@param stat string The stat name for which the l10n key and value is to be formatted.
---@return table formatted Contains two keys, `statFormatted` and `valueFormatted`.
local function formatStat(statvalues, stat)
-- format stat, for l10n key
local statFormatted = ''
if stat == 'accWatch' or stat == 'dashType' or stat == 'rocketBoots' then
--[[
the values of these three stats are like a switch
e.g. Copper Watch has "accWatch=1", Gold Watch has "accWatch=3"
so depending on the value, different l10n strings are needed
e.g. for Copper Watch: "displays the time down to the hour", for Gold Watch: "displays the time down to the minute"
and the l10n keys are based on the values, e.g. "stat_accWatch-1" for Copper Watch
]]
statFormatted = 'stat_' .. stat .. '-' .. statvalues[stat]
else
statFormatted = 'stat_' .. stat
end
-- format value
local valueFormatted = formatStatValue(statvalues, stat)
return { statFormatted = statFormatted, valueFormatted = valueFormatted }
end
---Return a string that is the fully formatted value of the specified `stat`.
---@param statvalues table The entire data table.
---@param stat string The stat name whose value is to be formatted.
---@return string
local function formatSingleStat(statvalues, stat)
local formatted = formatStat(statvalues, stat)
-- formatted is now: { ["statFormatted"] = "(l10n key)", ["valueFormatted"] = { data1, data2 } }
-- we only want data1, nothing else
return formatted['valueFormatted'][1]
end
---Return a string that is a bullet list with all stats in the `statvalues` table, fully formatted including l10n.
---@param statvalues table
---@return string
local function formatStatList(statvalues)
-- remove individual damage/crit stats if we have allDamage/allCrit
if statvalues['allDamage'] ~= nil then
statvalues['magicDamage'] = nil
statvalues['meleeDamage'] = nil
statvalues['minionDamage'] = nil
statvalues['rangedDamage'] = nil
end
if statvalues['allCrit'] ~= nil then
statvalues['magicCrit'] = nil
statvalues['meleeCrit'] = nil
statvalues['rangedCrit'] = nil
end
local statStr = '<ul>'
-- iterate over stats, apply formatting->l10n to each one.
-- stats may overwrite each other (e.g. accRunSpeed & desertBoots), so don't modify the stat table itself.
for stat, value in pairs(statvalues) do
local formatted = formatStat(statvalues, stat)
-- formatted is now: { ["statFormatted"] = "(l10n key)", ["valueFormatted"] = { data1, data2 } }
if formatted['valueFormatted'][2] == nil or formatted['valueFormatted'][2] == '' then -- if there is no supplemental formatting information
if tostring(value):sub(1, 1) ~= '-' then
formatted['valueFormatted'][2] = true -- set to true if value is positive
else
formatted['valueFormatted'][2] = ''
end
local vF1FirstChar = tostring(formatted['valueFormatted'][1]):sub(1, 1)
if vF1FirstChar == '-' or vF1FirstChar == '+' then
formatted['valueFormatted'][1] = tostring(formatted['valueFormatted'][1]):sub(2) -- strip +/- sign
end
end
statStr = statStr .. '<li>'
if isDebug then
statStr = statStr .. table.concat({ formatted['statFormatted'], formatted['valueFormatted'][1], formatted['valueFormatted'][2] }, '§§') .. ' – '
end
statStr = statStr .. l10n(formatted['statFormatted'], formatted['valueFormatted'][1], formatted['valueFormatted'][2]) .. '</li>'
end
if statStr == '<ul>' then
return ''
end
return statStr.. '</ul>'
end
---Return a statvalues table from an Equipinfo cargo query result.
---@param result table
---@return table
local function parseFrom(result)
local statvalues = {}
for _, row in ipairs(result) do -- iterate over rows
for stat, value in pairs(row) do -- iterate over columns
if value ~= '' then
local add = false
local valueFirstChar = tostring(value):sub(1, 1)
if statvalues[stat] ~= nil then
add = valueFirstChar == '+' or valueFirstChar == '-' -- if value starts with +/-, then do perform addition/subtraction
end
if valueFirstChar == '+' then
value = value:sub(2) -- strip plus sign
end
if add then
statvalues[stat] = statvalues[stat] + value
else
statvalues[stat] = value
end
end
end
end
return statvalues
end
---Pre-process the `statvalues` table: Add `allDamage`/`allCrit` if necessary, and resolve `equippedAnyTileRangeAcc`.
---@param statvalues table
---@return table statvalues
local function preProcessStatvalues(statvalues)
-- if all four damage values are the same and not nil, add an "allDamage" stat
local allDamageSet = (statvalues['magicDamage'] and statvalues['meleeDamage'] and statvalues['minionDamage'] and statvalues['rangedDamage']) ~= nil
if allDamageSet and statvalues['magicDamage'] == statvalues['meleeDamage'] and statvalues['meleeDamage'] == statvalues['minionDamage'] and statvalues['minionDamage'] == statvalues['rangedDamage'] then
statvalues['allDamage'] = statvalues['magicDamage']
end
-- if all three crit chance values are the same and not nil, add an "allCrit" stat
local allCritSet = (statvalues['magicCrit'] and statvalues['meleeCrit'] and statvalues['rangedCrit']) ~= nil
if allCritSet and statvalues['magicCrit'] == statvalues['meleeCrit'] and statvalues['meleeCrit'] == statvalues['rangedCrit'] then
statvalues['allCrit'] = statvalues['magicCrit']
end
-- if the "accFishingBobber" is set, pass its effects to "fishingSkill"
if statvalues['accFishingBobber'] then
statvalues['fishingSkill'] = (statvalues['fishingSkill'] or 0) + 10
end
-- if the "dd2Accessory" is set, pass its effects to "minionDamage" and "maxTurrets"
if statvalues['dd2Accessory'] then
statvalues['minionDamage'] = (statvalues['minionDamage'] or 0) + 0.1
statvalues['maxTurrets'] = (statvalues['maxTurrets'] or 0) + 1
end
-- if the "equippedAnyTileSpeedAcc" is set, pass its effects to "tileSpeed"
if statvalues['equippedAnyTileSpeedAcc'] then
statvalues['tileSpeed'] = (statvalues['tileSpeed'] or 0) + 0.5
end
-- if the "chiselSpeed" is set, pass its effects to "pickSpeed"
if statvalues['chiselSpeed'] then
statvalues['pickSpeed'] = (statvalues['pickSpeed'] or 0) - 0.25
end
-- if the "equippedAnyWallSpeedAcc" is set, pass its effects to "wallSpeed"
if statvalues['equippedAnyWallSpeedAcc'] then
statvalues['wallSpeed'] = (statvalues['wallSpeed'] or 0) + 0.5
end
-- if the "equippedAnyTileRangeAcc" is set, pass its effects to "tileRangeX" and "tileRangeY"
if statvalues['equippedAnyTileRangeAcc'] then
statvalues['tileRangeX'] = (statvalues['tileRangeX'] or 0) + 3
statvalues['tileRangeY'] = (statvalues['tileRangeY'] or 0) + 2
end
-- if the "hasLuck_LuckyHorseshoe" is set, pass its effects to "equipmentBasedLuckBonus"
if statvalues['hasLuck_LuckyHorseshoe'] then
statvalues['equipmentBasedLuckBonus'] = (statvalues['equipmentBasedLuckBonus'] or 0) + 0.05
end
-- if the "hasLuck_LuckyCoin" is set, pass its effects to "equipmentBasedLuckBonus"
if statvalues['hasLuck_LuckyCoin'] then
statvalues['equipmentBasedLuckBonus'] = (statvalues['equipmentBasedLuckBonus'] or 0) + 0.05
end
return statvalues
end
-----------------------------------------------------------------
-- main return object
return {
go = function(frame)
-- init cache
currentFrame = frame
args_table = frame.args
isDebug = getArg('debug')
-- prepare cargo query
local queryItemId = getArg('queryItemId')
local statList = getStatList()
local queryItemIdList = queryItemId:gsub('₴', ',') -- input is "1234₴42₴777", but SQL expects "1234,42,777"
-- fetch data: perform cargo query
local result = cargo.query('Equipinfo', statList, { where = 'itemid IN (' .. queryItemIdList .. ')' } )
if result == nil then return end
local statvalues = parseFrom(result)
statvalues = preProcessStatvalues(statvalues)
-- assemble output string
local outputMode = getArg('outputMode')
local queryStat = getArg('queryStat')
local outputStr = ''
if outputMode == 'raw' then
-- raw: just print the value as it is in cargo
outputStr = statvalues[queryStat]
elseif outputMode == 'singlestat' then
-- single stat: print the formatted value of one stat
outputStr = formatSingleStat(statvalues, queryStat)
elseif outputMode == 'listraw' then
-- raw list: print the values of all stats
for stat, value in pairs(statvalues) do
outputStr = outputStr .. stat .. ':' .. value .. ';'
end
elseif outputMode == 'list' then
-- list: print a fully formatted and localized bullet list with all stats
outputStr = formatStatList(statvalues)
end
if isDebug then
outputStr = '<small class="note-text">(debug start)' .. debugStr .. '(debug end)</small>' .. outputStr
end
return outputStr
end,
getStatList = getStatList,
}