Module:Monsters stats table

From Idlescape Wiki
Revision as of 11:57, 24 June 2024 by HASH (talk | contribs) (needs testing)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

local p = {}
local findId = require("Module:FindId")

local monsters_stats = mw.loadData("Module:Monsters stats/data")
local defaultAffinities = {
    Melee = 1,
    Range = 1,
    Magic = 1,
    Piercing = 1,
    Blunt = 1,
    Slashing = 1,
    Fire = 1,
    Ice = 1,
    Nature = 1,
    Chaos = 1,
    Posion = 1,
    Lightning = 1
}

-- Convert from CSV string to table (converts a single line of a CSV file)
local function fromCSV(s)
    s = s .. ',' -- ending comma
    local t = {} -- table to collect fields
    local fieldstart = 1
    repeat
        local nexti = string.find(s, ',', fieldstart)
        table.insert(t, string.sub(s, fieldstart, nexti - 1))
        fieldstart = nexti + 1
    until fieldstart > string.len(s)
    return t
end

local function pairsByKeys(t, f)
    local a = {}
    local orgi_key_type
    local orgi_key_numbered
    for n in pairs(t) do
        if tonumber(n) == nil then
            table.insert(a, n)
            orgi_key_type = "word"
        elseif type(n) == "number" then
            table.insert(a, n)
            orgi_key_type = "int"
        elseif type(n) == "string" and type(tonumber(n) == "number") then
            orgi_key_type = "number"
            table.insert(a, tonumber(n))
        end
    end
    table.sort(a, f)
    local key
    local value
    local i = 0           -- iterator variable
    local iter = function() -- iterator function
        i = i + 1
        if a[i] == nil then
            return nil
        elseif orgi_key_type == "word" or orgi_key_type == "int" then
            key = a[i]
            value = t[a[i]]
        elseif orgi_key_type == "number" then
            key = tostring(a[i])
            value = t[tostring(a[i])]
        end
        return key, value
    end
    return iter
end

local function calcThreat(monster)
    local damageThreat = 2
    local weaponThreat = 3
    local armorThreat = 5
    local attackSpeedThreat = 3
    local attackSpeedThreatLevel = 2.4 / monster.attackSpeed
    local attackSpeedThreatFinal = attackSpeedThreatLevel * attackSpeedThreat
    local potentialDamageThreatFinal =
        (monster.attack +
            monster.strength +
            monster.magic +
            monster.range) *
        damageThreat
    local weaponThreatFinal =
        (monster.weapon.dexterity +
            monster.weapon.intellect +
            monster.weapon.strength) *
        weaponThreat
    local targetArmorRating =
        monster.armor.protection +
        monster.armor.resistance +
        monster.armor.agility * 1.5
    local armorThreatFinal = (targetArmorRating + monster.defense * 10) * armorThreat
    local baseThreat = (potentialDamageThreatFinal + weaponThreatFinal) * attackSpeedThreatFinal + armorThreatFinal
    return baseThreat
end

local function genDefensiveTable(monsters)
    local defensiveAffinties = {}
    local s = "{|class=\"wikitable sortable hover-highlight\"\n"
    s = s .. "!rowspan=2 colspan=2|Monster\n"
    s = s .. "!rowspan=2|Base<br/>Threat\n"
    s = s .. "!rowspan=2|Crit<br/>Avoidance\n"
    s = s .. "!rowspan=2|Crit<br/>Reduction\n"
    s = s .. "!colspan=12 style=\"text-align:center\"|Affinities\n"
    s = s .. "|-\n"
    s = s .. "![[File:Melee splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Magic splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Range splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Stab splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Crush splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Slash splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Fire_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Ice_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Nature_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Chaos_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Poison_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Lightning_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "|-\n"
    for _, monster in ipairs(monsters) do
        for affinity, value in pairsByKeys(defaultAffinities) do
            if monster.defensiveDamageAffinity[affinity] then
                defensiveAffinties[affinity] = monster.defensiveDamageAffinity[affinity]
            else
                defensiveAffinties[affinity] = defaultAffinities[affinity]
            end
        end
        s = s .. "|{{img|" .. monster["name"] .. "|20}}\n"
        s = s .. "[[" .. monster["name"] .. "]]\n"
        s = s .. "|" .. calcThreat(monster) .. "\n"
        for key, value in pairsByKeys(defensiveAffinties) do
            if value > 0 then
                s = s .. "|<span style=\"color:#4caf50\">" .. tonumber(value * 100) .. "%<span/>\n"
            else
                s = s .. "|<span style=\"color:#f44336\">" .. tonumber(value * 100) .. "%<span/>\n"
            end
        end
        s = s .. "|-\n"
    end
    s = s .. "|}"
end

local function genOffensiveTable(monsters)
    local offensiveAffinities = {}
    local s = "{|class=\"wikitable sortable hover-highlight\"\n"
    s = s .. "!rowspan=2|Crit<br/>Chance\n"
    s = s .. "!rowspan=2|Crit<br/>Multiplier\n"
    s = s .. "!colspan=12 style=\"text-align:center\"|Affinities\n"
    s = s .. "|-\n"
    s = s .. "![[File:Melee splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Magic splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Range splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Stab splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Crush splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Slash splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Fire_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Ice_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Nature_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Chaos_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Poison_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "![[File:Lightning_splash.png|20px|link=Combat#Affinities]]\n"
    s = s .. "|-\n"
    for _, monster in ipairs(monsters) do
        for affinity, value in pairsByKeys(defaultAffinities) do
            if monster.offensiveDamageAffinity[affinity] then
                offensiveAffinities[affinity] = monster.offensiveDamageAffinity[affinity]
            else
                offensiveAffinities[affinity] = defaultAffinities[affinity]
            end
        end
        s = s .. "|{{img|" .. monster["name"] .. "|20}}\n"
        s = s .. "[[" .. monster["name"] .. "]]\n"
        s = s .. "|" .. calcThreat(monster) .. "\n"
        for key, value in pairsByKeys(offensiveAffinities) do
            if value > 0 then
                s = s .. "|<span style=\"color:#4caf50\">" .. tonumber(value * 100) .. "%<span/>\n"
            else
                s = s .. "|<span style=\"color:#f44336\">" .. tonumber(value * 100) .. "%<span/>\n"
            end
        end
        s = s .. "|-\n"
    end
    s = s .. "|}"
end

function p.monsters_stats_table(frame)
    return p._monsters_stats_table(frame:getParent().args)
end

function p._monsters_stats_table(_args)
    local monstersName = fromCSV(_args[1])
    local monsters = {}
    local style = _args[2]

    for _, value in ipairs(monstersName) do
        monsters.insert(monsters_stats[tostring(findId._findId({ "mosnter", value }))])
    end
    if style == "defensive" then
        return genDefensiveTable(monsters)
    elseif style == "offensive" then
        return genOffensiveTable(monsters)
    else
        return "wrong style"
    end
end

return p