Module:HeroSubClassData: Difference between revisions

From Heroes of Might and Magic: Olden Era Official Wiki
Undo revision 20721 by 76561198256426587 (talk)
Tag: Undo
No edit summary
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
local p = {}
local p = {}


-- Table de correspondance inversée (faction_classe) pour coller à la table HeroSpecialization
-- Table de correspondance pour traduire le nom de la classe en "faction_type"
local class_mapping = {
local class_to_faction_type = {
     ["herald"]      = "demon_magic",
     ["herald"]      = "demon_magic",
     ["warlock"]    = "dungeon_magic",
     ["warlock"]    = "dungeon_magic",
Line 17: Line 17:
}
}


-- Fonction interne pour traduire le nom usuel en identifiant Cargo valide
-- Fonction interne pour convertir l'argument en ID Cargo de sous-classe valide
local function get_cargo_spec_id(input_id)
local function get_cargo_subclass_id(input_id)
     if not input_id then return "" end
     if not input_id then return "" end
      
      
     -- On nettoie les espaces inutiles et on passe tout en minuscules
     -- On nettoie les espaces et on passe tout en minuscules
     local clean_id = mw.text.trim(string.lower(input_id))
     local clean_id = mw.text.trim(string.lower(input_id))
      
      
     -- Si le nom est dans notre dictionnaire, on renvoie l'ID Cargo, sinon on garde l'original
     -- Si l'ID commence déjà par "sub_class_", on n'y touche pas
     return class_mapping[clean_id] or clean_id
     if string.sub(clean_id, 1, 10) == "sub_class_" then
end
        return clean_id
 
    end
-- Fonction locale pour mettre la première lettre de chaque mot en majuscule
   
-- Gère les mots séparés par des espaces ou des underscores (_)
    -- On cherche à capturer le nom de la classe et le numéro (ex: "knight_2" ou "death knight_1")
local function capitalize(str)
     -- Le motif cherche tout jusqu'au dernier underscore suivi d'un chiffre
    if not str then return "" end
     local class_name, number = string.match(clean_id, "^(.+)_(%d+)$")
     -- Remplace la première lettre de chaque mot par sa version majuscule
   
     local capitalized = str:gsub("(%a)([%w]*)", function(first, rest)
    if class_name and number then
         return first:upper() .. rest:lower()
        -- On nettoie le nom de la classe extrait au cas où
     end)
        class_name = mw.text.trim(class_name)
     return capitalized
       
        -- Si la classe existe dans notre dictionnaire, on assemble le nouvel ID
         if class_to_faction_type[class_name] then
            return "sub_class_" .. class_to_faction_type[class_name] .. "_" .. number
        end
     end
   
    -- Si le format ne correspondait pas ou que la classe est inconnue, on renvoie l'original
     return clean_id
end
end


