Module:Items

From Predecessor Wiki
Jump to navigation Jump to search
Template-noinfo.svg Documentation
This module has no documentation. If you know how to use this module, please add some. Module:Items/doc

local p = {}

local items = mw.loadData('Module:Items/data')
local getArgs = require('Module:Arguments').getArgs
local getter = require('Module:Items/getter')
local builder = require("Module:SimpleHTMLBuilder")
local IL = require('Module:ImageLink')
local lib = require('Module:Feature')

function p.get(frame)
    local args = getArgs(frame)
    
    local get = require ('Module:Items/getter')
    args['itemname'] = args['itemname'] or args[1]
    args['datatype'] = args['datatype'] or args[2]
    args['output'] = args['output'] or args[3] or nil
    
    local resultGet = get[args['datatype']]
    local result
    if resultGet then
    	result = resultGet(args['itemname'])
    end

    if args['output'] ~= nil and type(result) == "table" then
        if args['output'] == "csv" then
            return lib.tbl_concat{result}
        elseif args['output'] == "custom" then 
            return frame:preprocess(lib.tbl_concat{result, prepend = args['prepend'], append = args['append'], separator = args['separator'], index = args["index"]})
        elseif args['output'] == "template" then 
            return frame:preprocess(lib.tbl_concat{result, prepend = "{{" .. args['t_name'] .. "|", append = "}}", separator = args['separator']})
        elseif args['output'] == "category" then 
            return frame:preprocess(lib.tbl_concat{result, prepend = "[[Category:" .. (args['prepend'] or ""), append = (args['append'] or "") .. "]]", separator = args['separator'] or " "})
        end
    elseif result == nil then
        return ""
    else
        return result
    end
end

function p.getInfobox(frame)
	local args = require( 'Module:ProcessArgs' ).merge( true )
	local item = args['item'] or args[1]
	return frame:expandTemplate{title = "Item/infobox", args = {
		-- Main
		['title'] = item,
		['image'] = getter.image(item),
		-- Information
		['tier'] = getter.tier(item),
		['class'] = getter.class(item),
		['type'] = getter.type(item),
		['slot'] = getter.slot(item),
		['benefit'] = getter.benefit(item),
		['requiredlevel'] = getter.requiredlevel(item),
		-- Cost
		['buy'] = getter.buy(item),
		['sell'] = getter.sell(item),
		-- Statistics
		['abilityhaste'] = getter.abilityhaste(item),
		['attackspeed'] = getter.attackspeed(item),
		['criticalchance'] = getter.criticalchance(item),
		['goldpersecond'] = getter.goldpersecond(item),
		['healshieldincrease'] = getter.healshieldincrease(item),
		['healthregeneration'] = getter.healthregeneration(item),
		['lifesteal'] = getter.lifesteal(item),
		['magicalarmor'] = getter.magicalarmor(item),
		['magicallifesteal'] = getter.magicallifesteal(item),
		['magicalpenetration'] = getter.magicalpenetration(item),
		['magicalpower'] = getter.magicalpower(item),
		['manaregeneration'] = getter.manaregeneration(item),
		['maxhealth'] = getter.maxhealth(item),
		['maxmana'] = getter.maxmana(item),
		['movementspeed'] = getter.movementspeed(item),
		['omnivamp'] = getter.omnivamp(item),
		['physicalarmor'] = getter.physicalarmor(item),
		['physicalpenetration'] = getter.physicalpenetration(item),
		['physicalpower'] = getter.physicalpower(item),
		['tenacity'] = getter.tenacity(item),
	}}
end

function p.getCategories(frame)
	local args = getArgs(frame)
	local item = args['item'] or args[1]
	return frame:expandTemplate{title = "Item/categories", args = { item }}
end

function p.getList(frame)
	return builder.create('div')
		:addClass('mw-collapsible')
		:wikitext('<h2>List of Items</h2>')
		:tag('div')
			:addClass('mw-collapsible-content')
			:wikitext(frame:expandTemplate{title = 'Item/list'})
			:done()
		:done()
