Path of Exile Wiki

Please consider helping keep the wiki up to date. Check the to-do list of updates needed for version 3.14.0.

Game data exports will becoming later as the technical changes in addition to regular changes take some more time.

READ MORE

Path of Exile Wiki
(show the text for sets in upgrade paths)
(Fixed sorting for 10+ elements)
Line 107: Line 107:
 
end
 
end
 
 
table.sort(sets_sort)
+
table.sort(sets_sort, function (a, b)
  +
return tonumber(sets[a]['upgraded_from_sets.set_id']) < tonumber(sets[b]['upgraded_from_sets.set_id'])
  +
end)
 
 
 
return sets, sets_sort
 
return sets, sets_sort

Revision as of 17:48, 17 June 2018

Template info icon Module documentation[view] [edit] [history] [purge]

This module provides functionality for showing item acquisition.

Overview

Item templates

Module:Item2

All templates defined in Module:Item2:

Module:Item table

All templates defined in Module:Item table:

Module:Item link

All templates defined in Module:Item link:

Module:Item acquisition

-- ----------------------------------------------------------------------------
-- Imports
-- ----------------------------------------------------------------------------

local getArgs = require('Module:Arguments').getArgs
local m_game = require('Module:Game')
local m_util = require('Module:Util')
local m_quest_reward = require('Module:Quest reward')._shared
local f_item_link = require('Module:Item link').item_link

-- ----------------------------------------------------------------------------
-- Strings
-- ----------------------------------------------------------------------------
-- This section contains strings used by this module.
-- Add new strings here instead of in-code directly, this will help other
-- people to correct spelling mistakes easier and help with translation to
-- other PoE wikis.
--
-- TODO: Maybe move this out to a separate sub-page module
local i18n = {
    acquisition = {
        header = 'Item acquisition',
        area_header = 'Area restrictions',
        area_legacy_header = 'Legacy area restrictions',
        area = 'This item can be acquired in the following areas:',
        
        upgraded_from_header = 'Upgrade paths',
        upgraded_from = 'This item can be acquired through the following upgrade paths or vendor recipes:',
        
        ingredient_header = 'Usage in upgrade paths',
        ingredient = 'This item is used by upgrade paths or vendor recipes to create the following items:',
    },
    
    quest_reward = {
        quest_rewards_header = 'Quest reward',
        quest_rewards_intro = 'This skill is given as quest reward for the following quests:',
        vendor_rewards_header = 'Vendor reward',
        vendor_rewards_intro = 'This skill can be bought at the listed npc vendors after completing the following quests:',
    },
}

-- ----------------------------------------------------------------------------
-- Globals
-- ----------------------------------------------------------------------------

local c = {}

c.MAX_ITEMS = 100

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

local h = {}
function h.head(str, level)
    local head = mw.html.create('h' .. (level or 3))
    head:wikitext(str)
    return tostring(head)
end

