Module:Items/ComparisonTables/Sandbox: Difference between revisions

From Melvor Idle
No edit summary
No edit summary
Line 13: Line 13:


local weaponTypes = {'Magic Staff', 'Magic Wand', 'Ranged Weapon', 'Weapon'}
local weaponTypes = {'Magic Staff', 'Magic Wand', 'Ranged Weapon', 'Weapon'}
local function getItemDesc(item)
if item.customDescription ~= nil then
return item.customDescription
elseif item.modifiers ~= nil then
return Modifiers.getModifiersText(item.modifiers, false, false)
else
return ''
end
end


local function getAttackSpeed(item)
local function getAttackSpeed(item)
Line 92: Line 82:
end
end


local function addStatCell(row, item, stat)
--== Helper Functions for getCategoryTable ==--
local statVal = 0
local function createStatCell(row, statVal)
if item.equipmentStats ~= nil then
statVal = item.equipmentStats[stat] or 0
end
local cell = row:tag('td')
local cell = row:tag('td')
if statVal > 0 then
if statVal > 0 then
Line 104: Line 91:
end
end
cell:css('text-align', 'right')
cell:css('text-align', 'right')
cell:wikitext(statVal)
return cell
return cell
end
end
local function addStatCell(row, item, stat)
local statVal = 0
if item.equipmentStats ~= nil then
statVal = item.equipmentStats[stat] or 0
end
return createStatCell(row, statVal)
:wikitext(statVal)
end
local function addDRCell(row, item)
local dr = 0
local icon = nil
-- Grab damage reduction figure
if item.equipmentStats ~= nil then
if item.equipmentStats.damageReduction then
dr, icon = item.equipmentStats.damageReduction, 'Damage Reduction'
elseif item.equipmentStats.resistance then
dr, icon = item.equipmentStats.resistance, 'Abyssal Resistance'
end
end
local cell = createStatCell(row, dr)
-- Add DR icons, if there's any value
if dr ~= 0 then
cell:wikitext(Icons.Icon({icon, size=15, notext='true'}) .. ' ')
end
-- Add DR value
cell:wikitext(dr .. '%')
return cell
end
function p._getCategoryTable(slot)
function p._getCategoryTable(slot)
local iconSize = 20
local iconSize = 20
Line 137: Line 158:
-- TODO: if abyssal switch text
-- TODO: if abyssal switch text
header0:tag('th'):wikitext("DR")
header0:tag('th'):wikitext("DR/AR")
header0:tag('th') -- Empty row above "Equip Req"
header0:tag('th') -- Empty row above "Equip Req"
Line 166: Line 187:
-- Damage reduction
-- Damage reduction
-- TODO: Check if isabyssal
header1:tag('th'):wikitext(Icons.Icon({'Damage Reduction', size=iconSize, notext='true'}))
header1:tag('th'):wikitext(Icons.Icon({'Damage Reduction', size=iconSize, notext='true'}))
--header1:tag('th'):wikitext(Icons.Icon({'Abyssal Resistance', size=iconSize, notext='true'}))
--Level requirements
--Level requirements
header1:tag('th'):wikitext('Equip Req')
header1:tag('th'):wikitext('Equip Req')
Debug.log(itemList)
-- Fill the table with all items
-- Fill the table with all items
for _, item in ipairs(itemList) do
for _, item in ipairs(itemList) do
Line 208: Line 227:
addStatCell(row, item, 'magicDefenceBonus')
addStatCell(row, item, 'magicDefenceBonus')


-- TODO: Switch Abyss
-- Add Damage Reduction / Abyssal Resistance
addStatCell(row, item, 'damageReduction'):wikitext('%') -- resistance
addDRCell(row, item)
-- TODO: Format requirements
-- TODO: Format requirements

Revision as of 11:55, 14 July 2024

Documentation for this module may be created at Module:Items/ComparisonTables/Sandbox/doc

local p = {}

local Shared = require('Module:Shared')
local GameData = require('Module:GameData')
local Common = require('Module:Common')
local Modifiers = require('Module:Modifiers')
local Icons = require('Module:Icons')
local Items = require('Module:Items')
local Num = require('Module:Number')


local Debug = require('Module:Debug')

local weaponTypes = {'Magic Staff', 'Magic Wand', 'Ranged Weapon', 'Weapon'}

