Module:Skills/Summoning

From Melvor Idle
< Module:Skills
Revision as of 14:45, 5 March 2022 by Auron956 (talk | contribs) (Fix Summoning non-shard item cost quantity)

Documentation for this module may be created at Module:Skills/Summoning/doc

local p = {}

local ItemData = mw.loadData('Module:Items/data')
local SkillData = mw.loadData('Module:Skills/data')

local Constants = require('Module:Constants')
local Shared = require('Module:Shared')
local Items = require('Module:Items')
local Icons = require('Module:Icons')

function p.getFamiliars()
  return Items.getItems(function(item) return item.type == "Familiar" end)
end

function p.getMarkTable(frame)
  local result = ''
  result = result..'{| class="wikitable sortable stickyHeader"'
  result = result..'\r\n|- class="headerRow-0"'
  result = result..'\r\n!colspan="2"|Mark!!'..Icons.Icon({'Summoning', type='skill', notext=true})..' Level'
  result = result..'!!Discovered in'

  local Familiars = {}
  for i, recipe in ipairs(SkillData.Summoning.Marks) do
	  table.insert(Familiars, recipe)
  end
  table.sort(Familiars, function(a, b)
                          if a.level == b.level then
                            return a.masteryID < b.masteryID
                          else
                            return a.level < b.level
                          end
                        end)

  local rowArray = {}
  for i, Fam in ipairs(Familiars) do
	local item = Items.getItemByID(Fam.itemID)
	if item ~= nil then
	    local rowText = '|-'
	    rowText = rowText..'\r\n|data-sort-value="'..item.name..'"|'..Icons.Icon({item.name, type='mark', notext=true, size='50'})
	    rowText = rowText..'||'..Icons.Icon({item.name, 'Mark of the ' .. item.name, type='mark', noicon=true})
	    rowText = rowText..'||style="text-align:right"|'..Fam.level
	    local discoveredArray = {}
	    for j, SkillID in Shared.skpairs(Fam.skills) do
	      table.insert(discoveredArray, Icons.Icon({Constants.getSkillName(SkillID), type='skill'}))
	    end
	    rowText = rowText..'||'..table.concat(discoveredArray, '<br/>')
	    table.insert(rowArray, rowText)
	end
  end

  result = result..'\r\n'..table.concat(rowArray, '\r\n')

  result = result..'\r\n|}'
  return result
end

function p.getTabletTable(frame)
  local result = ''
  result = result..'{| class="wikitable sortable stickyHeader"'
  result = result..'\r\n|- class="headerRow-0"'
  result = result..'\r\n!colspan="2"|Name!!'..Icons.Icon({'Summoning', type='skill', notext=true})..' Level'
  result = result..'!!Tier!!Effect!!' .. Icons.Icon({'Melee', notext=true, nolink=true}) .. ' Max Hit!!Description!!Shard Cost!!Secondary!!Creation XP'

  local Familiars = {}
  for i, recipe in ipairs(SkillData.Summoning.Marks) do
	  table.insert(Familiars, recipe)
  end
  table.sort(Familiars, function(a, b)
                          if a.level == b.level then
                            return a.masteryID < b.masteryID
                          else
                            return a.level < b.level
                          end
                        end)

  local rowArray = {}
  for i, Fam in ipairs(Familiars) do
	local item = Items.getItemByID(Fam.itemID)
	if item ~= nil then
	    local maxHit, maxHitText = Items._getItemStat(item, 'summoningMaxhit'), ''
	    if maxHit ~= nil then
	      maxHit = maxHit * 10
	      maxHitText = 'style="text-align:right"; data-sort-value="' .. maxHit .. '"|' .. Shared.formatnum(maxHit)
	    end
	    local rowText = '|-'
	    rowText = rowText..'\r\n|data-sort-value="'..item.name..'"|'..Icons.Icon({item.name, type='item', notext=true, size='50'})
	    rowText = rowText..'||'..Icons.Icon({item.name, type='item', noicon=true})
	    rowText = rowText..'||style="text-align:right"|'..Fam.level
	    rowText = rowText..'||style="text-align:right"|'..Fam.tier
	    rowText = rowText..'||'..item.description..'||'..maxHitText..'||'..Fam.description

		-- Create item requirements text
		local ShardCostArray, OtherCostArray = {}, {}
		-- Shards
		for j, cost in ipairs(Fam.itemCosts) do
			local shard = Items.getItemByID(cost.id)
			if shard ~= nil then
				table.insert(ShardCostArray, Icons.Icon({shard.name, type='item', notext=true, qty=cost.qty}))
			end
		end
		rowText = rowText..'||style="text-align:right"|'..table.concat(ShardCostArray, ', ')..'&nbsp;'

		-- Other costs
		local recipeGPCost = SkillData.Summoning.RecipeGPCost
		if Fam.gpCost > 0 then
			table.insert(OtherCostArray, Icons.GP(Fam.gpCost))
		end
		if Fam.scCost > 0 then
			table.insert(OtherCostArray, Icons.SC(Fam.scCost))
		end
		for j, nonShardID in ipairs(Fam.nonShardItemCosts) do
			local nonShard = Items.getItemByID(nonShardID)
			if nonShard ~= nil then
				local itemValue = math.max(nonShardItem.sellsFor, 20)
				local nonShardQty = math.max(1, math.floor(recipeGPCost / itemValue))
				table.insert(OtherCostArray, Icons.Icon({nonShard.name, type='item', notext=true, qty=nonShardQty}))
			end
		end
		rowText = rowText..'||style="text-align:right"|'..table.concat(OtherCostArray, "<br/>'''OR''' ")

		rowText = rowText..'||style="text-align:right"|'..Fam.baseXP

	    table.insert(rowArray, rowText)
	end
  end

  result = result..'\r\n'..table.concat(rowArray, '\r\n')

  result = result..'\r\n|}'
  return result
