Module:Quest reward: Difference between revisions

From Path of Exile Wiki
Jump to navigation Jump to search
>Illviljan
(Use the cargo module instead of util.cargo)
(Declare variables locally.)
 
(14 intermediate revisions by 4 users not shown)
Line 38: Line 38:


local tables = {}
local tables = {}
tables.quest_rewards = {
    table = 'quest_rewards',
    fields = {
        quest = {
            field = 'quest',
            type = 'String',
        },
        quest_id = {
            field = 'quest_id',
            type = 'Integer',
        },
        -- still needed?
        act = {
            field = 'act',
            type = 'Integer',
        },
        classes = {
            field = 'classes',
            type = 'String',
        },
        sockets = {
            field = 'sockets',
            type = 'Integer',
        },
        item_level = {
            field = 'item_level',
            type = 'Integer',
        },
        rarity = {
            field = 'rarity',
            type = 'String',
        },
        reward = {
            field = 'reward',
            type = 'Page',
        },
    },
}
tables.vendor_rewards = {
    table = 'vendor_rewards',
    fields = {
        quest = {
            field = 'quest',
            type = 'String',
        },
        quest_id = {
            field = 'quest_id',
            type = 'Integer',
        },
        act = {
            field = 'act',
            type = 'Integer',
        },
        reward = {
            field = 'reward',
            type = 'Page',
        },
        npc = {
            field = 'npc',
            type = 'String',
        },
        classes = {
            field = 'classes',
            type = 'String',
        },
    }
}


-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
Line 117: Line 48:
-- Page functions
-- Page functions
-- ----------------------------------------------------------------------------
-- ----------------------------------------------------------------------------
p.table_quest_rewards = m_cargo.declare_factory{data=tables.quest_rewards}
p.table_vendor_rewards = m_cargo.declare_factory{data=tables.vendor_rewards}
function p.store_data(frame)
    -- Get args
    tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)
   
    if tables[tpl_args.tbl .. '_rewards'] == nil then
        error(i18n.errors.invalid_table)
    end
   
    -- mw.loadData has some problems...
    local data = require(string.format('Module:Quest reward/data/%s', tpl_args.tbl))
    local imin = tpl_args.index_start or 1
    local imax = tpl_args.index_end or #data
    for i=imin, imax or #data do
        local row = data[i]
        if row == nil then
            break
        end
        -- get full table name
        row._table = tables[tpl_args.tbl .. '_rewards'].table
        m_cargo.store(frame, row)
    end
   
    return string.format(i18n.messages.storage, imin, imax, tpl_args.tbl)
end


function p._shared.reward_tbl_head()
function p._shared.reward_tbl_head()
Line 160: Line 60:
         tr:tag('th')
         tr:tag('th')
             :attr('rowspan', 2)
             :attr('rowspan', 2)
             :wikitext(string.format('[[%s]]', class))
             :wikitext(string.format('[[%s]]', m_game.constants.characters[class].name))
     end
     end
   
 
     tbl
     tbl
         :tag('tr')
         :tag('tr')
Line 175: Line 75:
         npc = string.format('<br>[[%s]]', row[rtbl .. '.npc'])
         npc = string.format('<br>[[%s]]', row[rtbl .. '.npc'])
     end
     end
   
 
     tr
     tr
         :tag('th')
         :tag('th')
Line 184: Line 84:
function p._shared.reward_tbl_extra_info(row)
function p._shared.reward_tbl_extra_info(row)
     local value = {}
     local value = {}
     if row['quest_rewards.item_level'] then
     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'])
         value[#value+1] = string.format(i18n.quest_reward.item_level, row['quest_rewards.item_level'])
     end
     end
Line 191: Line 91:
         value[#value+1] = m_util.html.poe_color(string.lower(row['quest_rewards.rarity']), row['quest_rewards.rarity'])
         value[#value+1] = m_util.html.poe_color(string.lower(row['quest_rewards.rarity']), row['quest_rewards.rarity'])
     end
     end
     if row['quest_rewards.sockets'] then
     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'])
         value[#value+1] = string.format(i18n.quest_reward.links, row['quest_rewards.sockets'])
     end
     end
   
 
     return table.concat(value, ', ')
     return table.concat(value, ', ')
end
end
Line 201: Line 101:
     --[[
     --[[
     Displays a table of quest rewards from a certain quest.
     Displays a table of quest rewards from a certain quest.
   
 
     Examples
     Examples
     --------
     --------
     = p.quest_reward_table{type='vendor_rewards', q_where="A Fixture of Fate"}
     = p.quest_reward_table{type='vendor_rewards', q_where='quest="A Fixture of Fate"'}
     ]]
     ]]
   
 
     -- Get args
     -- Get args
     tpl_args = getArgs(frame, {
     local tpl_args = getArgs(frame, {
         parentFirst = true
         parentFirst = true
     })
     })
Line 230: Line 130:
                 'quest_rewards.item_level',
                 'quest_rewards.item_level',
                 'quest_rewards.rarity',
                 'quest_rewards.rarity',
                 'quest_rewards.reward',
                 'quest_rewards._pageName',
             },
             },
             {
             {
                 where=q_where,
                 where=q_where,
                 orderBy='quest_rewards.act ASC, quest_rewards.quest_id ASC, quest_rewards.reward ASC',
                 orderBy='quest_rewards.act ASC, quest_rewards.quest_id ASC, quest_rewards._pageName ASC',
                 limit=5000,
                 limit=5000,
             }
             }
Line 246: Line 146:
                 'vendor_rewards.classes',
                 'vendor_rewards.classes',
                 'vendor_rewards.npc',
                 'vendor_rewards.npc',
                 'vendor_rewards.reward',
                 'vendor_rewards._pageName',
             },
             },
             {
             {
                 where=q_where,
                 where=q_where,
                 orderBy='vendor_rewards.act ASC, vendor_rewards.quest_id ASC, vendor_rewards.reward ASC',
                 orderBy='vendor_rewards.act ASC, vendor_rewards.quest_id ASC, vendor_rewards._pageName ASC',
                 limit=5000,
                 limit=5000,
             }
             }
