Jump to content

Module:Infobox: Difference between revisions

From Apogea Wiki
Dane (talk | contribs)
Add applyBonuses flag - items get + prefix, monsters don't (via update-page on MediaWiki MCP Server)
Dane (talk | contribs)
Update item() to query Cargo Items table (via update-page on MediaWiki MCP Server)
Line 20: Line 20:
     hpregen = { text = 'HP Regen', icon = 'Health_Regen.png', isBonus = true },
     hpregen = { text = 'HP Regen', icon = 'Health_Regen.png', isBonus = true },
     mpregen = { text = 'MP Regen', icon = 'Mana_Regen.png', isBonus = true },
     mpregen = { text = 'MP Regen', icon = 'Mana_Regen.png', isBonus = true },
    container = { text = 'Slots', icon = 'Container.png' },
      
      
     -- Monster-only stats
     -- Monster-only stats
Line 40: Line 41:
     end
     end
     return value
     return value
end
local function formatWeight(value)
    if not value or value == '' then
        return nil
    end
    return value .. ' oz'
end
end


Line 146: Line 154:
function p:finish()
function p:finish()
     return tostring(self.root)
     return tostring(self.root)
end
-- Query item data from Cargo
local function getItemData(name, rarity)
    local tables = 'Items'
    local fields = 'name,sprite,slot,type,weight,rng,damage,health,mana,ability,magic,armor,defense,move_speed,attack_speed,size,container,health_regen,mana_regen,description,rarity'
    local args = {
        where = 'name="' .. name .. '"',
        limit = 1
    }
   
    if rarity and rarity ~= '' then
        args.where = args.where .. ' AND rarity="' .. rarity .. '"'
    end
   
    local result = mw.ext.cargo.query(tables, fields, args)
   
    if result and result[1] then
        return result[1]
    end
    return nil
end
end


function p.item(frame)
function p.item(frame)
     local args = frame:getParent().args
     local args = frame:getParent().args
    local itemName = args.name or args[1]
    local rarity = args.rarity
   
    -- Query Cargo for item data
    local data = getItemData(itemName, rarity)
   
    if not data then
        return '<span class="error">Item not found: ' .. (itemName or 'nil') .. '</span>'
    end
      
      
     local box = p.new(frame, true)  -- applyBonuses = true for items
     local box = p.new(frame, true)  -- applyBonuses = true for items
         :addClass('item-infobox')
         :addClass('item-infobox')
      
      
     local sprite = args.sprite or args.name
     local sprite = data.sprite or data.name
     local spriteContent = frame:expandTemplate{
     local spriteContent = frame:expandTemplate{
         title = 'Sprite',
         title = 'Sprite',
Line 160: Line 198:
     }
     }
      
      
     box:addHeader(args.name or 'Unknown')
     box:addHeader(data.name or 'Unknown')
       :addImage(spriteContent)
       :addImage(spriteContent)
       :addRow('Slot', args.slot)
       :addRow('Slot', data.slot)
       :addRow('Type', args.category and string.format('[[:Category:%s|%s]]', args.category, args.category), 'type')
       :addRow('Type', data.type and string.format('[[:Category:%s|%s]]', data.type, data.type), 'type')
       :addStat('wgt', args.wgt)
       :addStat('wgt', formatWeight(data.weight))
       :addStat('rng', args.rng)
       :addStat('rng', data.rng)
       :addStat('dmg', args.dmg)
       :addStat('dmg', data.damage)
       :addStat('eq', args.eq)
       :addStat('eq', data.size)
       :addStat('hp', args.hp)
       :addStat('hp', data.health)
       :addStat('mp', args.mp)
       :addStat('mp', data.mana)
       :addStat('ab', args.ab)
       :addStat('ab', data.ability)
       :addStat('mag', args.mag)
       :addStat('mag', data.magic)
       :addStat('arm', args.arm)
       :addStat('arm', data.armor)
       :addStat('def', args.def)
       :addStat('def', data.defense)
       :addStat('ms', args.ms)
       :addStat('ms', data.move_speed)
       :addStat('as', args.as)
       :addStat('as', data.attack_speed)
       :addStat('hpregen', args.hpregen)
       :addStat('hpregen', data.health_regen)
       :addStat('mpregen', args.mpregen)
       :addStat('mpregen', data.mana_regen)
      :addStat('container', data.container)
      
      
     local categories = ''
     local categories = ''
     if args.category then
     if data.type then
         categories = categories .. '[[Category:' .. args.category .. ']]'
         categories = categories .. '[[Category:' .. data.type .. ']]'
     end
     end
      
      