end

function p.getSynergyTable(frame)
  local result = ''
  result = result..'{| class="wikitable sortable stickyHeader"'
  result = result..'\r\n|- class="headerRow-0"'
  result = result..'\r\n!colspan="2"|Familiar 1!!colspan="2"|Familiar 2!!Effect!!Requirements'

  local synergyList = {}
  for i, syn in ipairs(SkillData.Summoning.Synergies) do
	  table.insert(synergyList, syn)
  end
  table.sort(synergyList, function (a, b) return (a.summons[1] == b.summons[1] and a.summons[2] < b.summons[2]) or a.summons[1] < b.summons[1] end)

  local marksByID, famNames = {}, {}
  for i, recipe in ipairs(SkillData.Summoning.Marks) do
	  marksByID[recipe.masteryID] = recipe
	  local item = Items.getItemByID(recipe.itemID)
	  if item ~= nil then
	  	famNames[recipe.masteryID] = item.name
	  end
  end

  local rowArray = {}
  for i, syn in ipairs(synergyList) do
	local Fam1 = marksByID[syn.summons[1]]
	local Fam2 = marksByID[syn.summons[2]]
	if Fam1 ~= nil and Fam2 ~= nil then
      local FamName1 = famNames[Fam1.masteryID] or 'Unknown'
	  local FamName2 = famNames[Fam2.masteryID] or 'Unknown'
      local rowText = '|-'
      rowText = rowText..'\r\n|data-sort-value="'..FamName1..'"|'..Icons.Icon({FamName1, type='item', notext=true, size='30'})
      rowText = rowText..'||'..Icons.Icon({FamName1, type='item', noicon=true})
      rowText = rowText..'||data-sort-value="'..FamName2..'"|'..Icons.Icon({FamName2, type='item', notext=true, size='30'})
      rowText = rowText..'||'..Icons.Icon({FamName2, type='item', noicon=true})
      rowText = rowText..'||'..syn.description

      local reqArray = {}
      local reqLvl = math.max(Fam1.level, Fam2.level)
      table.insert(reqArray, Icons._SkillReq('Summoning', reqLvl))
      table.insert(reqArray, FamName1..' Mark Level '..(Fam2.tier + 1))
      table.insert(reqArray, FamName2..' Mark Level '..(Fam1.tier + 1))

      rowText = rowText..'||data-sort-value="'..reqLvl..'"|'..table.concat(reqArray, '<br/>')

      table.insert(rowArray, rowText)
    end
  end

  result = result..'\r\n'..table.concat(rowArray, '\r\n')

  result = result..'\r\n|}'
  return result
end

