Module:Equipment/Recommended

From Melvor Idle
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Documentation for this module may be created at Module:Equipment/Recommended/doc

-- Adapted from: https://oldschool.runescape.wiki/w/Module:Recommended_equipment
-- Released under: https://creativecommons.org/licenses/by-nc-sa/3.0/ 

local p = {}

local Params = require('Module:Shared/Paramtest')
local Shared = require('Module:Shared')
local Icons = require("Module:Icons")

local slots = {
	{ placement = 1, name = 'helm', icon = 'Slot_head', txt = 'Helmet', link = 'Helmets' },
	{ placement = 2, name = 'body', icon = 'Slot_chest', txt = 'Platebody', link = 'Platebodies' },
	{ placement = 3, name = 'legs', icon = 'Slot_legs', txt = 'Platelegs', link = 'Platelegs' },
	{ placement = 4, name = 'boots', icon = 'Slot_feet', txt = 'Boots', link = 'Boots' },
	{ placement = 5, name = 'gloves', icon = 'Slot_hands', txt = 'Gloves', link = 'Gloves' },
	
	{ placement = 6, name = 'cape', icon = 'Slot_back', txt = 'Cape', link = 'Capes' },
	{ placement = 7, name = 'neck', icon = 'Slot_neck', txt = 'Amulet', link = 'Amulets' },
	{ placement = 8, name = 'ring', icon = 'Slot_ring', txt = 'Ring', link = 'Rings' },
	{ placement = 9, name = 'gem', icon = 'Slot_gem', txt = 'Gem', link = 'Gems (Equipment)' },
	
	{ placement = 10, name = 'weapon', icon = 'Slot_weapon', txt = 'Weapon', link = 'Weapons' },
	{ placement = 11, name = 'shield', icon = 'Slot_shield', txt = 'Offhand', link = 'Shields' },
	{ placement = 12, name = 'ammo', icon = 'Slot_ammo', txt = 'Quiver', link = 'Ammunition' },
	
	{ placement = 13, name = 'passive', icon = 'Slot_passive', txt = 'Passive', link = 'Combat Passive Slot', hasStats = false },
	{ placement = 14, name = 'consumable', icon = 'Slot_consumable', txt = 'Consumable', link = 'Consumables' },
	{ placement = 15, name = 'familiar1', icon = 'Slot_summon', txt = 'Familiar Left', link = 'Summoning' },
	{ placement = 16, name = 'familiar2', icon = 'Slot_summon', txt = 'Familiar Right', link = 'Summoning' },
	{ placement = 17, name = 'prayer1', icon = 'Slot_prayer', txt = 'Prayer1', link = 'Prayer', icontype = 'prayer' },
	{ placement = 18, name = 'prayer2', icon = 'Slot_prayer', txt = 'Prayer2', link = 'Prayer', icontype = 'prayer' },
	
	{ placement = 99, name = 'notes', icon = '', txt = 'Notes', link = '', hasStats = false }
}

