Module:Item acquisition

From Path of Exile 2 Wiki
Revision as of 09:56, 13 May 2018 by >OmegaK2 (Fixed error)
Jump to navigation Jump to search
Module documentation[view] [edit] [history] [purge]


This module implements {{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 = {}

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

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

local p = {}

--
-- Template: Item acquisition
--

-- Used to duplicate the information from the infobox in a more readable manner on the page.

function p.item_acquisition (frame)
    -- 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['items.drop_areas__full'] then
        area_ids = m_util.string.split(area_ids['items.drop_areas__full'], ',')
    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 > 1 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
    
    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',
        },
        field='items._pageName',
        keep_id_field=true,
    }
    -- 
    -- 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
                local item_data = item_pages[group['upgraded_from_groups.item_page']][1]
                str[#str+1] = string.format('%sx %s', group['upgraded_from_groups.amount'], 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})
                if group['upgraded_from_groups.notes'] then
                    str[#str] = string.format('%s (%s)', str[#str], group['upgraded_from_groups.notes'])
                end
            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
                local item_data = item_pages[group['upgraded_from_groups.item_page']][1]
                str[#str+1] = string.format('%sx %s', group['upgraded_from_groups.amount'], 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})
                if group['upgraded_from_groups.notes'] then
                    str[#str] = string.format('%s [%s]', str[#str], group['upgraded_from_groups.notes'])
                end
            end
            item_data = item_pages[set['upgraded_from_sets._pageName']][1]
            li:wikitext(string.format('%s (%s)', 
                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}, 
                table.concat(str, ', ')
            ))
        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