Module:Experience

From RuneScape Classic Wiki
Jump to: navigation, search

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

--
-- All functions relating to experience needed etc
-- 

local p = {}
local commas = require('Module:Addcommas')

local NormalXPAtLevel = mw.loadData('Module:Experience/data')
local NormalXPAtLevelUnr = mw.loadData('Module:Experience/dataunr')

--
-- Returns lowest needed XP to have required level
-- [[Template:XP]]
-- 
function p.xp_at_level(frame)
	local level = tonumber(frame.args[1])
	local XPAtLevel = NormalXPAtLevel

	-- calling tonumber on a string returns nil
	if not level then
		 return "You must pass numbers as arguments"
	end

	return XPAtLevel[level]
end

-- Same as above, but with the 120/150 level cap removed

function p.xp_at_level_unr(frame)
	local level = tonumber(frame.args[1])
	local XPAtLevelUnr = NormalXPAtLevelUnr

	-- calling tonumber on a string returns nil
	if not level then
		 return "You must pass numbers as arguments"
	end

	return XPAtLevelUnr[level]
end

--
-- The maximum amount of experience you can have at a given level
-- [[Template:Max XP for level]]
--
function p.max_xp_at_level(frame)
	local level = tonumber(frame.args[1])
	local XPAtLevel = NormalXPAtLevel

	-- calling tonumber on a string returns nil
	if not level then
		 return "You must pass numbers as arguments"
	end

	if level == -1 then
		return 0
	elseif level <= 0 or level > 120 then
		return "Value must be in the range 1 - 120"
	-- Highest level is 120, highest XP is 200M
	elseif (level == 120) then
		return 200000000
	end

	-- Just in case
	level = math.floor(level)

	-- Return XP required for the *next* level minus 1
	local xp_at_next = XPAtLevel[level + 1]
	return xp_at_next - 1
end

--
-- What level you have when at a given xp
-- [[Template:Level]]
--
function p.level_at_xp(frame)
	local xp = frame.args[1]
	local XPAtLevel = NormalXPAtLevel

	-- just in case
	if type(xp) == 'string' then
		 xp = commas._strip(xp)
		 xp = tonumber(xp)
	end

	-- calling tonumber on an empty string returns nil
	if not xp then
		 return "You must pass numbers as arguments"
	end

	if xp < 0 or xp > 200000000 then
		return "Value must be in the range 0 - 200,000,000"
	end
	
	local level
	

    for i=99,1,-1 do
	    if (XPAtLevel[i]<= xp) then
	    	level = i
	    	break
	    end
    end

	return level
end

-- Same as above, but with the 120/150 level cap removed

function p.level_at_xp_unr(frame)
	local xp = frame.args[1]
	local XPAtLevelUnr = NormalXPAtLevelUnr

	-- just in case
	if type(xp) == 'string' then
		 xp = commas._strip(xp)
		 xp = tonumber(xp)
	end

	-- calling tonumber on a string returns nil
	if not xp then
		 return "You must pass numbers as arguments"
	end

	if xp == -1 then
		return 0
	elseif xp < 0 or xp > 200000000 then
		return "Value must be in the range 0 - 200,000,000"
	end
	
	local level
	for i=126,1,-1 do
		if (XPAtLevelUnr[i]<= xp) then
			level = i
			break
		end
	end
	
	return level
end

--
-- Experience needed to obtain a level from a given amount of xp
-- If current xp is greater than target, returns 0
-- [[Template:XP to Level]]
--
function p.xp_to_level(frame)
	local xp = frame.args[1]
	local target = tonumber(frame.args[2])
	local XPAtLevel = NormalXPAtLevel

	-- just in case
	if type(xp) == 'string' then
		 xp = commas._strip(xp)
		 xp = tonumber(xp)
	end

	if (xp < 0 or xp > 200000000) then
		return "XP value must be in the range 0 - 200,000,000"
	end

	if (target < 2 or target > 120) then
		return "Level value must be in the range 2 - 120"
	end

	-- calling tonumber on a string returns nil
	if not xp or not target then
		 return "You must pass numbers as arguments"
	end

	local target_xp = XPAtLevel[target]

	if (xp >= target_xp) then
		return 0
	else
		return target_xp - xp
	end
end

--
-- Experience between two levels; will always return absolute value
-- [[Template:XP level to level]]
--
function p.level_to_level(frame)
	local level1 = tonumber(frame.args[1])
	local level2 = tonumber(frame.args[2])
	local XPAtLevel = NormalXPAtLevel

	-- just in case
	if type(level1) == 'string' then
		 level1 = commas._strip(level1)
		 level1 = tonumber(level1)
	end

	if type(level2) == 'string' then
		 level2 = commas._strip(level2)
		 level2 = tonumber(level2)
	end

	if not level1 or not level2 then
		 return "You must pass numbers as arguments"
	end

	local difference = XPAtLevel[level1]- XPAtLevel[level2]
	difference = math.abs(difference)
	return difference
end

-- Same as above, but with the 120/150 level cap removed

function p.level_to_level_unr(frame)
	local level1 = tonumber(frame.args[1])
	local level2 = tonumber(frame.args[2])
	local XPAtLevelUnr = NormalXPAtLevelUnr

	-- just in case
	if type(level1) == 'string' then
		 level1 = commas._strip(level1)
		 level1 = tonumber(level1)
	end

	if type(level2) == 'string' then
		 level2 = commas._strip(level2)
		 level2 = tonumber(level2)
	end

	if not level1 or not level2 then
		 return "You must pass numbers as arguments"
	end

	local difference = XPAtLevelUnr[level1]- XPAtLevelUnr[level2]
	difference = math.abs(difference)
	return difference
end

--[=[ remainingExp
-- Finds and returns experiences and levels based on inputs
-- Inputs:
--      curLvl		The current level or 1
--		curXP		The current xp or 1
--      tgtLvl		The target level or 0
--		tgtXP		The target xp or 0
-- Returns:
--      current level,
--      current experience,
--      goal level,
--      goal experience,
--      experience remaining
--]=]
function p.remainingExp(curLvl, curXP, tgtLvl, tgtXP)
	local remaining

	if curLvl > 99 and curXP == 1 then
		curXP = curLvl
	elseif curXP <= 99 and curLvl == 1 then
		curLvl = curXP
		curXP = 1
	end
	if tgtLvl > 99 and tgtXP == 0 then
		tgtXP = tgtLvl
	elseif tgtXP <= 99 and tgtLvl == 0 then
		tgtLvl = tgtXP
		tgtXP = 0
	end

	if curXP == 1 then
		curXP = p.xp_at_level({args = {curLvl}})
	else
		curLvl = p.level_at_xp({args = {curXP}})
	end

	if tgtLvl > 0 or tgtXP > 0 then
		if tgtXP == 0 then
			tgtXP = p.xp_at_level({args = {tgtLvl}})
		else
			tgtLvl = p.level_at_xp({args = {tgtXP}})
		end
	end
    
    -- Prevent negative values
    local remaining = math.ceil(tgtXP - curXP)
    if remaining < 0 then
        remaining = 0
    end
    return curLvl, curXP, tgtLvl, tgtXP, remaining
end

return p