Module:Quest reward

From Path of Exile 2 Wiki
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]


Lua logo

This module depends on the following other modules:

Module for handling quest reward related data.

Subpages

--
-- Module for bestiary templates
--

local m_game = require('Module:Game')
local m_util = require('Module:Util')
local f_item_link = require('Module:Item link').item_link
local getArgs = require('Module:Arguments').getArgs
local m_cargo = require('Module:Cargo')

local p = {}
p._shared = {}

-- ----------------------------------------------------------------------------
-- Strings
-- ----------------------------------------------------------------------------

local i18n = {
    errors = {
        invalid_table = 'Invalid table selected. Valid choices are either quest or vendor',
        invalid_type = 'type must be either quest_rewards or vendor_rewards',
    },
    messages = {
        storage = 'Attempted to store rows %s to %s in "%s_rewards" table',
    },
    quest_reward = {
        character_class = 'Class →',
        quest = 'Quest ↓',
        row_header = '[[%s]]<br>Act %s',
        item_level = 'iLvl %s',
        links = '%s-linked',
    },
}

-- ----------------------------------------------------------------------------
-- Cargo
-- ----------------------------------------------------------------------------

local tables = {}

-- ----------------------------------------------------------------------------
-- Helper functions and globals
-- ----------------------------------------------------------------------------

local h = {}

-- ----------------------------------------------------------------------------
-- Page functions
-- ----------------------------------------------------------------------------

function p._shared.reward_tbl_head()
    local tbl = mw.html.create('table')
    tbl:attr('class', 'wikitable sortable')
    local tr = tbl:tag('tr')
    tr
        :tag('th')
            :attr('class', 'unsortable')
            :wikitext(i18n.quest_reward.character_class)
    for _, class in ipairs(m_game.constants.characters_order) do
        tr:tag('th')
            :attr('rowspan', 2)
            :wikitext(string.format('[[%s]]', m_game.constants.characters[class].name))
    end

    tbl
        :tag('tr')
            :tag('th')
                :wikitext(i18n.quest_reward.quest)
    return tbl
end

function p._shared.reward_tbl_row_head(tr, rtbl, row)
    local npc = ''
    if row[rtbl .. '.npc'] then
        npc = string.format('<br>[[%s]]', row[rtbl .. '.npc'])
    end

    tr
        :tag('th')
            :wikitext(string.format(i18n.quest_reward.row_header, row[rtbl .. '.quest'], row[rtbl .. '.act']))
            :wikitext(npc)
end