Revision as of 00:38, 28 January 2026

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

local p = {}

-- Stat definitions: key -> { text, icon, isBonus }
local stats = {
    -- Shared stats (isBonus only applies when explicitly requested)
    hp = { text = 'HP', icon = 'Health.png', isBonus = true },
    mp = { text = 'MP', icon = 'Mana.png', isBonus = true },
    arm = { text = 'Armor', icon = 'Armor.png', isBonus = true },
    def = { text = 'Defense', icon = 'Defense.png', isBonus = true },
    ms = { text = 'Move Speed', icon = 'Move_Speed.png', isBonus = true },
    as = { text = 'Attack Speed', icon = 'Attack_Speed.png', isBonus = true },
    
    -- Item-only stats
    wgt = { text = 'Weight', icon = 'Weight.png' },
    rng = { text = 'Range', icon = 'Range.png' },
    dmg = { text = 'Damage', icon = 'Damage.png' },
    eq = { text = 'Equip Size', icon = 'Weight.png' },
    ab = { text = 'Ability', icon = 'Ability.png', isBonus = true },
    mag = { text = 'Magic', icon = 'Magic.png', isBonus = true },
    hpregen = { text = 'HP Regen', icon = 'Health_Regen.png', isBonus = true },
    mpregen = { text = 'MP Regen', icon = 'Mana_Regen.png', isBonus = true },
    container = { text = 'Slots', icon = 'Container.png' },
    
    -- Monster-only stats
    xp = { text = 'Experience', icon = 'Experience.png' },
    respawn = { text = 'Respawn Time', icon = 'Respawn_Time.png' },
}

-- Other icons
local icons = {
    type = { icon = 'Question_Mark.png', text = 'Type' },
}

local function formatBonus(value)
    if not value or value == '' then
        return nil
    end
    local num = tonumber(value)
    if num and num > 0 then
        return '+' .. value
    end
    return value
end

local function formatWeight(value)
    if not value or value == '' then
        return nil
    end
    return value .. ' oz'
end

local function makeIcon(frame, icon, tooltip)
    local img = frame:preprocess('{{#spritescale:' .. icon .. '|stat}}')
    return '<span title="' .. mw.text.encode(tooltip) .. '">' .. img .. '</span>'
end

function p.new(frame, applyBonuses)
    local builder = {
        root = mw.html.create('table'),
        frame = frame,
        applyBonuses = applyBonuses or false
    }
    
    builder.root
        :addClass('wikitable')
        :addClass('infobox')
        :css('float', 'right')
        :css('clear', 'right')
        :css('margin', '0 0 1em 1em')
        :css('width', '250px')
    
    setmetatable(builder, { __index = p })
    return builder
end

function p:addClass(class)
    self.root:addClass(class)
    return self
end

function p:addHeader(text)
    self.root:tag('tr')
        :tag('th')
            :attr('colspan', 2)
            :css('text-align', 'center')
            :wikitext(text)
    return self
end

function p:addImage(content)
    self.root:tag('tr')
        :tag('td')
            :attr('colspan', 2)
            :css('text-align', 'center')
            :wikitext(content)
    return self
end

function p:addRow(label, value, iconKey)
    if not value or value == '' then
        return self
    end
    
    local row = self.root:tag('tr')
    local th = row:tag('th')
        :css('text-align', 'right')
        :css('width', '32px')
    
    local iconData = icons[iconKey]
    if iconData then
        th:wikitext(makeIcon(self.frame, iconData.icon, label))
    else
        th:wikitext(label)
    end
    
    row:tag('td')
        :css('text-align', 'left')
        :wikitext(value)
    return self
