Module:Incursion

From Path of Exile Wiki
Revision as of 12:35, 30 April 2023 by Vinifera7 (talk | contribs) (Translation strings moved to Module:Incursion/config for easier porting. No globals.)
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]


Handles various incursion related templates:

-------------------------------------------------------------------------------
-- 
--                            Module:Incursion
-- 
-- This module implements Template:Incursion room
-------------------------------------------------------------------------------

require('Module:No globals')
local m_util = require('Module:Util')
local m_cargo = require('Module:Cargo')

-- Should we use the sandbox version of our submodules?
local use_sandbox = m_util.misc.maybe_sandbox('Incursion')

-- Lazy loading
local f_infocard -- require('Module:Infocard')._main

-- The cfg table contains all localisable strings and configuration, to make it
-- easier to port this module to another wiki.
local cfg = use_sandbox and mw.loadData('Module:Incursion/config/sandbox') or mw.loadData('Module:Incursion/config')

local i18n = cfg.i18n

-- ----------------------------------------------------------------------------
-- Tables
-- ----------------------------------------------------------------------------

local tables = {
    incursion_rooms = {
        table = 'incursion_rooms',
        order = {'id', 'name', 'description', 'flavour_text', 'tier', 'upgrade_room_id', 'icon', 'min_level', 'architect_metadata_id', 'architect_name', 'modifier_ids', 'stat_text'},
        display_table_order = {'id', 'tier', 'upgrade_room_id', 'min_level', 'architect_name'},
        display_list_order = {'description', 'stat_text', 'icon', 'flavour_text',},
        fields = {
            id = {
                field = 'id',
                type = 'String(size=100; unique)',
                required = true,
                
                header = i18n.headings.id,
            },
            name = {
                field = 'name',
                type = 'String',
            },
            description = {
                field = 'description',
                type = 'Text',
                display = function (tpl_args)
                    return m_util.html.poe_color('mod', tpl_args.description)
                end
            },
            flavour_text = {
                field = 'flavour_text',
                type = 'Text',
                display = function (tpl_args)
                    return m_util.html.poe_color('flavour', tpl_args.flavour_text)
                end
            },
            tier = {
                field = 'tier',
                type = 'Integer',
                
                header = i18n.headings.tier,
            },
            upgrade_room_id = {
                field = 'upgrade_room_id',
                type = 'String',
                func = function (tpl_args, value)
                    if value == nil then
                        return
                    end
                    local results = m_cargo.query(
                        {'incursion_rooms'},
                        {'incursion_rooms._pageName', 'incursion_rooms.name'},
                        {
                            where=string.format('incursion_rooms.id="%s"', value)
                        }
                    )
                    if #results == 0 then
                        return
                    end
                    -- Save the upgrade room to tpl_args so we can make a link for it in the display
                    tpl_args.upgrade_room = results[1]
                    return value
                end,
                
                header = i18n.headings.upgrade_room_id,
                display = function(tpl_args)
                    if tpl_args.upgrade_room == nil then
                        if tpl_args.upgrade_room_id == nil then
                            return
                        else
                            return tpl_args.upgrade_room_id
                        end
                    end
                    return string.format('[[%s|%s]]', tpl_args.upgrade_room['incursion_rooms._pageName'], tpl_args.upgrade_room['incursion_rooms.name'])
                end
            },
            icon = {
                field = 'icon',
                type = 'Page',
                func = function (tpl_args, value)
                    if value == nil then
                        return
                    end
                    
                    return string.format(i18n.files.icon_format, value)
                end,
                
                display = function (tpl_args)
                    return string.format('[[%s]]', tpl_args.icon)
                end,
            },
            min_level = {
                field = 'min_level',
                type = 'Integer',
                default = 0,
                
                header = i18n.headings.min_level,
            },
            -- architect_name is temporary until monsters are added to the wiki
            architect_metadata_id = {
                field = 'architect_metadata_id',
                type = 'String',
            },
            architect_name = {
                field = 'architect_name',
                type = 'String',
                header = i18n.headings.architect,
                display = function (tpl_args)
                    return string.format('[[%s]]', tpl_args.architect_name)
                end,
            },
            modifier_ids = {
                field = 'modifier_ids',
                type = 'List (,) of String',
                func = function (tpl_args, value)
                    if value == nil then
                        return
                    end
                    tpl_args.mods = m_cargo.array_query{
                        tables={'mods'},
                        fields={'mods.stat_text'},
                        id_field='mods.id',
                        id_array=value
                    }
                    
                    return value
                end,
                
                header = i18n.headings.modifier_ids,
            },
            stat_text = {
                field = 'stat_text',
                type = 'Text',
                func = function (tpl_args, value)
                    if tpl_args.mods == nil then
                        return
                    end
                    local text = {}
                    for page, row in pairs(tpl_args.mods) do
                        if row['mods.stat_text'] then
                            text[#text+1] = row['mods.stat_text']
                        end
                    end
                    return table.concat(text, '<br>')
                end,
            },
        },
    },
}

-- ----------------------------------------------------------------------------
-- Helper functions
-- ----------------------------------------------------------------------------

local h = {}

function h.check_args(tpl_args, key, data)
    local value = tpl_args[key]
    if value == nil then
        return false
    end
    
    if data.default == value then
        return false
    end
    
    return true
end

-- Lazy loading for Module:Infocard
function h.infocard(args)
    if not f_infocard then
        f_infocard = require('Module:Infocard')._main
    end
    return f_infocard(args)
end

-- ----------------------------------------------------------------------------
-- Main functions
-- ----------------------------------------------------------------------------

local function _incursion_room(tpl_args)
    --[[
    Stores cargo data for incursion rooms and displays it in a infobox.
    
    Examples
    --------
    = p.incursion_room{
        id = 'CorruptionRoomIII',
        name = 'Locus of Corruption',
        description = 'Reduces player maximum resistances throughout the Temple.<br />Contains an Altar of Corruption.',
        flavour_text = 'Darkness coalesces, imbues, and blesses.',
        tier = '3',
        icon = 'CorruptionRoom3',
        modifier_ids = 'MapPlayerMaxResists3__',
        architect_metadata_id = 'Metadata/Monsters/VaalArchitect/VaalArchitect8',
        architect_name = 'Paquate, Architect of Corruption',
    }
    
    ]]
    
    m_util.args.from_cargo_map{
        tpl_args=tpl_args,
        table_map=tables.incursion_rooms,
    }
    
    --
    -- infobox
    -- 
    local infocard_args = {}
    infocard_args.header = tpl_args.name
    
    local function display (value, data)
        if data.display then
            return data.display(tpl_args) or ''
        end
        
        if type(value) == 'table' then
            return table.concat(value, ', ')
        end
        
        return value or ''
    end
    
    -- Main sections, loop through
    local tbl = mw.html.create('table')
    tbl:attr('style', 'width: 100%;')
    for _, key in ipairs(tables.incursion_rooms.display_table_order) do
        local data = tables.incursion_rooms.fields[key]
        if h.check_args(tpl_args, key, data) then
            tbl
                :tag('tr')
                    :tag('th')
                        :wikitext(data.header or '')
                        :done()
                    :tag('td')
                        :wikitext(display(tpl_args[key], data))
                        :done()
                    :done()
        end
    end
    
    infocard_args[1] = tostring(tbl)
    
    local i = 2
    for _, key in ipairs(tables.incursion_rooms.display_list_order) do
        local data = tables.incursion_rooms.fields[key]
        if h.check_args(tpl_args, key, data) then
            infocard_args[i] = display(tpl_args[key], data)
            i = i + 1
        end
    end
    
    --
    -- Categories
    -- 
    
    local cats = {
        'Incursion rooms',
    }

    -- Attach to table
    mw.getCurrentFrame():expandTemplate{title = 'Template:Incursion room/cargo/incursion_rooms/attach'}
    
    --
    -- Done - output
    --
    
    return h.infocard(infocard_args) .. m_util.misc.add_category(cats)
end

-- ----------------------------------------------------------------------------
-- Exported functions
-- ----------------------------------------------------------------------------

local p = {}

p.table_incursion_rooms = m_cargo.declare_factory{data=tables.incursion_rooms}

--
-- Template:Incursion room
-- 
p.incursion_room = m_util.misc.invoker_factory(_incursion_room, {
    wrappers = cfg.wrappers.incursion_room,
})

return p