function p.main(frame)
	local args = frame:getParent().args	
	-- Dynamic colspan and N/A generation value
	local greatest_row_size = 0
	-- Number of choices each slot can have
	local number_of_possible_choices = 5
	-- Have to sort this table or else the order is messed up when you use it
	table.sort(slots, function(a, b) return a.placement < b.placement end)
	
	local showDR = args.showDR ~= nil and string.lower(args.showDR) == 'true'
	local Items, statTotal = nil, 0
	if showDR then
		-- Include the Items module here if necessary, avoids loading the data
		-- if the template does not require it
		Items = require('Module:Items')
	end
	local imgSize = 36
	if args.imgSize ~= nil and tonumber(args.imgSize) ~= nil then
		imgSize = math.max(0, tonumber(args.imgSize))
	elseif showDR then
		imgSize = 25
	end
	
	local function make_row(slot, data, compact)
		local tr = mw.html.create('tr')
		local sloticon = tr:tag('td')
		sloticon:attr('style', 'text-align: center')
			:wikitext(string.format('[[File:%s.png|%s|link=%s|%spx]]', slot.icon, slot.txt, slot.link, imgSize))
		if compact then
			sloticon:attr('style', 'padding-bottom: 4px;')
		end
		for _, v in ipairs(data) do
			local itemIcon = nil
			local isPlain = type(string.find(v, '!', 1, true)) == 'number'
			if isPlain then
				-- ! prefix, treat as plain text
				itemIcon = string.sub(v, 2, -1)
			else
				-- Otherwise treat as an item icon
				local icontype = slot.icontype or 'item'
				itemIcon = Icons.Icon({v, img=v, type=icontype})
			end
			local gearname = tr:tag('td'):wikitext(itemIcon)
			if compact then
				gearname:attr('style', 'padding-left: 12px;')
			end
			-- Attempt to obtain DR value if requested
			if showDR then
				local hasStats = true
				if slot.hasStats ~= nil then
					hasStats = slot.hasStats
				end
				local statValue = 0
				if hasStats and not isPlain and Items ~= nil then
					local item = Items.getItem(v)
					if item ~= nil then
						statValue = Items._getItemStat(item, 'damageReduction', true)
					end
				end
				statTotal = statTotal + statValue
				tr:tag('td'):wikitext(statValue .. '%')
			end
		end
		
		-- If the data size is smaller than GRS, then we need to fill up the remaining td's with N/As
		if #data < greatest_row_size then
			local difference = greatest_row_size - #data
			tr:tag('td'):attr('colspan', difference):attr("class", ".dimmed")
		end
		return tr
	end
	
	-- Find the greatest row count
	for _, v in next, slots, nil do
		local grs = 0
		for i = 1, number_of_possible_choices, 1 do
			local check = args[v.name .. i]
			if check and Params.has_content(check) then
				grs = grs + 1	
			end
		end
		
		if greatest_row_size < grs then
			greatest_row_size = grs	
		end
	end
	
	if showDR and greatest_row_size > 1 then
		-- showDR option is only compatible if a single column of equipment is to be displayed
		return Shared.printError('showDR option is incompatible with more than one item per slot')
	end
	
	local parent = mw.html.create('table')
	-- If setname is passed in, apply it above the table
	if args.setname and Params.has_content(args.setname) then
		parent:tag('caption'):wikitext(string.format('Recommended equipment for %s', args.setname))
	end

	local compact = true
	if args.noheader == nil then
		local itemHeader = (greatest_row_size > 1 and 'Item (most effective → least effective)') or 'Item'
		compact = false
		parent:addClass('wikitable stickyHeader')
		local trHead = parent:tag('tr')
		trHead:addClass('headerRow-0')
			:tag('th'):wikitext('Slot'):done()
			:tag('th'):attr('colspan', greatest_row_size):wikitext(itemHeader):done()
		if showDR then
			trHead:tag('th'):wikitext('DR%'):done()
		end
	end
		
	for _, v in next, slots, nil do
		local row_data = {}
		for i = 1, number_of_possible_choices, 1 do
			local gear = args[v.name .. i]
			if gear and Params.has_content(gear) then
				table.insert(row_data, gear)
			end
		end

		if #row_data > 0 or args.showall then
			parent:node(make_row(v, row_data, compact))
		end
	end
	
	if showDR then
		-- Total row for displayed stat
		parent:tag('tr')
			:tag('th'):attr('colspan', 1 + greatest_row_size):wikitext('Total'):done()
			:tag('td'):wikitext(statTotal .. '%'):done()
			:done()
	end
	
	return tostring(parent) .. '\r\n[[Category:Pages with Equipment Recommendations]]'
end

function p.synergy(frame)
	local args = frame:getParent().args
	-- local args = frame.args
	-- mw.logObject(args)
	local left_summon = slots[13]
	local right_summon = slots[14]
	local summon_icon = string.format('[[File:%s.png|Summon|24px]]', right_summon.icon)
	local notes = slots[15]
	local number_of_possible_choices = 5
	
	local rows = {}
	local header_row = {}
	local header_style = '!style="padding-right: 3em; padding-left: 3em; text-align: center;" |'
	table.insert(header_row, summon_icon .. ' Left')
	table.insert(header_row, summon_icon .. ' Right')
	table.insert(header_row, 'Notes')
	
	table.insert(rows, '{| class="wikitable col-1-center col-2-center"')
	table.insert(rows, header_style .. table.concat(header_row, '\r\n'..header_style))
	
	local function make_gear_cell(name)
		if name then
			return '| ' .. Icons.Icon({name, img=name, type='item'})
		else
			return '| ' .. summon_icon
		end
	end
	
	-- first we create tables for left and right side making sure left[i] and right[i] correspond
	-- could generate the rows in one go, but eh
	local lefties = {}
	local righties = {}
	local notes = {}
	
	local number_rows = 0
	
	for i = 1, number_of_possible_choices, 1 do
		local left = args[left_summon.name .. i]
		table.insert(lefties, make_gear_cell(left))
		
		local right = args[right_summon.name .. i]
		table.insert(righties, make_gear_cell(right))
		
		local note = args['notes' .. i]
		table.insert(notes, note or '')
		
		if left or right or note then
			number_rows = number_rows + 1
		end
	end
	
	-- then we create all the rows by formatting them
	for i = 1, number_rows, 1 do
		local row = {}
		table.insert(row, lefties[i])
		table.insert(row, righties[i])
		table.insert(row, '| ' .. notes[i])
		
		table.insert(rows, table.concat(row, "\r\n"))
	end
	
	return table.concat(rows, '\r\n|-\r\n') .. '\r\n|}\r\n[[Category:Pages with Equipment Recommendations]]'

end

function p.test()
	return p.synergy({ args = { familiar11 = 'Crow',
								familiar21 = 'Devil',
								familiar12 = 'Crow',
								familiar22 = 'Octopus',
								familiar13 = 'Crow',
								familiar23 = 'Bear',
						}} )
end

return p