Module:Woodcutting chance calculator

From the RuneScape Wiki, the wiki for all things RuneScape
Jump to navigation Jump to search
Module documentation
This documentation is transcluded from Template:No documentation/doc. [edit] [history] [purge]
This module does not have any documentation. Please consider adding documentation at Module:Woodcutting chance calculator/doc. [edit]
Module:Woodcutting chance calculator's function calculator is invoked by Template:Woodcutting chance calculator.
Module:Woodcutting chance calculator requires Module:Paramtest.
Module:Woodcutting chance calculator requires Module:Yesno.
Module:Woodcutting chance calculator loads data from Module:GEPrices/data.
Module:Woodcutting chance calculator loads data from Module:Woodcutting chance calculator/data.
Function list
L 8 — plink
L 20 — jagexInterpolation
L 24 — multifloor
L 32 — gep
L 36 — fnum
L 42 — perc
L 48 — p.makeFellTable
L 68 — p.makeSimpleTable
L 147 — p.calculator
L 192 — p._calculator

local data = mw.loadData('Module:Woodcutting chance calculator/data')
local geprices = mw.loadData('Module:GEPrices/data')
local yn = require('Module:Yesno')
local pt = require('Module:Paramtest')
local p = {}
local lang = mw.getContentLanguage()

function plink(link, image, text)
	_text = text
	_image = image
	if text == nil then
		_text = link
	end
	if image == nil then
		_image = link
	end
	return string.format('[[File:%s.png|link=%s]] [[%s|%s]]', _image, link, link, _text)
end

function jagexInterpolation(hi, lo, lvl)
	return math.floor( ( (99-lvl)*lo + (lvl-1)*hi ) / 98 )
end

function multifloor(x, m)
	local _x = x
	for i,v in ipairs(m) do
		_x = math.floor( _x * v )
	end
	return _x
end

function gep(x)
	return geprices[x] or 0
end

function fnum(num, dp)
	local ret = math.pow(10, dp) * num + 0.5
	ret = math.floor(ret)
	ret = math.pow(10, -dp) * ret
	return lang:formatNum(ret)
end
function perc(x)
	return fnum(x*100,1)..'%'
end

local hatchet_order = { 'bronze', 'iron', 'steel', 'black', 'mithril', 'adamant', 'rune', 'dragon', 'crystal' }

function p.makeFellTable()
	local t = mw.html.create('table')
	t:addClass('wikitable sortable mw-collapsible mw-collapsed align-right-2 align-right-3')
		:tag('caption'):wikitext('Tree fell chances'):done()
		:tag('tr')
			:tag('th'):wikitext('Tree'):done()
			:tag('th'):wikitext('Fell chance<br>(x/256)'):done()
			:tag('th'):wikitext('Percentage'):done()
	
	for i,v in ipairs(data) do
		if v.fell ~= nil and v.fell ~= -1 then
			t:tag('tr')
				:tag('td'):wikitext('[['..v.name..']]'):done()
				:tag('td'):wikitext(v.fell):done()
				:tag('td'):wikitext(perc(v.fell/256)):done()
		end
	end
	return t
end

function p.makeSimpleTable()
	local t = mw.html.create('table')
	t:addClass('wikitable sortable sticky-header mw-collapsible mw-collapsed align-center-1 align-left-2 align-center-3')
		:css('text-align', 'right')
		:tag('caption'):wikitext('Tree high- and lowchances'):done()
		:tag('tr')
			:tag('th'):wikitext('Order'):attr('rowspan',2):done()
			:tag('th'):wikitext('Tree<br>Logs'):attr('rowspan',2):done()
			:tag('th'):wikitext('Level'):attr('rowspan',2):done()
			:tag('th'):wikitext('Base XP'):attr('rowspan',2):done()
			:tag('th'):wikitext('Fell chance<br>(x/256)'):attr('rowspan',2):done()
			:tag('th'):wikitext(plink('Bronze hatchet', nil, 'Bronze')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Iron hatchet', nil, 'Iron')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Steel hatchet', nil, 'Steel')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Black hatchet', nil, 'Black')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Mithril hatchet', nil, 'Mithril')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Adamant hatchet', nil, 'Adamant')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Rune hatchet', nil, 'Rune')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Dragon hatchet', nil, 'Dragon')):attr('colspan',2):done()
			:tag('th'):wikitext(plink('Crystal hatchet', nil, 'Crystal')):attr('colspan',2):done()
		:done()
		:tag('tr')
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
			:tag('th'):wikitext('Low'):done()
			:tag('th'):wikitext('High'):done()
		:done()
	for i,v in ipairs(data) do
		local namecell = '[['..v.name..']]'
		if v.logs then
			namecell = namecell..'<br>'..plink(v.logs)
		end
		local fallchance = v.fell
		if fallchance == nil or fallchance == -1 then
			fallchance = 'N/A'
		end
		t:newline()
		local tr = t:tag('tr')
		tr
			:tag('td')
				:wikitext(i)
			:done()
			:tag('td')
				:wikitext(namecell)
			:done()
			:tag('td')
				:wikitext(v.level)
			:done()
			:tag('td')
				:wikitext(v.xp)
			:done()
			:tag('td')
				:wikitext(fallchance)
			:done()
		for j,u in ipairs(hatchet_order) do
			tr
				:tag('td'):wikitext(v.low[u]):done()
				:tag('td'):wikitext(v.high[u]):done()
		end
	end
	t:newline()
	return t
end