function h.fetch_upgraded_from_sets(where_set, where_group)
    if where_set == "" or where_group == "" then
        return {}, {}
    end
    
    local sets = {}
    local results = m_util.cargo.query(
        {'upgraded_from_sets'},
        {
            'upgraded_from_sets._pageName',
            'upgraded_from_sets.set_id',
            'upgraded_from_sets.text',
        },
        {
            where=where_set,
        }
    )
    
    for _, row in ipairs(results) do
        row.groups = {}
        sets[row['upgraded_from_sets._pageName'] .. tonumber(row['upgraded_from_sets.set_id'])] = row
    end
    
    results = m_util.cargo.query(
        {'upgraded_from_groups'},
        {
            'upgraded_from_groups._pageName',
            'upgraded_from_groups.set_id',
            'upgraded_from_groups.group_id',
            'upgraded_from_groups.notes',
            'upgraded_from_groups.amount',
            'upgraded_from_groups.item_name',
            'upgraded_from_groups.item_page',
        },
        {
            where=where_group,
        }
    )
    
    for _, row in ipairs(results) do
        sets[row['upgraded_from_groups._pageName'] .. tonumber(row['upgraded_from_groups.set_id'])].groups[tonumber(row['upgraded_from_groups.group_id'])] = row
    end
    
    local sets_sort = {}
    for key, _ in pairs(sets) do
        sets_sort[#sets_sort+1] = key
    end
    
    table.sort(sets_sort, function (a, b)
        return tonumber(sets[a]['upgraded_from_sets.set_id']) < tonumber(sets[b]['upgraded_from_sets.set_id'])
    end)
    
    return sets, sets_sort
end

function h.reward_table(data, rtbl)
    if #data == 0 then
        return
    end
    
    local tbl = m_quest_reward.reward_tbl_head()
            
    for _, row in ipairs(data) do
        local classes
        if row[rtbl .. '.classes'] then
            classes = {}
            for _, class in ipairs(m_util.string.split(row[rtbl .. '.classes'], '�')) do
                classes[class] = true
            end
        end
        
        local tr = tbl:tag('tr')
        m_quest_reward.reward_tbl_row_head(tr, rtbl, row)
                
        local cell = {
            [0] = {
                value = '✗',
                sort = 0,
                class = 'table-cell-xmark',
            },
            [1] = {
                value = '✓',
                sort = 1,
                class = 'table-cell-checkmark',
            },
        }
        if rtbl == 'quest_rewards' then
            local value = m_quest_reward.reward_tbl_extra_info(row)
            
            -- If there isn't any extra information the checkmark will do
            if value ~= '' then
                cell[1].value = value
                cell[1].class = nil
                cell[1].css = 'text-align: center;'
            end
        end
        
        if classes then
            for _, class in ipairs(m_game.constants.characters_order) do
                local cell_value
                if classes[class] then
                    cell_value = cell[1]
                else
                    cell_value = cell[0]
                end
                tr:tag('td')
                    :attr('class', cell_value.class or '')
                    :attr('style', cell_value.css or '')
                    :attr('table-sort-value', cell_value.sort)
                    :wikitext(cell_value.value)
            end
        else
            tr:tag('td')
                :attr('colspan', 7)
                :attr('class', cell[1].class or '')
                :attr('style', cell[1].css or '')
                :attr('table-sort-value', cell[1].sort)
                :wikitext(cell[1].value)
        end
    end
    
    return h.head(i18n.quest_reward[rtbl .. '_header']) .. i18n.quest_reward[rtbl .. '_intro'] .. tostring(tbl)
end

function h.item_link(item_pages, group)
    local str 
    if #item_pages < c.MAX_ITEMS then
        local item_data = item_pages[group['upgraded_from_groups.item_page']][1]
        str = f_item_link{
            page=group['upgraded_from_groups.item_page'], 
            name=item_data['items.name'], 
            inventory_icon=item_data['items.inventory_icon'] or '', 
            html=item_data['items.html'] or '', 
            skip_query=true
        }
    else
        str = string.format('[[%s]]', group['upgraded_from_groups.item_page'])
    end
    str = string.format('%sx %s', group['upgraded_from_groups.amount'], str)
    if group['upgraded_from_groups.notes'] then
        str = string.format('%s (%s)', str, group['upgraded_from_groups.notes'])
    end
    return str
end

-- ----------------------------------------------------------------------------
-- Templates
-- ----------------------------------------------------------------------------

local p = {}

--
-- Template: Item acquisition
--
function p.item_acquisition (frame)
    --[[
    Duplicates the information from the infobox in a more readable manner on the page.
    
    Example:
    = p.item_acquisition{page='The Rite of Elements'}
    ]]


    -- Get args
    local tpl_args = getArgs(frame, {
        parentFirst = true
    })
    frame = m_util.misc.get_frame(frame)
    
    tpl_args.page = tpl_args.page or tostring(mw.title.getCurrentTitle())
    
    local out = {}
    local results
    local query
    
    out[#out+1] = tpl_args.acquisition_insert
    
    -- ------------------------------------------------------------------------
    -- Drop restrictions by text
    -- ------------------------------------------------------------------------
    results = m_util.cargo.query(
        {'items'},
        {
            'items.drop_text',
        },
        {
            where=string.format('items._pageName="%s"', tpl_args.page),
            limit=1,
        }
    )
        
    if #results > 0 then
        results = results[1]
        if results['items.drop_text'] then
            out[#out+1] = results['items.drop_text']
        end
    end
    
    -- ------------------------------------------------------------------------
    -- Drop restrictions by area
    -- ------------------------------------------------------------------------
    
    local area_ids = m_util.cargo.query(
        {'items'},
        {'items.drop_areas__full'},
        {
            where=string.format('items._pageName="%s"', tpl_args.page),
        }
    )[1]
    if area_ids and area_ids['items.drop_areas__full'] then
        area_ids = m_util.string.split(area_ids['items.drop_areas__full'], ',')
    else
        area_ids = {}
    end
    
    local query_sets = {
        {
            header=i18n.acquisition.area_header,
            condition='areas.id NOT LIKE "MapAtlas%" AND areas.id NOT LIKE "Map2%"',
            order='areas.name ASC',
        },
        {
            header=i18n.acquisition.area_legacy_header,
            condition='areas.id LIKE "MapAtlas%" OR areas.id LIKE "Map2%"',
            order=[[
                CASE 
                    WHEN areas.id LIKE "MapAtlas%" THEN 1 
                    WHEN areas.id LIKE "Map2%" THEN 2 
                    ELSE 3 
                END ASC, 
                areas.name ASC
            ]],
        },
    }
    
    if #area_ids > 0 then
        for _, query_set in ipairs(query_sets) do
            results = m_util.cargo.query(
                {'areas'},
                {
                    'areas._pageName',
                    'areas.id',
                    'areas.name',
                    'areas.main_page',
                },
                {
                    where=string.format('(%s) AND areas.id IN ("%s")', query_set.condition, table.concat(area_ids, '","')),
                    orderBy=query_set.order,
                    groupBy='areas.id',
                }
            )
            if #results > 0 then
                local ul = mw.html.create('ul')
                for _, row in ipairs(results) do
                    ul:tag('li')
                        :wikitext(string.format('[[%s|%s]]', row['areas.main_page'] or row['areas._pageName'], row['areas.name']))
                end            
                out[#out+1] = h.head(query_set.header)
                out[#out+1] = i18n.acquisition.area
                out[#out+1]= '<br>'
                out[#out+1] = tostring(ul)
            end
        end
    end
    
    -- ------------------------------------------------------------------------
    -- Vendor recipes/upgrades handling
    -- ------------------------------------------------------------------------
    
    --
    -- Query set data
    --
    local obtained_sets, obtained_sets_order = h.fetch_upgraded_from_sets(
        string.format('upgraded_from_sets._pageName="%s"', tpl_args.page),
        string.format('upgraded_from_groups._pageName="%s"', tpl_args.page)
    )
    
    results = m_util.cargo.query(
        {'upgraded_from_groups'},
        {
            'upgraded_from_groups._pageID',
            'upgraded_from_groups.set_id',
        },
        {
            where=string.format('upgraded_from_groups.item_page="%s"', tpl_args.page),
            -- only need one result set for the where clause
            groupBy='upgraded_from_groups._pageID, upgraded_from_groups.set_id',
        }
    )
    local where = {sets={}, groups={}}
    for key, data in pairs(where) do
        for _, row in ipairs(results) do
            data[#data+1] = string.format('upgraded_from_%s.set_id="%s" AND upgraded_from_%s._pageID="%s"', key, row['upgraded_from_groups.set_id'], key, row['upgraded_from_groups._pageID'])
        end
        where[key] = table.concat(data, ' OR ')
    end
    local ingredient_sets, ingredient_sets_order = h.fetch_upgraded_from_sets(where.sets, where.groups)
    --
    -- Query bulk item info for item linking
    --
    local item_pages = {assoc={}}
    for _, set_data in ipairs({{obtained_sets, obtained_sets_order}, {ingredient_sets, ingredient_sets_order}}) do
        for _, set_key in ipairs(set_data[2]) do
            local set = set_data[1][set_key]
            for _, group in ipairs(set.groups) do
                item_pages.assoc[group['upgraded_from_groups.item_page']] = true
            end
            item_pages.assoc[set['upgraded_from_sets._pageName']] = true
        end
    end
    -- remove duplicates
    for name, _ in pairs(item_pages.assoc) do
        item_pages[#item_pages+1] = name
    end
    
    if #item_pages < c.MAX_ITEMS then
        item_pages = m_util.cargo.map_results_to_id{
            results=m_util.cargo.array_query{
                tables={'items'},
                fields={'items.name', 'items.inventory_icon', 'items.html'},
                id_array = item_pages,
                id_field = 'items._pageName',
                query = {
                    limit=5000
                },
            },
            field='items._pageName',
            keep_id_field=true,
        }
    end
    -- 
    -- Output for being obtained via vendor recipe
    --
    
    if #obtained_sets_order > 0 then
        local ul = mw.html.create('ul')
        for _, set_key in ipairs(obtained_sets_order) do
            local set = obtained_sets[set_key]
            local li = ul:tag('li')
            if set['upgraded_from_sets.text'] then
                li:wikitext(set['upgraded_from_sets.text'] .. '<br>')
            end
            
            local str = {}
            for _, group in ipairs(set.groups) do
                str[#str+1] = h.item_link(item_pages, group)
            end
            li:wikitext(table.concat(str, ', '))
        end
    
        out[#out+1] = h.head(i18n.acquisition.upgraded_from_header)
        out[#out+1] = i18n.acquisition.upgraded_from
        out[#out+1]= '<br>'
        out[#out+1] = tostring(ul)
    end
    
    -- 
    -- Ingredient of vendor recipes/upgrades
    -- 
    
    if #ingredient_sets_order > 0 then
        out[#out+1] = h.head(i18n.acquisition.ingredient_header)
        out[#out+1] = i18n.acquisition.ingredient
        out[#out+1]= '<br>'
    
        local ul = mw.html.create('ul')
        for _, set_key in ipairs(ingredient_sets_order) do
            local set = ingredient_sets[set_key]
            local li = ul:tag('li')
            
            local str = {}
            local item_data
            for _, group in ipairs(set.groups) do
                str[#str+1] = h.item_link(item_pages, group)
            end
            local il 
            if #item_pages < c.MAX_ITEMS then
                item_data = item_pages[set['upgraded_from_sets._pageName']][1]
                il = f_item_link{page=set['upgraded_from_sets._pageName'], name=item_data['items.name'], inventory_icon=item_data['items.inventory_icon'] or '', html=item_data['items.html'] or '', skip_query=true}
            else
                il = string.format('[[%s]]', set['upgraded_from_sets._pageName'])
            end
            li:wikitext(string.format('%s (%s)', il, table.concat(str, ', ')))
            if set['upgraded_from_sets.text'] then
                li:wikitext(string.format(' &#91;%s&#93;', set['upgraded_from_sets.text']))
            end
        end
        
        out[#out+1] = tostring(ul)
    end
    
    out[#out+1] = tpl_args.ingredient_append
    
    -- ------------------------------------------------------------------------
    -- Obtained via quest or vendor reward
    -- ------------------------------------------------------------------------
    
    local quest_rewards = m_util.cargo.query(
        {'quest_rewards'},
        {
            'quest_rewards.quest',
            'quest_rewards.act',
            'quest_rewards.classes',
            'quest_rewards.sockets',
            'quest_rewards.item_level',
            'quest_rewards.rarity',
        },
        {
            where=string.format('quest_rewards.reward="%s"', tpl_args.page),
            orderBy='quest_rewards.act ASC, quest_rewards.quest_id ASC',
        }
    )
    out[#out+1] = h.reward_table(quest_rewards, 'quest_rewards')
    
    local vendor_rewards = m_util.cargo.query(
        {'vendor_rewards'},
        {
            'vendor_rewards.quest',
            'vendor_rewards.act',
            'vendor_rewards.classes',
            'vendor_rewards.npc',
        },
        {
            where=string.format('vendor_rewards.reward="%s"', tpl_args.page),
            orderBy='vendor_rewards.act ASC, vendor_rewards.quest_id ASC',
        }
    )
    out[#out+1] = h.reward_table(vendor_rewards, 'vendor_rewards')
    
    -- ------------------------------------
    -- output
    -- ------------------------------------
    
    local head = mw.html.create('h2')
    head:wikitext(i18n.acquisition.header .. '[[File:Questionmark.png|right|24px|link=Path_of_Exile_Wiki:How_to_edit_item_acquisition]]')
    return tostring(head) .. table.concat(out)
end

-- ----------------------------------------------------------------------------
-- Return
-- ----------------------------------------------------------------------------

return p