local function getAttackSpeed(item)
	if item.equipmentStats ~= nil and item.equipmentStats['attackSpeed'] ~= nil then
		return item.equipmentStats['attackSpeed'] or 4000
	end
	return 0
end

local function getSlotID(slot)
	-- If slot is a slot name, convert it to the slot ID instead
	local slotID = Shared.getNamespacedID('melvorD', slot)
	local slotData = GameData.getEntityByID('equipmentSlots', slotID)
	-- Validate slotID
	if slotData == nil then
		-- slotID invalid, check if user provided a slot name
		slotData = GameData.getEntityByProperty('equipmentSlots', 'emptyName', slot)
		if slotData == nil then
			return nil
		end
		slotID = slotData.id
	end
	return slotID
end

local function getItems(slotID)
	local slotNS, slotLocalID = Shared.getLocalID(slotID)
	
	local sortFunc = function(item)
		-- Exclude the debug item
		if item.id == 'melvorD:DEBUG_ITEM' then
			return false
		end
		-- Exclude Golbin raid exclusives for now, such that they don't pollute various equipment tables
		if item.golbinRaidExclusive ~= nil and item.golbinRaidExclusive then
			return false
		end
		
		local isMatch = true
		local sID = slotLocalID
		if not Shared.contains(item.validSlots, sID) then 
			isMatch = false 
		end
		
		if isMatch and other ~= nil then
			if slot == 'Cape' then
				-- TODO Would be more reliable if based on items appearing within the relevant shop categories instead
				local isSkillcape = Shared.contains(item.name, 'Skillcape') or Shared.contains(item.name, 'Cape of Completion')
				if other == 'Skillcapes' then
					isMatch = isSkillcape
				elseif other == 'No Skillcapes' then
					isMatch = not isSkillcape
				end
			end
			if slotLocalID == 'Weapon' then --For quiver slot or weapon slot, 'other' is the ammo type
				isMatch = other == item.ammoTypeRequired
			elseif slotLocalID == 'Quiver' then
				if other == 'Thrown' and Shared.contains({'Javelins', 'ThrowingKnives'}, item.ammoType) then
					isMatch = true
				else
					isMatch = other == item.ammoType
				end
			end
		end
		return isMatch
	end

	return Items.getItems(sortFunc)
end

--== Helper Functions for getCategoryTable ==--
local function createStatCell(row, statVal)
	local cell = row:tag('td')
	if statVal > 0 then
		cell:addClass('table-positive')
	elseif statVal < 0 then
		cell:addClass('table-negative')
	end
	cell:css('text-align', 'right')
	return cell
end

local function addStatCell(row, item, stat)
	local statVal = 0
	if item.equipmentStats ~= nil then
		statVal = item.equipmentStats[stat] or 0
	end
	
	return createStatCell(row, statVal)
		:wikitext(statVal)
end

local function addDRCell(row, item)
	local dr = 0
	local icon = nil
	
	-- Grab damage reduction figure
	if item.equipmentStats ~= nil then
		if item.equipmentStats.damageReduction then
			dr, icon = item.equipmentStats.damageReduction, 'Damage Reduction'
		elseif item.equipmentStats.resistance then
			dr, icon = item.equipmentStats.resistance, 'Abyssal Resistance'
		end
	end
	
	local cell = createStatCell(row, dr)
	
	-- Add DR icons, if there's any value
	if dr ~= 0 then
		cell:wikitext(Icons.Icon({icon, size=15, notext='true'}) .. ' ')
	end
	
	-- Add DR value
	cell:wikitext(dr .. '%')
	return cell
end