function p._shared.reward_tbl_extra_info(row)
    local value = {}
    if row['quest_rewards.item_level'] and row['quest_rewards.item_level'] ~= 0 then
        value[#value+1] = string.format(i18n.quest_reward.item_level, row['quest_rewards.item_level'])
    end
    -- TODO: i18n rarity name?
    if row['quest_rewards.rarity'] then
        value[#value+1] = m_util.html.poe_color(string.lower(row['quest_rewards.rarity']), row['quest_rewards.rarity'])
    end
    if row['quest_rewards.sockets'] and row['quest_rewards.sockets'] ~= 0 then
        value[#value+1] = string.format(i18n.quest_reward.links, row['quest_rewards.sockets'])
    end

    return table.concat(value, ', ')
end

function p.quest_reward_table(frame)
    --[[
    Displays a table of quest rewards from a certain quest.

    Examples
    --------
    = p.quest_reward_table{type='vendor_rewards', q_where='quest="A Fixture of Fate"'}
    ]]

    -- Get args
    local tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)
    local q_where = tpl_args.q_where
    if tpl_args.item_link then
        tpl_args.item_link = m_util.cast.boolean(tpl_args.item_link)
    else
        tpl_args.item_link = true
    end

    local data
    if tpl_args.type == 'quest_rewards' then
        data = m_cargo.query(
            {'quest_rewards'},
            {
                'quest_rewards.quest',
                'quest_rewards.act',
                'quest_rewards.classes',
                'quest_rewards.sockets',
                'quest_rewards.item_level',
                'quest_rewards.rarity',
                'quest_rewards._pageName',
            },
            {
                where=q_where,
                orderBy='quest_rewards.act ASC, quest_rewards.quest_id ASC, quest_rewards._pageName ASC',
                limit=5000,
            }
        )
    elseif tpl_args.type == 'vendor_rewards' then
        data = m_cargo.query(
            {'vendor_rewards'},
            {
                'vendor_rewards.quest',
                'vendor_rewards.act',
                'vendor_rewards.classes',
                'vendor_rewards.npc',
                'vendor_rewards._pageName',
            },
            {
                where=q_where,
                orderBy='vendor_rewards.act ASC, vendor_rewards.quest_id ASC, vendor_rewards._pageName ASC',
                limit=5000,
            }
        )
    else
        error(i18n.errors.invalid_type, tpl_args.type)
    end

    -- ------------------------------------------------------------------------
    -- Build output table
    -- ------------------------------------------------------------------------
    local tbl = p._shared.reward_tbl_head()

    if #data == 0 then
        return tostring(tbl)
    end

    local quest_order = {}
    local quests = {}
    local pages = {}

    --
    -- remap data to quests[questid].classes[class]
    --
    for _, row in ipairs(data) do
        local classes = quests[row[tpl_args.type .. '.quest']]
        if classes == nil then
            table.insert(quest_order, row[tpl_args.type .. '.quest'])
            classes = {}
            quests[row[tpl_args.type .. '.quest']] = classes
        end

        if row[tpl_args.type .. '.classes'] then
            classes[-1] = {}
            for _, class in ipairs(m_util.string.split(row[tpl_args.type .. '.classes'], ',')) do
                if classes[class] == nil then
                    classes[class] = {}
                end
                table.insert(classes[class], row)
            end
        else
            if classes[0] == nil then
                    classes[0] = {}
                end
            table.insert(classes[0], row)
        end

        pages[row[tpl_args.type .. '._pageName']] = true
    end
    --
    -- Cache item data
    --
    local item_data
    if tpl_args.item_link then
        local pages_array = {}
        for page, _ in pairs(pages) do
            pages_array[#pages_array+1] = page
        end

        local fields = {
            'items.name',
            'items.inventory_icon',
        }

        if m_util.cast.boolean(tpl_args.no_html) ~= true then
            fields[#fields+1] = 'items.html'
        end

        item_data = m_cargo.map_results_to_id{
            results=m_cargo.array_query{
                tables={'items'},
                fields=fields,
                id_field='items._pageName',
                id_array=pages_array,
                query={
                    limit=5000,
                },
            },
            field='items._pageName',
        }
    end
    --
    -- Output rows
    --

    local function element(rows)
        if rows == nil then
            return ''
        end
        local out = {}
        for _, row in ipairs(rows) do
            local reward = row[tpl_args.type .. '._pageName']
            if tpl_args.item_link then
                local idata = item_data[reward][1]
                reward = f_item_link{page=reward, name=idata['items.name'], inventory_icon=idata['items.inventory_icon'] or '', html=idata['items.html'] or '', skip_query=true}
            else
                reward = string.format('[[%s]]', reward)
            end
            local info = p._shared.reward_tbl_extra_info(row)
            if info ~= '' then
                out[#out+1] = string.format('%s (%s)', reward, info)
            else
                out[#out+1] = reward
            end
        end
        return table.concat(out, '<br>')
    end

    for _, quest_key in ipairs(quest_order) do
        local classes = quests[quest_key]

        if classes[0] then
            local tr = tbl:tag('tr')
            for _, class in pairs(classes) do
                if class[1] then
                    p._shared.reward_tbl_row_head(tr, tpl_args.type, class[1])
                    break
                end
            end
            tr:tag('td')
                :attr('colspan', 7)
                :attr('style', 'text-align: center;')
                :wikitext(element(classes[0]))
        end
        if classes[-1] then
            local tr = tbl:tag('tr')
            for _, class in pairs(classes) do
                if class[1] then
                    p._shared.reward_tbl_row_head(tr, tpl_args.type, class[1])
                    break
                end
            end
            for _, class in ipairs(m_game.constants.characters_order) do
                 tr:tag('td')
                    :wikitext(element(classes[m_game.constants.characters[class].name]))
            end
        end
    end

    return tostring(tbl)
end

-- ----------------------------------------------------------------------------
-- End
-- ----------------------------------------------------------------------------

return p