-- Fonction principale pour récupérer une donnée de spécialisation
-- Fonction principale pour récupérer les données d'une sous-classe
-- Syntaxe : {{#invoke:HeroSpecializationData|get|ID_SPECIALISATION|CHAMP|LANGUE}}
-- Syntaxe : {{#invoke:HeroSubClassData|get|ID_SOUS_CLASSE|CHAMP|LANGUE}}
function p.get(frame)
function p.get(frame)
     local args = frame.args[1] and frame.args or frame:getParent().args
     local args = frame.args[1] and frame.args or frame:getParent().args
      
      
     -- Conversion automatique du nom de classe saisi vers le format faction_classe
     -- Conversion automatique de "classe_numero" en "sub_class_faction_type_numero"
     local spec_id = get_cargo_spec_id(args[1])
     local subclass_id = get_cargo_subclass_id(args[1])
     local field = args[2]
     local field = args[2]
     local lang = args[3] or 'en' -- Anglais par défaut
     local lang = args[3] or 'fr' -- Par défaut en français


     if spec_id == "" or not field then
     if subclass_id == "" or not field then
         return "Erreur : ID de spécialisation ou champ manquant."
         return "Erreur : ID de sous-classe ou champ manquant."
     end
     end


     -- 1. Gestion des champs textuels traduits (name, description)
     -- 1. GESTION DES DONNÉES TRADUITES (Ajusté sur "hero_sub_class")
     if field == 'name' or field == 'description' then
     if field == 'name' or field == 'description' then
         local queryOpts = {
         local queryOpts = {
             where = string.format('target_id="%s" AND language="%s" AND type="hero_specialization"', spec_id, lang)
             where = string.format('target_id="%s" AND language="%s" AND type="hero_sub_class"', subclass_id, lang)
         }
         }
       
         local res = mw.ext.cargo.query('Translation', field, queryOpts)
         local res = mw.ext.cargo.query('Translation', field, queryOpts)


Line 64: Line 71:
             return res[1][field]
             return res[1][field]
         else
         else
             -- Système de secours (fallback) vers l'anglais
             -- Système de fallback (secours) vers le français ou l'anglais
            if lang ~= 'fr' then
                local fallbackFr = mw.ext.cargo.query('Translation', field, {where = string.format('target_id="%s" AND language="fr" AND type="hero_sub_class"', subclass_id)})
                if fallbackFr and fallbackFr[1] and fallbackFr[1][field] then return fallbackFr[1][field] end
            end
             if lang ~= 'en' then
             if lang ~= 'en' then
                 local fallbackOpts = {
                 local fallbackEn = mw.ext.cargo.query('Translation', field, {where = string.format('where target_id="%s" AND language="en" AND type="hero_sub_class"', subclass_id)})
                    where = string.format('target_id="%s" AND language="en" AND type="hero_specialization"', spec_id)
                 if fallbackEn and fallbackEn[1] and fallbackEn[1][field] then return fallbackEn[1][field] end
                }
                local fallbackRes = mw.ext.cargo.query('Translation', field, fallbackOpts)
                 if fallbackRes and fallbackRes[1] and fallbackRes[1][field] then
                    return fallbackRes[1][field]
                end
             end
             end
             return ""  
             return ""
         end
         end
     end
     end


     -- 2. Gestion des données brutes de la table "HeroSpecialization"
     -- 2. GESTION DES PROPRIÉTÉS STRUCTURELLES
     local specOpts = {
     local queryOpts = {
         where = string.format('id="%s"', spec_id)
         where = string.format('id="%s"', subclass_id)
     }
     }
     local specRes = mw.ext.cargo.query('HeroSpecialization', field, specOpts)
     local res = mw.ext.cargo.query('HeroSubClass', field, queryOpts)


     if specRes and specRes[1] and specRes[1][field] then
     if res and res[1] and res[1][field] then
         local value = specRes[1][field]
         return res[1][field]
       
        -- SI le champ demandé est l'icône, on applique la transformation des majuscules
        if field == 'icon' then
            return capitalize(value)
        end
       
        return value
     end
     end



Latest revision as of 19:57, 28 May 2026

Template:Documentation This module provides standardized methods to query mechanical data configurations, activation skill prerequisites, and localized texts mapped to specific hero mastery subclasses directly from the Cargo database tables (specifically HeroSubClass and Translation).

Basic Syntax

To extract any structural variable node or translation block from a hero subclass registry page:

{{#invoke:HeroSubClassData|get|SUBCLASS_ID|VARIABLE|LANGUAGE_CODE}}
  • SUBCLASS_ID : The technical internal database key identifier assigned to the targeted hero subclass row (e.g., sub_class_human_might_1).
  • VARIABLE : The specific data field node target identifier to look up (see reference matrix below).
  • LANGUAGE_CODE : (Optional) Sets the localization system language. Defaults to French (fr) if omitted, with automated fallbacks.

---

Technical Reference Index

📝 Localized Text Blocks (Language-Aware)

Queries localized dictionary assets that translate dynamically based on the language parameter input.

Variable Keyword Description Sample Expected Output
name The localized public name of the specialty subclass. Bretteur
description Mechanical lore synopses detailing passive thresholds or stats adjustments. Coup héroïque inflige +60 point(s)...

⚙️ Structural & Mechanical Properties

Static code variables returning gameplay rows directly mapped parameters tied into the core game database.

Variable Keyword Description Sample Output
faction The alignment technical name faction group linked to the subclass. human
class_type Archetypal class methodology branch style. might
icon Graphical asset emblem visual token key identifier. sub_class_human_might_1_icon
source_path Server file system dump localization repository tree tracker. DB/heroes_sub_classes/sub_classes_human.json

⚔️ Required Activation Skills

Prerequisites requirements parameters checking skills conditions to validate the subclass unlock state.

Variable Keyword Description Variable Keyword Description
activation_skill_1_sid Internal ID of required Skill 1 activation_skill_1_level Required level threshold for Skill 1
activation_skill_2_sid Internal ID of required Skill 2 activation_skill_2_level Required level threshold for Skill 2
activation_skill_3_sid Internal ID of required Skill 3 activation_skill_3_level Required level threshold for Skill 3
activation_skill_4_sid Internal ID of required Skill 4 activation_skill_4_level Required level threshold for Skill 4
activation_skill_5_sid Internal ID of required Skill 5 activation_skill_5_level Required level threshold for Skill 5

---

Practical Implementation Examples

Example 1: Creating a Prerequisites Checklist

Pull structural required requirements to display dynamic conditional lists on wiki pages:

To become a {{#invoke:HeroSubClassData|get|sub_class_human_might_1|name|en}}, you need:
* {{#invoke:HeroSubClassData|get|sub_class_human_might_1|activation_skill_1_sid}} at Level {{#invoke:HeroSubClassData|get|sub_class_human_might_1|activation_skill_1_level}}
* {{#invoke:HeroSubClassData|get|sub_class_human_might_1|activation_skill_2_sid}} at Level {{#invoke:HeroSubClassData|get|sub_class_human_might_1|activation_skill_2_level}}

local p = {}

-- Table de correspondance pour traduire le nom de la classe en "faction_type"
local class_to_faction_type = {
    ["herald"]      = "demon_magic",
    ["warlock"]     = "dungeon_magic",
    ["cleric"]      = "human_magic",
    ["druid"]       = "nature_magic",
    ["necromancer"] = "undead_magic",
    ["riftspeaker"] = "unfrozen_magic",
    ["enforcer"]    = "demon_might",
    ["overlord"]    = "dungeon_might",
    ["knight"]      = "human_might",
    ["warden"]      = "nature_might",
    ["death knight"]= "undead_might",
    ["oathkeeper"]  = "unfrozen_might"
}

-- Fonction interne pour convertir l'argument en ID Cargo de sous-classe valide
local function get_cargo_subclass_id(input_id)
    if not input_id then return "" end
    
    -- On nettoie les espaces et on passe tout en minuscules
    local clean_id = mw.text.trim(string.lower(input_id))
    
    -- Si l'ID commence déjà par "sub_class_", on n'y touche pas
    if string.sub(clean_id, 1, 10) == "sub_class_" then
        return clean_id
    end
    
    -- On cherche à capturer le nom de la classe et le numéro (ex: "knight_2" ou "death knight_1")
    -- Le motif cherche tout jusqu'au dernier underscore suivi d'un chiffre
    local class_name, number = string.match(clean_id, "^(.+)_(%d+)$")
    
    if class_name and number then
        -- On nettoie le nom de la classe extrait au cas où
        class_name = mw.text.trim(class_name)
        
        -- Si la classe existe dans notre dictionnaire, on assemble le nouvel ID
        if class_to_faction_type[class_name] then
            return "sub_class_" .. class_to_faction_type[class_name] .. "_" .. number
        end
    end
    
    -- Si le format ne correspondait pas ou que la classe est inconnue, on renvoie l'original
    return clean_id
end

-- Fonction principale pour récupérer les données d'une sous-classe
-- Syntaxe : {{#invoke:HeroSubClassData|get|ID_SOUS_CLASSE|CHAMP|LANGUE}}
function p.get(frame)
    local args = frame.args[1] and frame.args or frame:getParent().args
    
    -- Conversion automatique de "classe_numero" en "sub_class_faction_type_numero"
    local subclass_id = get_cargo_subclass_id(args[1])
    local field = args[2]
    local lang = args[3] or 'fr' -- Par défaut en français

    if subclass_id == "" or not field then
        return "Erreur : ID de sous-classe ou champ manquant."
    end

    -- 1. GESTION DES DONNÉES TRADUITES (Ajusté sur "hero_sub_class")
    if field == 'name' or field == 'description' then
        local queryOpts = {
            where = string.format('target_id="%s" AND language="%s" AND type="hero_sub_class"', subclass_id, lang)
        }
        local res = mw.ext.cargo.query('Translation', field, queryOpts)

        if res and res[1] and res[1][field] then
            return res[1][field]
        else
            -- Système de fallback (secours) vers le français ou l'anglais
            if lang ~= 'fr' then
                local fallbackFr = mw.ext.cargo.query('Translation', field, {where = string.format('target_id="%s" AND language="fr" AND type="hero_sub_class"', subclass_id)})
                if fallbackFr and fallbackFr[1] and fallbackFr[1][field] then return fallbackFr[1][field] end
            end
            if lang ~= 'en' then
                local fallbackEn = mw.ext.cargo.query('Translation', field, {where = string.format('where target_id="%s" AND language="en" AND type="hero_sub_class"', subclass_id)})
                if fallbackEn and fallbackEn[1] and fallbackEn[1][field] then return fallbackEn[1][field] end
            end
            return ""
        end
    end

    -- 2. GESTION DES PROPRIÉTÉS STRUCTURELLES
    local queryOpts = {
        where = string.format('id="%s"', subclass_id)
    }
    local res = mw.ext.cargo.query('HeroSubClass', field, queryOpts)

    if res and res[1] and res[1][field] then
        return res[1][field]
    end

    return ""
end

return p