Module:UnitInfobox: Difference between revisions

From Heroes of Might and Magic: Olden Era Official Wiki
No edit summary
No edit summary
Line 92: Line 92:
         return ''
         return ''
     end
     end
     local dwellingResults = runQuery([[
     local success, result = pcall(function()
        tables =
        return runQuery([[
            MapObject = M
            tables =
        | where =
                MapObject = M
            M.id = '%s'
            | where =
        | fields =
                M.id = '%s'
            M.units_weekly = units_weekly
            | fields =
        | limit =
                M.units_weekly = units_weekly
            1
            | limit =
    ]], dwelling);
                1
     growth = (dwellingResults[1] or { units_weekly = '' }).units_weekly
        ]], dwelling);
     end)
    if success then
        growth = (result[1] or { units_weekly = '' }).units_weekly
    end
     return growth
     return growth
end
end

Revision as of 16:14, 16 July 2026

Documentation for this module may be created at Module:UnitInfobox/doc

-- This module is intended as a supporting muscle for the UnitInfobox template.
local p = {}

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

-- Parses and runs a Cargo query from wiki-like syntax
------------------------------------------------------------------------------------------------------------------------
local function runQuery(query, ...)
    query = string.gsub(query, "%-%-.-\n", "") -- remove "comments"
    query = select('#', ...) > 0 and mw.ustring.format(query, ...) or query
    query = mw.text.trim(query)
    local tables = ''
    local fields = ''
    local options = {}
    for part in query:gmatch('[^|]+') do
        local key, val = part:match('^%s*([^=]+)%s*=%s*(.-)%s*$')
        if key and val then
            key = mw.text.trim(key):lower()
            val = mw.text.trim(val)
            val = val:gsub('%s', ' ')
            if key == 'tables' then
                tables = val
            elseif key == 'fields' then
                fields = val
            elseif key == 'limit' then
                options[key] = tonumber(val) or val
            elseif key == 'join on' then
                options['join'] = val
            else
                options[key] = val
            end
        end
    end
    return mw.ext.cargo.query(tables, fields, options)
end

------------------------------------------------------------------------------------------------------------------------
local function getBaseId(unitId)
    return unitId:gsub('_alt$', ''):gsub('_upg$', '')
end

------------------------------------------------------------------------------------------------------------------------
local function getEnglishBaseUnitName(unitId)
    local baseId = getBaseId(unitId)
    local table = runQuery([[
        tables =
            Unit = U,
            Translation = T
        | join on =
            U.id = T.target_id
        | where =
            U.id = '%s'
            AND T.language = 'en'
            AND T.type = 'unit'
        | fields =
            T.name = name
        | limit =
            1
    ]], baseId);
    local row = table[1] or {}
    return row.name
end

------------------------------------------------------------------------------------------------------------------------
function p.findGrowth(frame)
    local unitId = frame.args.id
    local baseId = getBaseId(unitId)
    local table = runQuery([[
        tables =
            Building = B
        | where =
            B.units_hire_sid = '%s'
        | fields =
            B.units_weekly = units_weekly
        | limit =
            1
    ]], baseId);
    local growth = (table[1] or { units_weekly = '' }).units_weekly

    if growth ~= '' then
        return growth
    end

    -- We couldn't find a town building that hires this unit.
    -- Fallback: Attempt to find the growth from external dwellings
    local dwelling = p.findDwelling(frame)
    if dwelling == '' then
        return ''
    end
    local success, result = pcall(function()
        return runQuery([[
            tables =
                MapObject = M
            | where =
                M.id = '%s'
            | fields =
                M.units_weekly = units_weekly
            | limit =
                1
        ]], dwelling);
    end)
    if success then
        growth = (result[1] or { units_weekly = '' }).units_weekly
    end
    return growth
end

------------------------------------------------------------------------------------------------------------------------
function p.findBuilding(frame)
    local unitId = frame.args.id
    local baseId = getBaseId(unitId)
    local level = unitId == baseId and 1 or 2

    local table = runQuery([[
        tables =
            Building = B
        | where =
            B.units_hire_sid = '%s'
            AND B.level = %s
        | fields =
            B.id = id
        | limit =
            1
    ]], baseId, level);
    local row = table[1] or {}
    local building = row.id or ''
    return building
end

------------------------------------------------------------------------------------------------------------------------
function p.findDwelling(frame)
    local unitId = frame.args.id
    local nameEn = getEnglishBaseUnitName(unitId)
    nameEn = nameEn:gsub('man$', 'men') -- fix 'Swordmen' and 'Crossbowmen'
    nameEn = nameEn:gsub(' of', 's of') -- fix 'Sentinels of Glory'
    nameEn = nameEn:gsub('Waurms', 'Waurmos')

    -- Note: Currently (2026-07-16), the banks are not present in Cargo
    local isBank = tonumber(frame.args.bank)
    local prefix = isBank == 1 and 'Defeat its guard to obtain' or 'You can recruit'

    local table = runQuery([[
        tables =
            Translation = T
        | where =
            T.type = 'map_object'
            AND T.language = 'en'
            AND T.description LIKE '%s %s%%'
        | fields =
            T.target_id = target_id
        | limit =
            1
    ]], prefix, nameEn);
    local row = table[1] or {}
    local dwelling = row.target_id or ''
    return dwelling
end

------------------------------------------------------------------------------------------------------------------------
function p.findSpecialist(frame)
    local unitId = frame.args.id
    local nameEn = getEnglishBaseUnitName(unitId)
    local table = runQuery([[
        tables =
            Translation = T
        | where =
            T.type = 'hero_specialization'
            AND T.language = 'en'
            AND T.description LIKE '%s growth in your cities increases by%%'
        | fields =
            T.target_id = target_id
        | limit =
            1
    ]], nameEn);
    local row = table[1] or {}
    local specialist = row.target_id or ''
    specialist = specialist:gsub('_specialization', '')
    return specialist
end

return p