Line 257: Line 157:
         error(i18n.errors.invalid_type, tpl_args.type)
         error(i18n.errors.invalid_type, tpl_args.type)
     end
     end
   
 
     -- ------------------------------------------------------------------------
     -- ------------------------------------------------------------------------
     -- Build output table
     -- Build output table
     -- ------------------------------------------------------------------------
     -- ------------------------------------------------------------------------
     local tbl = p._shared.reward_tbl_head()
     local tbl = p._shared.reward_tbl_head()
   
 
     if #data == 0 then
     if #data == 0 then
         return tostring(tbl)
         return tostring(tbl)
     end
     end
   
 
     local quest_order = {}
     local quest_order = {}
     local quests = {}
     local quests = {}
     local pages = {}
     local pages = {}
   
 
     --
     --
     -- remap data to quests[questid].classes[class]
     -- remap data to quests[questid].classes[class]
Line 281: Line 181:
             quests[row[tpl_args.type .. '.quest']] = classes
             quests[row[tpl_args.type .. '.quest']] = classes
         end
         end
       
 
         if row[tpl_args.type .. '.classes'] then
         if row[tpl_args.type .. '.classes'] then
             for _, class in ipairs(m_util.string.split(row[tpl_args.type .. '.classes'], '')) do
            classes[-1] = {}
             for _, class in ipairs(m_util.string.split(row[tpl_args.type .. '.classes'], ',')) do
                 if classes[class] == nil then
                 if classes[class] == nil then
                     classes[class] = {}
                     classes[class] = {}
Line 295: Line 196:
             table.insert(classes[0], row)
             table.insert(classes[0], row)
         end
         end
       
 
         pages[row[tpl_args.type .. '.reward']] = true
         pages[row[tpl_args.type .. '._pageName']] = true
     end
     end
     --
     --
Line 307: Line 208:
             pages_array[#pages_array+1] = page
             pages_array[#pages_array+1] = page
         end
         end
       
 
         local fields = {
         local fields = {
             'items.name',
             'items.name',
             'items.inventory_icon',
             'items.inventory_icon',
         }
         }
       
 
         if m_util.cast.boolean(tpl_args.no_html) ~= true then
         if m_util.cast.boolean(tpl_args.no_html) ~= true then
             fields[#fields+1] = 'items.html'
             fields[#fields+1] = 'items.html'
         end
         end
       
 
         item_data = m_cargo.map_results_to_id{
         item_data = m_cargo.map_results_to_id{
             results=m_cargo.array_query{
             results=m_cargo.array_query{
Line 326: Line 227:
                     limit=5000,
                     limit=5000,
                 },
                 },
             },  
             },
             field='items._pageName',
             field='items._pageName',
         }
         }
Line 333: Line 234:
     -- Output rows
     -- Output rows
     --
     --
   
 
     function element(rows)
     local function element(rows)
         if rows == nil then
         if rows == nil then
             return ''
             return ''
Line 340: Line 241:
         local out = {}
         local out = {}
         for _, row in ipairs(rows) do
         for _, row in ipairs(rows) do
             local reward = row[tpl_args.type .. '.reward']
             local reward = row[tpl_args.type .. '._pageName']
             if tpl_args.item_link then
             if tpl_args.item_link then
                 local idata = item_data[reward][1]
                 local idata = item_data[reward][1]
Line 356: Line 257:
         return table.concat(out, '<br>')
         return table.concat(out, '<br>')
     end
     end
   
 
     for _, quest_key in ipairs(quest_order) do
     for _, quest_key in ipairs(quest_order) do
        local tr = tbl:tag('tr')
       
         local classes = quests[quest_key]
         local classes = quests[quest_key]
         for _, class in pairs(classes) do
 
            if class[1] then
         if classes[0] then
                p._shared.reward_tbl_row_head(tr, tpl_args.type, class[1])
            local tr = tbl:tag('tr')
                 break
            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
             end
        end
       
        if classes[0] then
             tr:tag('td')
             tr:tag('td')
                 :attr('colspan', 7)
                 :attr('colspan', 7)
                 :attr('style', 'text-align: center;')
                 :attr('style', 'text-align: center;')
                 :wikitext(element(classes[0]))
                 :wikitext(element(classes[0]))
         else
         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
             for _, class in ipairs(m_game.constants.characters_order) do
                tr:tag('td')
                tr:tag('td')
                     :wikitext(element(classes[class]))
                     :wikitext(element(classes[m_game.constants.characters[class].name]))
             end
             end
         end
         end
     end
     end
   
 
     return tostring(tbl)
     return tostring(tbl)
end
end

Latest revision as of 16:45, 17 January 2022

--
-- 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