<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.hoodedhorse.com/Heroes_of_Might_and_Magic_Olden_Era/index.php?action=history&amp;feed=atom&amp;title=Module%3ASkillChances</id>
	<title>Module:SkillChances - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.hoodedhorse.com/Heroes_of_Might_and_Magic_Olden_Era/index.php?action=history&amp;feed=atom&amp;title=Module%3ASkillChances"/>
	<link rel="alternate" type="text/html" href="https://wiki.hoodedhorse.com/Heroes_of_Might_and_Magic_Olden_Era/index.php?title=Module:SkillChances&amp;action=history"/>
	<updated>2026-10-20T01:52:13Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.5</generator>
	<entry>
		<id>https://wiki.hoodedhorse.com/Heroes_of_Might_and_Magic_Olden_Era/index.php?title=Module:SkillChances&amp;diff=39426&amp;oldid=prev</id>
		<title>76561198048502585: Created page with &quot;-- This module is intended as a supporting muscle for the SkillChances template. local p = {} local UtilQuery = require(&#039;Module:UtilQuery&#039;) local FACTION = {     humans = &#039;human&#039;, -- changed!     necros = &#039;undead&#039;, -- changed!     nature = &#039;nature&#039;,     demons = &#039;demon&#039;, -- changed!     unfrozen = &#039;unfrozen&#039;,     dungeon = &#039;dungeon&#039;, }  -- Displays a variable -----------------------------------------------------------------------------------------------------------------...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.hoodedhorse.com/Heroes_of_Might_and_Magic_Olden_Era/index.php?title=Module:SkillChances&amp;diff=39426&amp;oldid=prev"/>
		<updated>2026-08-27T07:43:26Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;-- This module is intended as a supporting muscle for the SkillChances template. local p = {} local UtilQuery = require(&amp;#039;Module:UtilQuery&amp;#039;) local FACTION = {     humans = &amp;#039;human&amp;#039;, -- changed!     necros = &amp;#039;undead&amp;#039;, -- changed!     nature = &amp;#039;nature&amp;#039;,     demons = &amp;#039;demon&amp;#039;, -- changed!     unfrozen = &amp;#039;unfrozen&amp;#039;,     dungeon = &amp;#039;dungeon&amp;#039;, }  -- Displays a variable -----------------------------------------------------------------------------------------------------------------...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- This module is intended as a supporting muscle for the SkillChances template.&lt;br /&gt;
local p = {}&lt;br /&gt;
local UtilQuery = require(&amp;#039;Module:UtilQuery&amp;#039;)&lt;br /&gt;
local FACTION = {&lt;br /&gt;
    humans = &amp;#039;human&amp;#039;, -- changed!&lt;br /&gt;
    necros = &amp;#039;undead&amp;#039;, -- changed!&lt;br /&gt;
    nature = &amp;#039;nature&amp;#039;,&lt;br /&gt;
    demons = &amp;#039;demon&amp;#039;, -- changed!&lt;br /&gt;
    unfrozen = &amp;#039;unfrozen&amp;#039;,&lt;br /&gt;
    dungeon = &amp;#039;dungeon&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Displays a variable&lt;br /&gt;
------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
local function dump(target)&lt;br /&gt;
    return &amp;#039;&amp;lt;pre&amp;gt;&amp;#039; .. mw.dumpObject(target) .. &amp;#039;&amp;lt;/pre&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
local function collectChances()&lt;br /&gt;
    local result = UtilQuery.run([[&lt;br /&gt;
        tables =&lt;br /&gt;
            SkillRollWeight = S&lt;br /&gt;
        |where =&lt;br /&gt;
            S.table_id NOT LIKE &amp;#039;arenaGame%%&amp;#039;&lt;br /&gt;
        |fields =&lt;br /&gt;
            S.table_id = table_id,&lt;br /&gt;
            S.band_kind = band_kind,&lt;br /&gt;
            S.skill_id = skill_id,&lt;br /&gt;
            S.weight = weight&lt;br /&gt;
        |limit = 1000&lt;br /&gt;
    ]])&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
local function consolidateChances(chancesBulk)&lt;br /&gt;
    local chances = {}&lt;br /&gt;
    for _, row in ipairs(chancesBulk) do&lt;br /&gt;
        local tableId = row.table_id or &amp;#039;&amp;#039;&lt;br /&gt;
        local factionPlural, type = tableId:match(&amp;#039;^([^_]+)_([^_]+)&amp;#039;)&lt;br /&gt;
        local classId = type .. &amp;#039;_&amp;#039; .. FACTION[factionPlural]&lt;br /&gt;
        local entry = chances[classId]&lt;br /&gt;
        if not entry then&lt;br /&gt;
            chances[classId] = {&lt;br /&gt;
                default = {},&lt;br /&gt;
                magic_levels = {},&lt;br /&gt;
                signature_levels = {},&lt;br /&gt;
                level_20_mega = {},&lt;br /&gt;
            }&lt;br /&gt;
            entry = chances[classId]&lt;br /&gt;
        end&lt;br /&gt;
        local band_kind = row.band_kind or &amp;#039;default&amp;#039;&lt;br /&gt;
        entry[band_kind][row.skill_id] = tonumber(row.weight)&lt;br /&gt;
    end&lt;br /&gt;
    return chances&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
local function computeTotals(chances)&lt;br /&gt;
    local totals = {}&lt;br /&gt;
    for classId, info in pairs(chances) do&lt;br /&gt;
        totals[classId] = {&lt;br /&gt;
            default = 0,&lt;br /&gt;
            magic_levels = 0,&lt;br /&gt;
            signature_levels = 0,&lt;br /&gt;
            level_20_mega = 0,&lt;br /&gt;
        }&lt;br /&gt;
        for skillId, weight in pairs(info.default) do&lt;br /&gt;
            totals[classId].default = totals[classId].default + weight&lt;br /&gt;
&lt;br /&gt;
            local magicWeight = info.magic_levels[skillId] or weight&lt;br /&gt;
            totals[classId].magic_levels = totals[classId].magic_levels + magicWeight&lt;br /&gt;
&lt;br /&gt;
            local signatureWeight = info.signature_levels[skillId] or weight&lt;br /&gt;
            totals[classId].signature_levels = totals[classId].signature_levels + signatureWeight&lt;br /&gt;
&lt;br /&gt;
            local l20Weight = info.level_20_mega[skillId] or weight&lt;br /&gt;
            totals[classId].level_20_mega = totals[classId].level_20_mega + l20Weight&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return totals&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
local function formatRatio(a, b)&lt;br /&gt;
    if not a or not b then&lt;br /&gt;
        return &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    return string.format(&amp;quot;%.2f&amp;quot;, 100 * a / b) .. &amp;#039;%&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
local function formatChances(chances, totals, skillId)&lt;br /&gt;
    local lines = {}&lt;br /&gt;
    for classId, info in pairs(chances) do&lt;br /&gt;
        local parts = {}&lt;br /&gt;
&lt;br /&gt;
        local main = info.default[skillId]&lt;br /&gt;
        local magic = info.magic_levels[skillId] or main&lt;br /&gt;
        local signature = info.signature_levels[skillId] or main&lt;br /&gt;
        local l20 = info.level_20_mega[skillId] or main&lt;br /&gt;
&lt;br /&gt;
        local ts = totals[classId]&lt;br /&gt;
        table.insert(parts, formatRatio(main, ts.default))&lt;br /&gt;
        table.insert(parts, magic ~= main and formatRatio(magic, ts.magic_levels) or &amp;#039;&amp;#039;)&lt;br /&gt;
        table.insert(parts, signature ~= main and formatRatio(signature, ts.signature_levels) or &amp;#039;&amp;#039;)&lt;br /&gt;
        table.insert(parts, l20 ~= main and formatRatio(l20, ts.level_20_mega) or &amp;#039;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
        while #parts &amp;gt; 0 and parts[#parts] == &amp;#039;&amp;#039; do&lt;br /&gt;
            table.remove(parts)&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        table.insert(lines, &amp;#039;| &amp;#039; .. classId .. &amp;#039; = &amp;#039; .. table.concat(parts, &amp;#039;,&amp;#039;))&lt;br /&gt;
    end&lt;br /&gt;
    return table.concat(lines, &amp;#039;\n&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------------------------------------------&lt;br /&gt;
function p.populate(frame)&lt;br /&gt;
    local lang = frame.args.lang&lt;br /&gt;
    local skillId = frame.args.id;&lt;br /&gt;
&lt;br /&gt;
    local chancesBulk = collectChances();&lt;br /&gt;
    local chances = consolidateChances(chancesBulk);&lt;br /&gt;
    local totals = computeTotals(chances);&lt;br /&gt;
    local formattedChances = formatChances(chances, totals, skillId);&lt;br /&gt;
    --do return dump(formattedChances) end&lt;br /&gt;
&lt;br /&gt;
    local cleanTitle = frame:getTitle():gsub(&amp;#039;Module:&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
    return frame:preprocess(mw.ustring.format([[&lt;br /&gt;
        {{%s/base&lt;br /&gt;
        | lang = %s&lt;br /&gt;
        | id = %s&lt;br /&gt;
        %s&lt;br /&gt;
        }}&lt;br /&gt;
    ]], cleanTitle, lang, skillId, formattedChances))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>76561198048502585</name></author>
	</entry>
</feed>