function p._getCategoryTable(slot)
	local iconSize = 20
	local slotID = getSlotID(slot)
	if slotID == nil then
		return Shared.printError('Invalid slot ID: ' .. (slot or 'nil'))
	end
	
	-- Always sort by name.
	local itemList = getItems(slotID)
	table.sort(itemList, function(a, b) return a.name < b.name end)
	
	local isWeapon = (slot == 'Weapon')
	local itemColspan = 3
	if isWeapon == true then itemColspan = 4 end
	
	local html = mw.html.create('table')
		:addClass('wikitable sortable stickyHeader')
		:addClass('col-1-center col-3-center')

	local header0 = html:tag('tr'):addClass('headerRow-0')
	header0:tag('th'):attr('colspan', itemColspan)
	header0:tag('th'):attr('colspan', 5)
					 :wikitext("Attack Bonus")
	header0:tag('th'):attr('colspan', 3)
					 :wikitext("Strength Bonus")
	header0:tag('th'):attr('colspan', 3)
					 :wikitext("Defence Bonus")
	
	-- TODO: if abyssal switch text
	header0:tag('th'):wikitext("DR/AR")
	header0:tag('th') -- Empty row above "Equip Req"
	
	local header1 = html:tag('tr'):addClass('headerRow-1')
	header1:tag('th'):wikitext('Name')
					 :attr('colspan', 2)
	header1:tag('th'):wikitext('DLC')
	if isWeapon == true then
		header1:tag('th'):wikitext('Attack<br>Speed')
	end

	-- Attack bonuses
	header1:tag('th'):wikitext(Icons.Icon({'Attack', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Strength', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Defence', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Ranged', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Magic', type='skill', size=iconSize, notext='true'}))

	--Strength bonuses
	header1:tag('th'):wikitext(Icons.Icon({'Strength', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Ranged', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Magic', type='skill', size=iconSize, notext='true'}))

	--Defence bonuses
	header1:tag('th'):wikitext(Icons.Icon({'Strength', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Ranged', type='skill', size=iconSize, notext='true'}))
	header1:tag('th'):wikitext(Icons.Icon({'Magic', type='skill', size=iconSize, notext='true'}))
	
	-- Damage reduction
	header1:tag('th'):wikitext(Icons.Icon({'Damage Reduction', size=iconSize, notext='true'}))
	
	--Level requirements
	header1:tag('th'):wikitext('Equip Req')
	Debug.log(itemList)
	-- Fill the table with all items
	for _, item in ipairs(itemList) do
		local row = html:tag('tr')
		row:tag('td'):wikitext(Icons.Icon({item.name, type='item', notext=true}))
					 :attr('data-sort-value', item.name)
		row:tag('td'):wikitext(Icons.Icon({item.name, type='item', noicon=true}))
					 :attr('data-sort-value', item.name)
		row:tag('td'):wikitext(Icons.getDLCColumnIcon(item.id))
					 :attr('data-sort-value', Icons.getExpansionID(item.id))

		-- Add attack speed.
		if isWeapon == true then
			local atkSpeed = getAttackSpeed(item)
			row:tag('td'):wikitext(Num.round(atkSpeed / 1000, 3, 1) .. 's')
						 :attr('data-sort-value', atkSpeed)
						 :css('text-align', 'right')
		end
		
		-- Attack bonuses
		addStatCell(row, item, 'stabAttackBonus')
		addStatCell(row, item, 'slashAttackBonus')
		addStatCell(row, item, 'blockAttackBonus')
		addStatCell(row, item, 'rangedAttackBonus')
		addStatCell(row, item, 'magicAttackBonus')
		
		-- Strength bonuses
		addStatCell(row, item, 'meleeStrengthBonus')
		addStatCell(row, item, 'rangedStrengthBonus')
		addStatCell(row, item, 'magicDamageBonus'):wikitext('%')	

		-- Defence bonuses
		addStatCell(row, item, 'meleeDefenceBonus')
		addStatCell(row, item, 'rangedDefenceBonus')
		addStatCell(row, item, 'magicDefenceBonus')

		-- Add Damage Reduction / Abyssal Resistance
		addDRCell(row, item)
	
		-- TODO: Format requirements
		row:tag('td'):wikitext('None')
		--'attackLevelRequired', 'strengthLevelRequired', 
		--'defenceLevelRequired', 'rangedLevelRequired', 'magicLevelRequired',
		--'attackAbyssalLevel', 'strengthAbyssalLevel','defenceAbyssalLevel',
		--'rangedAbyssalLevel', 'magicAbyssalLevel'		
	end

	return tostring(html)
end

-- TODO:
--- Split Melvor / Abyss items (based on realm?)
--- Split 1h and 2h weapons
--- When the category is 'Weapon', include every wieldable items (incl knives, javs, etc)
function p.getCategoryTable(frame)
	local slot = frame.args ~= nil and frame.args[1] or frame[1]

	return p._getCategoryTable(slot)
end

return p