end

function p:addStat(key, value)
    if not value or value == '' then
        return self
    end
    
    local stat = stats[key]
    if not stat then
        return self
    end
    
    local displayValue = value
    if self.applyBonuses and stat.isBonus then
        displayValue = formatBonus(value)
    end
    
    local row = self.root:tag('tr')
    local th = row:tag('th')
        :css('text-align', 'right')
        :css('width', '32px')
    
    if stat.icon then
        th:wikitext(makeIcon(self.frame, stat.icon, stat.text))
    else
        th:wikitext(stat.text)
    end
    
    row:tag('td')
        :css('text-align', 'left')
        :wikitext(displayValue)
    return self
end

function p:finish()
    return tostring(self.root)
end

-- Query item data from Cargo
local function getItemData(name, rarity)
    local tables = 'Items'
    local fields = 'name,sprite,slot,type,weight,rng,damage,health,mana,ability,magic,armor,defense,move_speed,attack_speed,size,container,health_regen,mana_regen,description,rarity'
    local args = {
        where = 'name="' .. name .. '"',
        limit = 1
    }
    
    if rarity and rarity ~= '' then
        args.where = args.where .. ' AND rarity="' .. rarity .. '"'
    end
    
    local result = mw.ext.cargo.query(tables, fields, args)
    
    if result and result[1] then
        return result[1]
    end
    return nil
end

function p.item(frame)
    local args = frame:getParent().args
    local itemName = args.name or args[1]
    local rarity = args.rarity
    
    -- Query Cargo for item data
    local data = getItemData(itemName, rarity)
    
    if not data then
        return '<span class="error">Item not found: ' .. (itemName or 'nil') .. '</span>'
    end
    
    local box = p.new(frame, true)  -- applyBonuses = true for items
        :addClass('item-infobox')
    
    local sprite = data.sprite or data.name
    local spriteContent = frame:expandTemplate{
        title = 'Sprite',
        args = { sprite, '64', class = 'pageimage' }
    }
    
    box:addHeader(data.name or 'Unknown')
       :addImage(spriteContent)
       :addRow('Slot', data.slot)
       :addRow('Type', data.type and string.format('[[:Category:%s|%s]]', data.type, data.type), 'type')
       :addStat('wgt', formatWeight(data.weight))
       :addStat('rng', data.rng)
       :addStat('dmg', data.damage)
       :addStat('eq', data.size)
       :addStat('hp', data.health)
       :addStat('mp', data.mana)
       :addStat('ab', data.ability)
       :addStat('mag', data.magic)
       :addStat('arm', data.armor)
       :addStat('def', data.defense)
       :addStat('ms', data.move_speed)
       :addStat('as', data.attack_speed)
       :addStat('hpregen', data.health_regen)
       :addStat('mpregen', data.mana_regen)
       :addStat('container', data.container)
    
    local categories = ''
    if data.type then
        categories = categories .. '[[Category:' .. data.type .. ']]'
    end
    
    return box:finish() .. categories
end

function p.monster(frame)
    local args = frame:getParent().args
    
    local box = p.new(frame, false)  -- applyBonuses = false for monsters
        :addClass('monster-infobox')
    
    local sprite = args.sprite or args.name
    local previewContent = frame:expandTemplate{
        title = 'MonsterPreview',
        args = { sprite, '128', mode = args.mode or 'auto', file = args.file or '' }
    }
    
    box:addHeader(args.name or 'Unknown')
       :addImage(previewContent)
       :addStat('hp', args.hp)
       :addStat('xp', args.xp)
       :addStat('arm', args.arm)
       :addStat('def', args.def)
       :addStat('as', args.as)
       :addStat('ms', args.ms)
       :addStat('respawn', args.respawn)
    
    return box:finish() .. '[[Category:Monsters]]'
end

return p