Module:AbilityHints: Difference between revisionsGive feedback
Unlink automatic hint icons; wikilink game terms inside tooltips (with help from vergir-bot LLM) |
Use the standard interacts text for the enhanced state (with help from vergir-bot LLM) |
||
| (12 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
-- Small item icons on ability cards showing how an ability interacts with items (dispellable, reduced, blocked, etc.). | -- Small item icons on ability cards showing how an ability interacts with items (dispellable, reduced, blocked, etc.). | ||
-- Used by Template:AbilitySection. Styles are there too. | -- Used by Template:AbilitySection. Styles are there too. | ||
-- label_dict_key names the [[Data:Dictionary]] entry holding the tooltip text. It is | |||
-- resolved at render time rather than here, so the tooltip follows the page language | |||
-- and so no frame is needed while the module is still loading. | |||
local CONFIG = { | |||
{ list = "melee", file = "Melee Lifesteal.png", label_dict_key = "AbilityHintsMelee" }, | |||
{ list = "dontbreakstealth", file = "Veil Walker.png", label_dict_key = "AbilityHintsDontBreakStealth" }, | |||
{ list = "movementbased", file = "Slowing Hex.png", label_dict_key = "AbilityHintsMovementBased" }, | |||
{ list = "debuffresist", file = "Debuff Reducer.png", label_dict_key = "AbilityHintsDebuffResist" }, | |||
{ list = "heal", file = "Healing Booster.png", label_dict_key = "AbilityHintsHeal" }, | |||
{ list = "healingtempo", file = "Healing Tempo.png", label_dict_key = "AbilityHintsHealingTempo" }, | |||
{ list = "reactivebarrier", file = "Reactive Barrier.png", label_dict_key = "AbilityHintsReactiveBarrier" }, | |||
{ list = "dispelmagic", file = "Dispel Magic.png", label_dict_key = "AbilityHintsDispelMagic" }, | |||
{ list = "indomitable", file = "Indomitable.png", label_dict_key = "AbilityHintsIndomitable" }, | |||
{ list = "unstoppable", file = "Unstoppable.png", label_dict_key = "AbilityHintsUnstoppable" }, | |||
{ list = "platedarmor", file = "Plated Armor.png", label_dict_key = "AbilityHintsPlatedArmor" }, | |||
{ list = "summons", file = "Monster Rounds.png", label_dict_key = "AbilityHintsSummons" }, | |||
} | |||
-- Tooltip wording for a manually placed icon, keyed by its iconbox state. Each entry | |||
-- takes the item title as {{{1}}}, so translations can put the object where their | |||
-- grammar wants it rather than always after the verb. The enhanced state has no entry | |||
-- of its own: the glow already marks it, so it falls through to the normal wording. | |||
local STATE_DICT_KEYS = { | |||
normal = "AbilityHintsInteracts", | |||
disabled = "AbilityHintsInteractsNot", | |||
partial = "AbilityHintsInteractsPartial", | |||
} | |||
local AbilityTable = require("Module:AbilityTable") | local AbilityTable = require("Module:AbilityTable") | ||
local | local dictionary = require("Module:Dictionary") | ||
local resource_lookup = mw.loadJsonData("Data:ResourceLookup.json") | |||
local item_data = mw.loadJsonData("Data:ItemData.json") | |||
local p = {} | local p = {} | ||
-- Display order | -- Display order: item type (Weapon => Vitality => Spirit), then cost, then name. | ||
local | local function sort_key(file) | ||
local base = mw.ustring.lower((file:gsub('%.%w+$', ''))) | |||
local entry = resource_lookup[base] | |||
{ | local item = (entry ~= nil and entry.type == 'item') and item_data[entry.key] or nil | ||
if item == nil then | |||
return { 99, math.huge, base } | |||
end | |||
{ | local slot = item["Slot"] | ||
local slot_rank = (slot == "Weapon" and 1) or (slot == "Armor" and 2) or (slot == "Tech" and 3) or 98 | |||
return { | |||
slot_rank, | |||
tonumber(item["Cost"]) or math.huge, | |||
mw.ustring.lower(item["Name"] or base), | |||
} | |||
end | |||
local function compare(a, b) | |||
for i = 1, 3 do | |||
if a.sort[i] ~= b.sort[i] then return a.sort[i] < b.sort[i] end | |||
end | |||
return false | |||
end | |||
-- partial: split the icon so the top-left half is grayscale (mirrors the | -- partial: split the icon so the top-left half is grayscale (mirrors the iconbox-partial box icon). | ||
-- An empty link makes the icon non-clickable; automatic hints link from their tooltip text instead. | -- An empty link makes the icon non-clickable; automatic hints link from their tooltip text instead. | ||
local function icon_img(file, link, partial) | local function icon_img(file, link, partial) | ||
| Line 36: | Line 76: | ||
local function hint_icon(def) | local function hint_icon(def) | ||
return '<span class="ability-hint">' .. icon_img(def.file) | return '<span class="ability-hint">' .. icon_img(def.file) | ||
.. '<span class="ability-hint-tip">' .. def. | .. '<span class="ability-hint-tip">' .. dictionary.translate(def.label_dict_key) .. '</span></span>' | ||
end | end | ||
local function manual_icon(m) | local function manual_icon(m) | ||
local cls = 'ability-hint' | local cls = 'ability-hint' | ||
local | local dict_key = STATE_DICT_KEYS.normal | ||
local partial = false | local partial = false | ||
if m.state == 'disabled' then | if m.state == 'disabled' then | ||
cls = cls .. ' ability-hint--disabled' | cls = cls .. ' ability-hint--disabled' | ||
dict_key = STATE_DICT_KEYS.disabled | |||
elseif m.state == 'partial' then | elseif m.state == 'partial' then | ||
dict_key = STATE_DICT_KEYS.partial | |||
partial = true | partial = true | ||
elseif m.state == 'enhanced' then | |||
cls = cls .. ' ability-hint--enhanced' | |||
end | end | ||
local tip = dictionary.translate(dict_key, nil, nil, { m.title }) | |||
.. '<br>' .. dictionary.translate('AbilityHintsClickReveal') | |||
return '<span class="' .. cls .. '">' .. icon_img(m.file, '#' .. m.anchor, partial) | return '<span class="' .. cls .. '">' .. icon_img(m.file, '#' .. m.anchor, partial) | ||
.. '<span class="ability-hint-tip">' .. | .. '<span class="ability-hint-tip">' .. tip .. '</span></span>' | ||
end | end | ||
| Line 57: | Line 101: | ||
manual = manual or {} | manual = manual or {} | ||
local manual_by_file = {} | local manual_by_file = {} | ||
for _, m in ipairs(manual) do | for _, m in ipairs(manual) do | ||
| Line 63: | Line 106: | ||
end | end | ||
local | local entries = {} | ||
local placed = {} | local placed = {} | ||
local num = tonumber(ability_num) | |||
for _, def in ipairs(CONFIG) do | |||
if AbilityTable.is_member(def.list, ability_key, num) then | |||
local key = mw.ustring.lower(def.file) | |||
local m = manual_by_file[key] | |||
if m ~= nil then | |||
table.insert(entries, { file = m.file, html = manual_icon(m) }) | |||
placed[key] = true | |||
else | |||
table.insert(entries, { file = def.file, html = hint_icon(def) }) | |||
end | end | ||
end | end | ||
end | end | ||
for _, m in ipairs(manual) do | for _, m in ipairs(manual) do | ||
if not placed[mw.ustring.lower(m.file)] then | if not placed[mw.ustring.lower(m.file)] then | ||
table.insert( | table.insert(entries, { file = m.file, html = manual_icon(m) }) | ||
end | end | ||
end | end | ||
if # | if #entries == 0 then return '' end | ||
for _, e in ipairs(entries) do e.sort = sort_key(e.file) end | |||
table.sort(entries, compare) | |||
local icons = {} | |||
for _, e in ipairs(entries) do table.insert(icons, e.html) end | |||
return '<div class="ability-section-hints">' .. table.concat(icons) .. '</div>' | return '<div class="ability-section-hints">' .. table.concat(icons) .. '</div>' | ||
end | end | ||
return p | return p | ||