Module:Monsters By Ability

From Idlescape Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Monsters By Ability/doc

local p = {}
local abilitiesData = mw.loadData("Module:Abilities/data")
local monstersData = mw.loadData("Module:Monsters/data")
local monstersStatsData = mw.loadData("Module:Monsters stats/data")


---Finds the first table entry in the given table with the given key and value.
---@generic T
---@param tbl table<any, T> # The table to search.
---@param key any # The key to search for.
---@param val any # The value to search for.
---@return T|nil # The first table entry with the given key and value, or nil if not found.
local function findByKeyVal(tbl, key, val)
    if type(tbl) ~= "table" then return nil end
    for k, v in pairs(tbl) do
        if v[key] == val then
            return v
        end
    end
end

---Formats the given URL to full play.idlescape.com URL.
local function fullUrl(url)
    local newUrl = url
    if url:sub(1, 4) == "http" or url:sub(1,2) == "[[" then
        return newUrl
    end

    if url:sub(1, 1) ~= "/" then
        newUrl = "/" .. newUrl
    end

    return "https://www.play.idlescape.com" .. newUrl
end

---Creates an image link for the given name and URL.
---@param name string # The name of the link and image.
---@param url string # The URL of the image.
---@param word boolean # Whether to include the name in the link, if falsy it will be an image only.
---@param size number|string # The size of the image.
---@return string
local function image(name, url, word, size)
    size = size or 20
    url = fullUrl(url)
    return string.format(
        '[[%s|<img src="%s" alt="%s" width="%d" height="%d"><span style="position:relative;top:1px;">%s</span>]]',
        name, url, name, size, size, word and name or ""
    )
end


function p.usage(frame)
    local args = frame:getParent().args
    return p._usage(args)
end

function p._usage(args)
    local collapse = args.collapsed or args.collapse
    if collapse then collapse = collapse ~= "false" end
    local addCaption = args.caption ~= "false"
    local name = args.name or args.title or args[1] or mw.title.getCurrentTitle().text
    local ability = findByKeyVal(abilitiesData, "abilityName", name)

    if not ability then
        return "<div style=\"color:red\">No ability named '" .. name .. "'. The Module:Abilities/data may be outdated.</div>"
    end

    local monsters = {}
    for monsterId, monsterStats in pairs(monstersStatsData) do
        local monster = monstersData[monsterId]
        for _, v in ipairs(monster and monsterStats.abilities or {}) do
            if v.id == ability.id then
                table.insert(monsters, image(monsterStats.name, monster.image, true, 25))
                break
            end
        end
    end

    if monsters[1] ~= nil then
        table.sort(monsters)

        local container = mw.html.create("div"):css("width", "fit-content")
        if collapse ~= nil then
            container:addClass("mw-collapsible" .. (collapse and " mw-collapsed" or ""))
        end
        if addCaption then
            container:node(mw.html.create("div")
                :css("display", "inline")
                :wikitext("This ability is used by the following monsters:&nbsp;")
            )
        end

        local monsterList = mw.html.create(collapse ~= nil and "div" or nil)
            :addClass(collapse ~= nil and "mw-collapsible-content" or nil)

        for _, monster in ipairs(monsters) do
            monsterList:wikitext("\n* " .. monster)
        end

        return container:node(monsterList)
    end
end

return p