function p.calculator(frame)
	return p._calculator(frame:getParent().args)
end

local multipliers_list = {
	skillchompa = {
		cobalt = 1.01,
		viridian = 1.02,
		azure = 1.03,
		crimson = 1.04,
		crystal = 1.05
	},
	aura = {
		basic = 1.03,
		greater = 1.05,
		master = 1.07,
		supreme = 1.1,
		legendary = 1.15
	},
	outfit = {
		sentinel = 1.05,
		["nature's sentinel"] = 1.07,
		["nature&#039;s sentinel"] = 1.07
	},
	offhand = 1.06,
	ring = 1.03,
	idol = 1.1,
	menaphos = 1.1,
	familiar = {
		['beaver'] = 2
	},
	hatchets = {
		bronze = true,
		iron = true,
		steel = true,
		black = true,
		mithril = true,
		adamant = true,
		rune = true,
		dragon = true,
		crystal = true
	}
	
}

function p._calculator(args)
	local level = tonumber(args.level) or 99
	local spots = {}
	local spots_order = {}
	
	-- setup multipliers
	local hi_multipliers = {}
	local lo_multipliers = {}
	
	local xp_multipliers = {}
	
	local hatchet = string.lower(args.hatchet or '')
	if not multipliers_list.hatchets[hatchet] then
		hatchet = 'bronze'
	end
	
	-- if table.insert(t, nil) is a noop
	for i,v in ipairs({ 'skillchompa', 'outfit', 'aura'}) do
		if pt.has_content(args[v]) then
			table.insert(hi_multipliers, multipliers_list[v][string.lower(args[v])])
		end
	end
	for i,v in ipairs({'ring', 'idol', 'offhand'}) do
		if yn(args[v]) then
			table.insert(hi_multipliers, multipliers_list[v])
		end
	end
	
	-- only applies to menaphos fish
	local menaphos = {}
	if yn(args.menaphos) then
		menaphos = { multipliers_list.menaphos }
	end
	
	-- both hi and low
	local _h = tonumber(args.honed) or 0
	local honed = 0
	if _h > 0 then
		honed = 1 + 0.02 * _h
		if yn(args.level20) then
			honed = 1 + 0.022 * _h
		end
	end
	
	-- familiar is special
	local familiar = 0
	if pt.has_content(args.familiar) then
		familiar = multipliers_list.familiar[string.lower(args.familiar)] or 0
	end
	
	--[==[
	-- undecided if i want to add this, since i then should really add all of the other xp multipliers and there's a lot
	if (tonumber(args.xpoutfit) or 0) > 0 then
		if tonumber(args.xpoutfit) >= 4 then
			table.insert(xp_multipliers, 1.05)
		else
			table.insert(xp_multipliers, 1+(0.01*tonumber(args.xpoutfit)))
		end
	end
	--]==]
	
	
	-- filter into spot-groupings of the relevant things based on level
	for i,v in ipairs(data) do
		local addSpot = level >= v.level
		if addSpot then
			local spotName = v.name
			table.insert(spots_order, spotName)
			spots[spotName] = v
		end
	end
	
	-- construct output table
	local ret = mw.html.create('table')
	ret:addClass('wikitable sortable align-right-3 align-right-4 align-right-5 align-right-6 align-right-7')
		:tag('tr')
			:tag('th'):wikitext('Tree'):done()
			:tag('th'):wikitext('Logs'):done()
			:tag('th'):wikitext('WC XP'):done()
			:tag('th'):wikitext('Success chance'):done()
			:tag('th'):wikitext('Logs/hr'):done()
			:tag('th'):wikitext('Overall XP/hr'):done()
			:tag('th'):wikitext('Overall GP/hr'):done()
	ret:newline()
	
	for i,v in ipairs(spots_order) do
		local tree = spots[v]
		local tr = ret:tag('tr')
		local delay = 4
		local totalGPH = 0
		local totalXPH = 0
		local newHi = multifloor(tree.high[hatchet], hi_multipliers)
		if tree.is_menaphos then
			newHi = multifloor(newHi, menaphos)
		end
		local newLo = multifloor(tree.low[hatchet], lo_multipliers)
		if honed > 0 then
			newHi = math.ceil( newHi * honed )
			newLo = math.ceil( newLo * honed )
		end
		if familiar > 0 then
			local fambuff = math.floor( familiar * math.floor(10*(tree.high[hatchet]-tree.low[hatchet])/98) /10 )
			newHi = newHi + fambuff
			newLo = newLo + fambuff
		end
		
		
		local rawchance = jagexInterpolation(newHi, newLo, level)
		local chance = math.max(rawchance / 256, 0)
		local lph = 6000/delay * math.min(chance,1)
		totalGPH = lph * gep(tree.ge or tree.logs)
		local xp = tree.xp
		if tree.is_bgh_tree then
			xp = level
		end
		totalXPH = lph * xp
		
		
		tr:tag('td'):wikitext('[['..tree.name..']]'):done()
		if tree.logs then
			tr:tag('td'):wikitext(plink(tree.logs)):done()
		else
			tr:tag('td'):wikitext('N/A'):addClass('table-na')
		end
		tr:tag('td'):wikitext(xp):done()
			:tag('td'):wikitext(perc(chance)):done()
			:tag('td'):wikitext(fnum(lph, 0)):done()
			:tag('td'):wikitext(fnum(totalXPH, 1)):done()
			:tag('td'):wikitext(fnum(totalGPH, 0)):done()
		ret:newline()
	end
	
	return ret
end


return p