end
function p.buildList(frame)
	local list = ''
	local remlist = ''

	for k,v in p.pairsByAlphabeticalKeys(items) do
		if not getter.removed(k) then
			list = list .. tostring(_buildListItem(k))
		else
			remlist = remlist .. tostring(_buildListItem(k))
		end
	end
	return list .. '\n<dl><dt>Removed Items</dt></dl>\n' .. remlist
end

function _buildListItem(item)
	local search = item
	local slot = ''
	local tier = ''
	local type = ''
	local class = ''
	
	if getter.slot(item) then
		slot = getter.slot(item) 
	end
	if getter.tier(item) then
		tier = getter.tier(item)
	end
	if getter.type(item) then
		type = getter.type(item)
	end
	if getter.class(item) then
		class = getter.class(item)
	end
	
	return builder.create('div')
		:addClass('module-items__icon')
		:cssText('display: inline-block; margin: 1px;')
		:attr('data-search', search)
		:attr('data-slot', slot)
		:attr('data-tier', 'tier-' .. tier)
		:attr('data-type', type)
		:attr('data-class', class)
		:node(IL.item({['item'] = item, ['showlabel'] = 'false', ['size'] = '40px'}))
end

function p.getEffects(frame)
	local args = getArgs(frame)
	local item = args['item'] or args[1]
	local effects = getter.effects(item)
	if not effects then
		return
	else
		local grid = builder.create('div')
		local a = _createEffect(item, 'active') or ''
		local p = _createEffect(item, 'passive') or ''
		local p2 = _createEffect(item, 'passive2') or ''
		local p3 = _createEffect(item, 'passive3') or ''
		grid
			:addClass('template-effect__grid')
			:wikitext(frame:preprocess(a .. p .. p2 .. p3))
			:done()
		return grid
	end
end
function _createEffect(item, type)
	local effect = getter[type](item)
	if effect then
		local currentFrame = mw.getCurrentFrame()
		local effName = effect.name
		local effDesc = effect.description
		local effCD = effect.cooldown
		local effCond = effect.condition
		
		local active = ''
		if type == 'active' then active = 'true' end
		
		return currentFrame:expandTemplate{title = "Item/effect", args = {
			['name'] = effName,
			['description'] = effDesc,
			['cooldown'] = effCD,
			['condition'] = effCond,
			['active'] = active
		}}
	end
end
function p.getRecommended(frame)
    local args = getArgs(frame)
    local item = args['item'] or args[1]
    local IL = require('Module:ImageLink')
    local recommendedfor = getter.recommendedfor(item)
    if not recommendedfor then
        return
    else
        local result = ''
        local currentFrame = mw.getCurrentFrame()
        
        local recList = builder.create()

        local sortedRec = {}
        for i,v in ipairs(recommendedfor) do
            table.insert(sortedRec, v)
        end
        table.sort(sortedRec, function(a, b) return a:lower() < b:lower() end)
        
        for i,v in ipairs(sortedRec) do
            result = result .. tostring(IL.hero({['hero'] = v})) .. '<br>'
        end
        recList
            :wikitext(result)
            :done()
        return recList
    end
end

function p.getBuilds(frame)
    local args = getArgs(frame)
    local item = args['item'] or args[1]
    local IL = require('Module:ImageLink')
    local builds = getter.buildsinto(item)
    if not builds then
        return
    else
        local result = ''

        local buildList = builder.create('div')
        buildList:cssText('display: flex; flex-direction: column; flex-wrap: wrap;')
        
        local sortedBuilds = {}
        for i,v in ipairs(builds) do
            table.insert(sortedBuilds, v)
        end
        table.sort(sortedBuilds, function(a, b) return a:lower() < b:lower() end)
        
        for i,v in ipairs(sortedBuilds) do
            result = result .. tostring(IL.item({item = v}))
        end
        buildList
            :wikitext(result)
            :done()
        return buildList
    end