function p._getFamiliarSynergyTable(familiarID)
	local result = ''
	result = result..'{| class="wikitable sortable stickyHeader"'
	result = result..'\r\n|- class="headerRow-0"'
	result = result..'\r\n!colspan="2"|Familiar 1!!colspan="2"|Familiar 2!!Effect!!Requirements'

	local synergyList = {}
	for i, syn in ipairs(SkillData.Summoning.Synergies) do
		if Shared.contains(syn.summons, familiarID) then
			table.insert(synergyList, syn)
		end
	end
    table.sort(synergyList, function (a, b) return (a.summons[1] == b.summons[1] and a.summons[2] < b.summons[2]) or a.summons[1] < b.summons[1] end)

	local marksByID, famNames = {}, {}
	for i, recipe in ipairs(SkillData.Summoning.Marks) do
		marksByID[recipe.masteryID] = recipe
		local item = Items.getItemByID(recipe.itemID)
		if item ~= nil then
		  famNames[recipe.masteryID] = item.name
		end
	end

	local rowArray = {}
	for i, syn in ipairs(synergyList) do
		local Fam1 = marksByID[syn.summons[1]]
		local Fam2 = marksByID[syn.summons[2]]
		if Fam1 ~= nil and Fam2 ~= nil then
			local FamName1 = famNames[Fam1.masteryID] or 'Unknown'
			local FamName2 = famNames[Fam2.masteryID] or 'Unknown'
			local rowText = '|-'
			rowText = rowText..'\r\n|data-sort-value="'..FamName1..'"|'..Icons.Icon({FamName1, type='item', notext=true, size='30'})
			rowText = rowText..'||'..Icons.Icon({FamName1, type='item', noicon=true})
			rowText = rowText..'||data-sort-value="'..FamName2..'"|'..Icons.Icon({FamName2, type='item', notext=true, size='30'})
			rowText = rowText..'||'..Icons.Icon({FamName2, type='item', noicon=true})
			rowText = rowText..'||'..syn.description

			local reqArray = {}
			local reqLvl = math.max(Fam1.level, Fam2.level)
			table.insert(reqArray, Icons._SkillReq('Summoning', reqLvl))
			table.insert(reqArray, FamName1..' Mark Level '..(Fam2.tier + 1))
			table.insert(reqArray, FamName2..' Mark Level '..(Fam1.tier + 1))
			rowText = rowText..'||data-sort-value="'..reqLvl..'"|'..table.concat(reqArray, '<br/>')

			table.insert(rowArray, rowText)
		end
	end

	result = result..'\r\n'..table.concat(rowArray, '\r\n')
	result = result..'\r\n|}'
	return result
end

function p.getFamiliarSynergyTable(frame)
	local famName = frame.args ~= nil and frame.args[1] or frame
	local familiarID = nil
	local familiarItem = Items.getItem(famName)
	if familiarItem == nil then
		return 'ERROR: Not a valid familiar[[Category:Pages with script errors]]'
	else
		for i, recipe in ipairs(SkillData.Summoning.Marks) do
			if recipe.itemID == familiarItem.id then
				familiarID = recipe.masteryID
				break
			end
		end
		if familiarID == nil then
			return 'ERROR: Not a valid familiar[[Category:Pages with script errors]]'
		else
			return p._getFamiliarSynergyTable(familiarID)
		end
	end
end

function p._getSkillSummoningBonusTable(skill)
	local rowArray = {}
	local famNames = {}

	-- Familiars
	for i, recipe in ipairs(SkillData.Summoning.Marks) do
		local item = Items.getItemByID(recipe.itemID)
		if item ~= nil then
			famNames[recipe.masteryID] = item.name
			if item.modifiers ~= nil then
				local famSkills = Constants.getModifierSkills(item.modifiers)
				if Shared.contains(famSkills, skill) then
					table.insert(rowArray, {Fam1 = item.name, Fam2 = nil, Descrip = Constants.getModifiersText(item.modifiers, false)})
				end
			end
		end
	end

	-- Synergies
	for i, syn in ipairs(SkillData.Summoning.Synergies) do
		local synSkills = Constants.getModifierSkills(syn.modifiers)
		if Shared.contains(synSkills, skill) then
			local FamName1 = famNames[syn.summons[1]] or 'Unknown'
			local FamName2 = famNames[syn.summons[2]] or 'Unknown'
			table.insert(rowArray, {Fam1 = FamName1, Fam2 = FamName2, Descrip = syn.description})
		end
	end

	if Shared.tableCount(rowArray) == 0 then
		return ''
	end

	local resultPart = {}
	table.insert(resultPart, '{| class="wikitable sortable stickyHeader"')
  	table.insert(resultPart, '\r\n|- class="headerRow-0"')
	table.insert(resultPart, '\r\n!colspan="2"|Familiar 1!!colspan="2"|Familiar 2!!Effect')

	for i, rowItem in Shared.skpairs(rowArray) do
		table.insert(resultPart, '\r\n|-')
	    table.insert(resultPart, '\r\n|data-sort-value="'..rowItem.Fam1..'"|'..Icons.Icon({rowItem.Fam1, type='item', notext=true, size='30'}))
		table.insert(resultPart, '||'..Icons.Icon({rowItem.Fam1, type='item', noicon=true}))
		if rowItem.Fam2 ~= nil then
			table.insert(resultPart, '||data-sort-value="'..rowItem.Fam2..'"|'..Icons.Icon({rowItem.Fam2, type='item', notext=true, size='30'}))
			table.insert(resultPart, '||'..Icons.Icon({rowItem.Fam2, type='item', noicon=true}))
		else
			table.insert(resultPart, '|| || ')
		end
		table.insert(resultPart, '||'..(rowItem.Descrip or ' '))
	end

	table.insert(resultPart, '\r\n|}')
	return table.concat(resultPart)
end

function p.getSkillSummoningBonusTable(frame)
	local skillName = frame.args ~= nil and frame.args[1] or frame
	return p._getSkillSummoningBonusTable(skillName)
end

return p