Module:SkillArtifacts

From Heroes of Might and Magic: Olden Era Official Wiki
Revision as of 14:48, 28 June 2026 by Aurelain (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This module lists the artifacts that mention a specific skill. Additionally, it applies hyperlinks to words that exactly match skill names.

Usage

1. English:

Input: {{#invoke:SkillArtifacts|display | lang=en | skill=skill_diplomacy}}

Output:

Holy Sigil of Insara  — Epic Relic
While worn, grants all unlearned Subskills of the following Skills: Leadership, Insight, Diplomacy, Tactics.
Diplomatic Gifts  — Legendary Item
+10% to Persuasion Power in Diplomacy.
Ambassador's Sash  — Legendary Back
+10% to Persuasion Power in Diplomacy.

2. Japanese:

Input: {{#invoke:SkillArtifacts|display | lang=ja | skill=skill_diplomacy}}

Output:

大使の懸章  — Legendary Back
外交における説得力が10%増加する。
外交の贈り物  — Legendary Item
外交における説得力が10%増加する。
インサラの聖印  — Epic Relic
装備中、以下のスキルの未習得サブスキルをすべて得る:〈統率〉、〈洞察〉、〈外交〉、〈戦術〉。

-- Usage: {{#invoke:SkillArtifacts|display|lang=en|skill=skill_assault}}
local p = {}
local f = mw.ustring.format
local SkillsOverview = require("Module:SkillsOverview")
local PATCH_NAME = {
    ['Summon Avatar'] = 'Summon Avatar (Skill)',
}
-- The following are exceptions caused by collision between the Skill name and Attribute name in English:
local SPECIAL_PATTERNS = {
    Defense = 'Skills.-Defense',
    Luck = 'Skills.-Luck'
}

------------------------------------------------------------------------------------------------------------------------
-- Debugs a variable
------------------------------------------------------------------------------------------------------------------------
local function dump(target)
    return '<pre>' .. mw.dumpObject(target) .. '</pre>'
end

------------------------------------------------------------------------------------------------------------------------
-- Spawns a safe robotic url from an English name, fit for adding it before the visible name
------------------------------------------------------------------------------------------------------------------------
local function getUrl(nameEn, lang)
    local url = PATCH_NAME[nameEn] or nameEn
    if lang ~= 'en' then
        url = url .. '/' .. lang
    end
    return url
end

------------------------------------------------------------------------------------------------------------------------
--
------------------------------------------------------------------------------------------------------------------------
local function queryArtifacts(lang)
    -- fields:
    local fields = {}
    table.insert(fields, 'Artifact.id = id');
    table.insert(fields, 'Artifact.icon = icon');
    table.insert(fields, 'Translation.name = name');
    table.insert(fields, 'Translation.description = description');
    table.insert(fields, 'Translation.language = language');

    -- where:
    local where = {}
    table.insert(where, '(Translation.language = "en" OR Translation.language = "' .. lang .. '")')

    -- query:
    return mw.ext.cargo.query('Artifact, Translation', table.concat(fields, ','), {
        join = 'Artifact.id = Translation.target_id',
        where = table.concat(where, ' AND '),
        limit = 1000
    })
end

------------------------------------------------------------------------------------------------------------------------
-- Folds all artifact results from Cargo into a compacted table
------------------------------------------------------------------------------------------------------------------------
local function consolidateArtifacts(artifactsResult, lang)
    local hub = {}
    for _, row in ipairs(artifactsResult) do
        local id = row.id
        hub[id] = hub[id] or { id = id }
        local entry = hub[id]
        if row.language == lang then
            entry.name = row.name or ''
            entry.description = row.description or ''
            entry.icon = row.icon or ''
        end
        if row.language == 'en' then
            entry.descriptionEn = row.description or ''
        end
    end
    return hub
end

------------------------------------------------------------------------------------------------------------------------
--
------------------------------------------------------------------------------------------------------------------------
local function linkifyDescription(description, skillsHub, lang)
    for _, group in pairs(skillsHub) do
        local url = getUrl(group.nameEn, lang)
        description = mw.ustring.gsub(description, '(' .. group.name .. ')', '[[' .. url .. '|' .. '%1]]')
    end
    return description
end

------------------------------------------------------------------------------------------------------------------------
--
------------------------------------------------------------------------------------------------------------------------
local function highlightCurrentSkill(description, name)
    local spanMarkup = '<span style="color:peru">' .. name .. '</span>'
    description = mw.ustring.gsub(description, '%[%[[^%]]*' .. name .. '%]%]', spanMarkup)
    return description
end

------------------------------------------------------------------------------------------------------------------------
--
------------------------------------------------------------------------------------------------------------------------
local function findRelatedArtifacts(artifacts, pattern, skillName, skillsHub, lang)
    local related = {}
    for id, artifact in pairs(artifacts) do
        if artifact.descriptionEn:match(pattern) then
            -- We found an artifact that mentions our target skill by name
            local description = linkifyDescription(artifact.description, skillsHub, lang)
            -- Note: We cannot highlight the current skill because we're passing the description to ArtifactSummary
            --description = highlightCurrentSkill(description, skillName)
            table.insert(related, {
                id = id,
                name = artifact.name,
                description = description,
                icon = artifact.icon,
            })
        end
    end
    return related
end

------------------------------------------------------------------------------------------------------------------------
--
------------------------------------------------------------------------------------------------------------------------
local function renderArtifacts(artifacts, lang, frame)
    local list = {}
    for _, artifact in ipairs(artifacts) do
        local formatted = f(
            '{{ArtifactSummary | lang=%s | id=%s | description=%s}}',
            lang,
            artifact.id,
            artifact.description
        );
        table.insert(list, frame:preprocess(formatted))
    end
    return table.concat(list)
end

------------------------------------------------------------------------------------------------------------------------
-- Main public function
------------------------------------------------------------------------------------------------------------------------
function p.display(frame)
    --if 1 then return dump(frame) end

    -- Args
    local args = frame.args
    local lang = args.lang or 'en'
    local skillId = args.skill or ''
    if skillId == '' then return 'You must provide a skill id!' end
    --lang = 'en'
    --skillId = 'skill_diplomacy'

    -- Cargo
    local skillsHub = SkillsOverview.getSkillsFromCargo(lang)
    local skill = skillsHub[skillId]
    if not skill then return 'Cannot resolve skill!' end
    local artifactsResult = queryArtifacts(lang)
    local artifactsHub = consolidateArtifacts(artifactsResult, lang)

    -- Main computation
    local pattern = SPECIAL_PATTERNS[skill.nameEn] or skill.nameEn
    local artifacts = findRelatedArtifacts(artifactsHub, pattern, skill.name, skillsHub, lang)
    --if 1 then return dump(artifacts) end
    if #artifacts == 0 then return "''No results''" end

    -- Output
    local markup = renderArtifacts(artifacts, lang, frame)
    return markup
end

return p