Jump to content

Module:MonsterCategoryTable

From Apogea Wiki

Documentation for this module may be created at Module:MonsterCategoryTable/doc

local p = {}

-- Parent categories and their child types (for future subcategories)
local parentCategories = {
    -- Example: ["Undead"] = {"Skeleton", "Zombie", "Ghost"},
}

-- Query monsters by type from Cargo
local function getMonstersByType(monsterType)
    local tables = 'Monsters'
    local fields = 'name,sprite,type,hp,xp,armor,defense,attack_speed,move_speed,respawn'
    local args = {
        where = 'type="' .. monsterType .. '"',
        orderBy = 'name',
        limit = 500
    }
    
    return mw.ext.cargo.query(tables, fields, args)
end

-- Query monsters by multiple types
local function getMonstersByTypes(types)
    local tables = 'Monsters'
    local fields = 'name,sprite,type,hp,xp,armor,defense,attack_speed,move_speed,respawn'
    
    local conditions = {}
    for _, t in ipairs(types) do
        table.insert(conditions, 'type="' .. t .. '"')
    end
    
    local args = {
        where = table.concat(conditions, ' OR '),
        orderBy = 'name',
        limit = 500
    }
    
    return mw.ext.cargo.query(tables, fields, args)
end

-- Query all monsters
local function getAllMonsters()
    local tables = 'Monsters'
    local fields = 'name,sprite,type,hp,xp,armor,defense,attack_speed,move_speed,respawn'
    local args = {
        orderBy = 'name',
        limit = 500
    }
    
    return mw.ext.cargo.query(tables, fields, args)
end

-- Get numeric value from stat (0 if empty)
local function statNum(value)
    if value and value ~= "" then
        return tonumber(value) or 0
    end
    return 0
end

-- Format stat value (return empty string if 0 or empty)
local function stat(value)
    if value and value ~= "" then
        return value
    end
    return "0"
end

function p.render(frame)
    local args = frame:getParent().args
    local categoryName = args[1] or args.category or mw.title.getCurrentTitle().text:gsub("^Category:", "")
    
    -- Check if this is all monsters or a parent category
    local isAllMonsters = (categoryName == "Monsters")
    local isParent = parentCategories[categoryName] ~= nil or isAllMonsters
    local monsters
    
    if isAllMonsters then
        monsters = getAllMonsters()
    elseif parentCategories[categoryName] then
        monsters = getMonstersByTypes(parentCategories[categoryName])
    else
        monsters = getMonstersByType(categoryName)
    end
    
    if not monsters or #monsters == 0 then
        return '<p class="mw-empty">No monsters found.</p>'
    end
    
    -- Sort by XP (descending) as a proxy for difficulty
    table.sort(monsters, function(a, b) return statNum(a.xp) > statNum(b.xp) end)
    
    -- Build sortable table
    local tbl = mw.html.create('table')
    tbl:addClass('wikitable')
       :addClass('sortable')
       :css('width', '100%')
    
    -- Header row
    local header = tbl:tag('tr')
    header:tag('th')
        :css('width', '64px')
        :addClass('unsortable')
        :wikitext('')
    header:tag('th'):wikitext('Monster')
    if isParent and not isAllMonsters then
        header:tag('th'):wikitext('Type')
    end
    header:tag('th'):attr('title', 'Health Points'):wikitext('HP')
    header:tag('th'):attr('title', 'Experience'):wikitext('XP')
    header:tag('th'):attr('title', 'Armor'):wikitext('ARM')
    header:tag('th'):attr('title', 'Defense'):wikitext('DEF')
    header:tag('th'):attr('title', 'Attack Speed'):wikitext('AS')
    header:tag('th'):attr('title', 'Move Speed'):wikitext('MS')
    header:tag('th'):attr('title', 'Respawn Time'):wikitext('Respawn')
    
    -- Data rows
    for _, monster in ipairs(monsters) do
        local row = tbl:tag('tr')
        
        -- Icon column
        local iconCell = row:tag('td')
            :css('width', '64px')
            :css('text-align', 'center')
        local sprite = monster.sprite or monster.name or "Unknown"
        if sprite and sprite ~= "" then
            iconCell:wikitext(frame:preprocess('{{MonsterPreview|' .. sprite .. '|48}}'))
        end
        
        -- Monster name column
        local monsterName = monster.name or "Unknown"
        row:tag('td'):wikitext('[[' .. monsterName .. ']]')
        
        -- Type column (for parent categories with subcategories)
        if isParent and not isAllMonsters then
            row:tag('td'):wikitext(monster.type or "")
        end
        
        -- Stats
        row:tag('td'):css('text-align', 'right'):wikitext(stat(monster.hp))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(monster.xp))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(monster.armor))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(monster.defense))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(monster.attack_speed))
        row:tag('td'):css('text-align', 'right'):wikitext(stat(monster.move_speed))
        row:tag('td'):css('text-align', 'right'):wikitext(monster.respawn or "")
    end
    
    return tostring(tbl)
end

return p