end

function p.getRecipeTree(frame)
	local args = getArgs(frame)
	local item = args.item or args[1]
	if getter.recipe(item) then
		return tostring(_buildRecipeTree(args))
	end
end

function _buildRecipeTree(frame)
	local args = getArgs(frame)
	local item = args.item or args[1]
	local recipe = getter.recipe(item) or nil
	
    local tableNode = builder.create('table')
    tableNode:css('border-collapse', 'collapse'):newline()
    local tableRow = builder.create('tr')
    tableRow
        :tag('td')
            :attr('colspan', '3')
            :css('padding-left', '0px')
            :node(_buildRecipeTreeItem{item})
            :done()
        :done()
    
    tableNode:node(tableRow):newline()
    
    if(recipe == nil) then 
        tableNode:allDone()
        return tableNode
    end
    local num_components = 0
    for k in ipairs(recipe) do num_components = num_components + 1 end
    
    local firstComponentRow = builder.create('tr')
    firstComponentRow
        :tag('td')
            :attr('rowspan', tostring(num_components * 2 - 1))
            :cssText('width:10px;border-right:1px solid var(--border-color-base);')
            :done()
        :tag('td')
            :cssText('height:14px; width:17px; border-bottom:1px solid var(--border-color-base);')
            :done()
        :tag('td')
            :attr('rowspan', '2')
            :node(_buildRecipeTree{recipe[1]})
            :done()
        :done()
    tableNode:node(firstComponentRow)
    
    for i, v in ipairs(recipe) do
        if(i ~= 1) then
            tableNode
                :tag('tr')
                    :tag('td')
                        :done()
                    :done()
                :newline()
            local recipeRow = builder.create('tr')
            recipeRow
                :tag('td')
                    :cssText('height:14px; width:17px; border-bottom:1px solid var(--border-color-base);')
                    :done()
                :tag('td')
                    :attr('rowspan', '2')
                    :node(_buildRecipeTree{v})
                    :done()
                :done()
            tableNode:node(recipeRow):newline()
        end
    end
    tableNode
        :tag('tr')
            :tag('td')
                :done()
            :tag('td')
                :done()
            :done()
    
    tableNode:allDone()
    return tableNode
end

function _buildRecipeTreeItem(frame)
    local args = getArgs(frame)
	local item = args.item or args[1]
    local itemNode	= builder.create('span')
    	:node(IL.item{['item'] = item, ['size'] = '20px'})
    	if getter.buy(item) then
    		itemNode
    			:wikitext('&nbsp;&nbsp;')
    			:wikitext(_getCost(item))
    	end
    	itemNode:done()
    itemNode:allDone()
    
    return itemNode
end
function _getCost(item)
	local currentFrame = mw.getCurrentFrame()
	local cost = ""
    if not (getter.buy(item) == 0) then
        cost = cost .. currentFrame:expandTemplate{title = "Gold", args = {getter.buy(item), size = '12px'}}
    end
	if getter.combine(item) and getter.combine(item) ~= 0 then
	       	cost = cost .. "&nbsp;<span style='font-size:var(--font-size-x-small); color: var(--pred-gold);'>(" .. currentFrame:expandTemplate{title = "Gold", args = {getter.combine(item), size = '12px'}} .. ')</span>'
	end

    if cost == "" then
    	return currentFrame:expandTemplate{title = "Gold", args = {'0', size = '12px'}}
    end
    return cost
end


-- Returns an iterator over keys sorted alphabetically
-- https://www.lua.org/pil/19.3.html
function p.pairsByAlphabeticalKeys(t, f)
    local a = {}
	local a_len = 0
    for n in pairs(t) do 
    	a_len = a_len + 1
    	a[a_len] = n
    end
    table.sort(a, f)
    local i = 0      -- iterator variable
    local iter = function ()   -- iterator function
        i = i + 1
        if a[i] == nil then
        	return nil
        end
        return a[i], t[a[i]]
	end

    return iter
end

return p