Module:Unit

From Heroes of Might and Magic: Olden Era Official Wiki
Revision as of 19:03, 9 December 2025 by Krom (talk | contribs)

Module for requesting characteristics of all existing units in Olden Era. Actual data is stored in Data:units.json.

For documentation page, see Module:Unit/doc.

Supported Commands

get

The module supports the main get command, through which you can retrieve individual unit attributes (listed below). The basic syntax of the command is:

{{#invoke:Unit|get|Unit Name|Property Name}}
Name Description Example Result
name Unit name (localized)
{{#invoke:Unit|get|Angel|name}}
Angel
Base name Name of un-upgraded unit (localized)
{{#invoke:Unit|get|Apotheosis|baseName}}
Property 'baseName' not found for unit 'Apotheosis'
First Upgrade Name of upgraded unit (localized)
{{#invoke:Unit|get|Angel|upgradeName}}
Property 'upgradeName' not found for unit 'Angel'
Second Upgrade Name of alt. upgraded unit (localized)
{{#invoke:Unit|get|Angel|altUpgradeName}}
Property 'altUpgradeName' not found for unit 'Angel'
Image name Name without spaces and apostrophes, suitable for wiki file names
{{#invoke:Unit|get|Sun's Aegis|imageName}}
Property 'imageName' not found for unit 'Sun's Aegis'
description Narrative description (localized with data substitutions)
{{#invoke:Unit|get|Angel|description}}
Property 'description' not found for unit 'Angel'
faction Unit faction
{{#invoke:Unit|get|Angel|faction}}
human
tier Unit tier
{{#invoke:Unit|get|Angel|tier}}
7
id Unit ID
{{#invoke:Unit|get|Angel|id}}
angel
nativeBiome Native biome
{{#invoke:Unit|get|Angel|nativeBiome}}
Grass
cost Hiring cost
{{#invoke:Unit|get|Angel|cost}}
Property 'cost' not found for unit 'Angel'
cost.gold
cost.resource
Access to specific property in unitCost object
{{#invoke:Unit|get|Angel|cost.gold}}
{{#invoke:Unit|get|Angel|cost.gemstones}}
Property 'cost.gold' not found for unit 'Angel'
Property 'cost.gemstones' not found for unit 'Angel'
upgradeCost Upgrade cost
{{#invoke:Unit|get|Archangel|upgradeCost}}
Property 'upgradeCost' not found for unit 'Archangel'
weeklyIncrement Base weekly increment from main building
{{#invoke:Unit|get|Angel|weeklyIncrement}}
1
expBonus Experience gained when defeating the unit
{{#invoke:Unit|get|Angel|expBonus}}
366
squadValue Squad value of the unit (used for army composition calculations)
{{#invoke:Unit|get|Angel|squadValue}}
3660
hp Maximum health
{{#invoke:Unit|get|Angel|hp}}
225
offence Offence parameter
{{#invoke:Unit|get|Angel|offence}}
30
defence Defence parameter
{{#invoke:Unit|get|Angel|defence}}
30
damageMin Minimum damage dealt
{{#invoke:Unit|get|Angel|damageMin}}
50
damageMax Maximum damage dealt
{{#invoke:Unit|get|Angel|damageMax}}
75
moral Default morale
{{#invoke:Unit|get|Angel|moral}}
0
moralMin Minimum morale value
{{#invoke:Unit|get|Angel|moralMin}}
-3
moralMax Maximum morale value
{{#invoke:Unit|get|Angel|moralMax}}
3
luck Default luck
{{#invoke:Unit|get|Angel|luck}}
0
luckMin Minimum luck value
{{#invoke:Unit|get|Angel|luckMin}}
-3
luckMax Maximum luck value
{{#invoke:Unit|get|Angel|luckMax}}
3
initiative Initiative
{{#invoke:Unit|get|Angel|initiative}}
8
speed Speed
{{#invoke:Unit|get|Angel|speed}}
4
moveType Movement type (fly or teleport)
{{#invoke:Unit|get|Angel|moveType}}
fly
baseClass.name Base class name (localized)
{{#invoke:Unit|get|Angel|baseClass.name|ru}}
Property 'baseClass.name' not found for unit 'Angel'
baseClass.description Base class description (localized)
{{#invoke:Unit|get|Angel|baseClass.description}}
Property 'baseClass.description' not found for unit 'Angel'
baseClass.icon Base class icon filename
{{#invoke:Unit|get|Angel|baseClass.icon}} or [[File:{{#invoke:Unit|get|Angel|baseClass.icon}}|50px]]
Property 'baseClass.icon' not found for unit 'Angel' - File:Property 'baseClass.icon' not found for unit 'Angel'

Active Abilities

To access specific active ability properties, use the format: abilities.index.property

Name Description Example Result
abilities.1.name Ability name (localized)
{{#invoke:Unit|get|Flaming Phoenix|abilities.1.name|ru}}
Пробуждение. Огонь II
abilities.1.description Ability main description (localized with data substitutions)
{{#invoke:Unit|get|Flaming Phoenix|abilities.1.description|ru}}
Property 'description' not found in abilities[1] for unit 'Flaming Phoenix'
abilities.1.infoDescription Additional ability information (localized)
{{#invoke:Unit|get|Flaming Phoenix|abilities.1.infoDescription|ru}}
ability_no_turn
abilities.1.excaptionInTooltip Ability restrictions or exceptions (localized)
{{#invoke:Unit|get|Cultist|abilities.1.excaptionInTooltip|ru}}
description_effect_magic_creature_undead_construct_immunities
abilities.1.abilityType Type of ability (localized)
{{#invoke:Unit|get|Flaming Phoenix|abilities.1.abilityType|ru}}
Ability_type_special
abilities.1.ability_tier Ability rank or tier
{{#invoke:Unit|get|Flaming Phoenix|abilities.1.ability_tier|ru}}
6
abilities.1.energyLevel Energy required for ability activation
{{#invoke:Unit|get|Flaming Phoenix|abilities.1.energyLevel|ru}}
3
abilities.1.icon Ability icon filename
{{#invoke:Unit|get|Flaming Phoenix|abilities.1.icon|ru}}
Phoenix_ability_2.png

Passive Abilities

To access specific passive ability properties, use the format: passives.index.property

Name Description Example Result
passives.1.name Passive ability name (localized)
{{#invoke:Unit|get|Giant Toad|passives.1.name}}
Melee Attack
passives.1.description Passive ability description (localized with data substitutions)
{{#invoke:Unit|get|Giant Toad|passives.1.description}}
Property 'description' not found in passives[1] for unit 'Giant Toad'
passives.1.excaptionInTooltip Passive ability restrictions or exceptions (localized)
{{#invoke:Unit|get|Giant Toad|passives.1.excaptionInTooltip}}
Property 'excaptionInTooltip' not found in passives[1] for unit 'Giant Toad'
passives.1.icon Passive ability icon filename
{{#invoke:Unit|get|Giant Toad|passives.1.icon}}
Base passive melee attack.png

Alternative Attacks

To access specific alternative attack properties, use the format: alternativeAttacks.index.property

Name Description Example Result
alternativeAttacks.1.name Alternative attack name (localized)
{{#invoke:Unit|get|Infiltrator|alternativeAttacks.1.name}}
Fighting Style: Hit and Run
alternativeAttacks.1.description Alternative attack description (localized with data substitutions)
{{#invoke:Unit|get|Infiltrator|alternativeAttacks.1.description}}
Property 'description' not found in alternativeAttacks[1] for unit 'Infiltrator'
alternativeAttacks.1.abilityType Type of alternative attack (localized)
{{#invoke:Unit|get|Infiltrator|alternativeAttacks.1.abilityType}}
Ability_type_attack_alt
alternativeAttacks.1.infoDescription Additional alternative attack information (localized)
{{#invoke:Unit|get|Infiltrator|alternativeAttacks.1.infoDescription}}
ability_no_energy
alternativeAttacks.1.icon Alternative attack icon filename
{{#invoke:Unit|get|Infiltrator|alternativeAttacks.1.icon}}
Assassin_ability_1.png
alternativeAttacks.1.ability_tier Alternative attack rank or tier
{{#invoke:Unit|get|Infiltrator|alternativeAttacks.1.ability_tier}}
1

Localization Support

The module supports localization in multiple languages. You can specify the language as an optional third parameter:

{{#invoke:Unit|get|Unit Name|Property Name|Language Code}}

For example:

  • {{#invoke:Unit|get|Angel|name|pl}}
    Anioł - Polish
  • {{#invoke:Unit|get|Angel|name|ru}}
    Ангел - Russian

local Unit = {}

-- Cache for data
local dataCache = nil

-- Load localization module
local LangStrings = require("Module:LocGetString")

-- Function to load JSON data from wiki page
local function loadJson(title)
    local page = mw.title.new(title)
    local content = page and page:getContent() or ""
    if content == "" then return {} end
    local ok, data = pcall(mw.text.jsonDecode, content)
    if not ok then return {} end
    return data
end

-- Load unit data from unitdata_work.json
local function loadUnits()
    if dataCache then return dataCache end
    dataCache = {}

    -- Load main JSON file (in real wiki, JSON data needs to be placed on this page)
    local units = loadJson("Data:units.json") -- or another suitable name for wiki page

    -- Copy data to cache
    for name, unit in pairs(units) do
        dataCache[name] = unit
    end

    return dataCache
end

-- Function to get localized text
local function getLocalizedText(sid, lang)
    if sid and sid ~= "" then
        return LangStrings.getText({args = {sid = sid, lang = lang}})
    else
        return sid  -- Return the original value if no sid
    end
end

-- Function to get unit name using localization
local function getUnitName(unit, lang)
    local id = unit.id or ""
    if id ~= "" then
        return getLocalizedText(id .. "_name", lang)
    else
        return unit.name or "No name"
    end
end

-- Function to get unit property
function Unit.get(frame)
    local args = frame.args
    local unitName = args[1] or args.unit or ""
    local property = args[2] or args.property or ""
    local lang = args[3] or args.lang or "en"  -- Get language parameter, default to 'en'

    unitName = mw.text.trim(unitName or "")
    property = mw.text.trim(property or "")
    lang = mw.text.trim(lang or "en")

    if unitName == "" then
        return "Unit name not specified"
    end

    if property == "" then
        return "Property not specified"
    end

    -- Load unit data
    local units = loadUnits()

    -- Check if unit exists in data
    local unit = units[unitName]
    if not unit then
        return "Unit '" .. unitName .. "' not found"
    end

    -- If property is 'name', return localized name
    if property == "name" then
        return getUnitName(unit, lang)
    end

    -- Check if property is in format "arrayName.index.propertyName" (for accessing arrays)
    local arrayAccess = string.match(property, "^(.+)%.(%d+)%.(.+)$")
    if arrayAccess then
        local arrayName, indexStr, propName = string.match(property, "^(.+)%.(%d+)%.(.+)$")
        local index = tonumber(indexStr)
        if arrayName and index and propName then
            -- Convert from 1-based indexing (user-friendly) to 0-based indexing (JSON format)
            local actualIndex = index - 1
            local array = unit[arrayName]

            -- Check if the array exists and is a table
            if array == nil then
                return "Array '" .. arrayName .. "' not found for unit '" .. unitName .. "'"
            end

            if type(array) ~= "table" then
                return "Property '" .. arrayName .. "' is not an array for unit '" .. unitName .. "'"
            end

            local element = array[actualIndex]

            -- If element is not found at the converted index, it might mean that the array uses 1-based indexing
            -- This can happen depending on how the JSON was parsed
            if element == nil then
                -- Try with 1-based indexing (standard Lua arrays)
                element = array[index]
                if element ~= nil then
                    -- Use 1-based indexing, so we don't subtract 1
                    actualIndex = index
                end
            end

            -- Now check if we found an element
            if element ~= nil and type(element) == "table" then
                local value = element[propName]
                if value ~= nil then
                    -- If this property has localization (for example, name fields), return localized version
                    if propName == "name" and element["sid_name"] then
                        return getLocalizedText(element["sid_name"], lang)
                    else
                        return tostring(value)
                    end
                else
                    return "Property '" .. propName .. "' not found in " .. arrayName .. "[" .. actualIndex .. "] for unit '" .. unitName .. "'"
                end
            else
                return "Array '" .. arrayName .. "' does not contain index " .. actualIndex .. " for unit '" .. unitName .. "' (requested as " .. index .. " for user-friendly indexing)"
            end
        end
    end

    -- First check if property exists in main unit object
    if unit[property] ~= nil then
        return tostring(unit[property])
    end

    -- Then check if property exists in stats
    if unit.stats and unit.stats[property] ~= nil then
        return tostring(unit.stats[property])
    end

    -- If property not found
    return "Property '" .. property .. "' not found for unit '" .. unitName .. "'"
end

return Unit