Module:ItemEconomy: Difference between revisions

From Melvor Idle
m (Fix nil exceptions)
m (Chance extraItemAmount default from 0 to 1)
 
(4 intermediate revisions by the same user not shown)
Line 1: Line 1:
local number = require('Module:Number')
local p = {}
local p = {}


local function clamp(value, min, max)
local ItemEconomy = {
    return math.min(math.max(value, min), max)
-- Amount of items required per action.
inputsPerAction,
-- Amount of items created per action. (ie. 3 bolts per action).
outputsPerAction,
-- The chance from 0 to 80 to preserve resources.
preservationChance,
-- The chance from 0 to 100 to duplicate the crafting output.
duplicationChance,
-- The chance from 0 to 100 to get extra output items (not doubled).
extraItemChance,
-- The amount of extra items received, when the extraItemChance is rolled.
extraItemAmount,
-- The amount of extra items always received per action (not doubled).
flatExtraItems,
-- The chance to get extra base items (can be doubled).
extraBaseItemChance,
-- The amount of extra base items received.
extraBaseItems
}
 
--- Constructor function for creating new ItemEconomy instances.
-- @return ItemEconomy An instance of the ItemEconomy class.
function ItemEconomy:new()
    local newObj = {}
   
    self.__index = self
    return setmetatable(newObj, self)
end
end


--
--- Verifies and updates the economy values of the ItemEconomy instance.
-- Calculates the expected output given the player's starting items and item economy modifiers.
-- If any economy value is nil, it sets a default value.
-- PreservationChance (number from 0 - 80)
-- If any economy value is out of range, clamp it to the nearest valid range.
-- DuplicationChance (number from 0 - 100)
-- @return ItemEconomy Returns a verified ItemEconomy object.
-- ExtraItemChance (number from 0 - ?)
function ItemEconomy:verify()
--
function p.estimatedOutput(inputAmount, preservationChance, duplicationChance, extraItemChance)
    -- Set default values if some are nil
-- Default values to zero if they haven't been provided.
    self.inputsPerAction = self.inputsPerAction or 1
     preservationChance = preservationChance or 0
     self.outputsPerAction = self.outputsPerAction or 1
     duplicationChance = duplicationChance or 0
    self.preservationChance = self.preservationChance or 0
     extraItemChance = extraItemChance or 0
     self.duplicationChance = self.duplicationChance or 0
     self.extraItemChance = self.extraItemChance or 0
    self.extraItemAmount = self.extraItemAmount or 1
    self.flatExtraItems = self.flatExtraItems or 0
    self.extraBaseItemChance = self.extraBaseItemChance or 0
    self.extraBaseItems = self.extraBaseItems or 0
   
    -- Clamp economy values (clamp the verified copy values)
    self.preservationChanceP = number.clamp(self.preservationChance, 0, 80) / 100
    self.duplicationChanceP = number.clamp(self.duplicationChance, 0, 100) / 100
    self.extraItemChanceP = number.clamp(self.extraItemChance, 0, 100) / 100
    self.extraBaseItemChanceP = number.clamp(self.extraBaseItemChance, 0, 100) / 100
   
    return self
end


-- Clamp values and turn them into decimals
--- Creates a deep copy of ItemEconomy to prevent clashes with the caller.
    local preservationP = clamp(preservationChance, 0, 80) / 100
function ItemEconomy:copy()
     local duplicationP = clamp(duplicationChance, 0, 100) / 100
     local cpy = {}
     local extraItemP = math.max(extraItemChance, 0) / 100
     for k, v in pairs(self) do cpy[k] = v end
      
      
     local input = inputAmount or 0
     return setmetatable(cpy, getmetatable(self))
   
end
    local totalActions = input / (1 - preservationP)
 
    local extraItems = totalActions * extraItemP
--- Calculates a ratio between input to output.
-- @param itemEconomy (table) The ItemEconomy object containing ItemEconomy values.
-- @return (number) The output ratio of the crafting process.
function p.estimatedOutputMultiplier(itemEconomy)
local minOutput = p.estimatedOutput(nil, itemEconomy)
return minOutput / itemEconomy.inputsPerAction
end
 
--- Estimates the output of a crafting process based on input and ItemEconomy values.
-- @param inputAmount (number) The total amount of input items available for crafting.
-- @param itemEconomy (table) The ItemEconomy object containing ItemEconomy values.
-- @return (number) The estimated output of the crafting process.
function p.estimatedOutput(inputAmount, itemEconomy)
local eco = itemEconomy:verify()
 
-- Equal inputAmount to inputsPerAction to get 1 baseAction
inputAmount = inputAmount or eco.inputsPerAction
local baseActions = inputAmount / eco.inputsPerAction
-- Can't craft with what you don't have...
if inputAmount < eco.inputsPerAction then
return 0
end
-- Calculate the effective actions taken.
local totalActions = baseActions / (1 - eco.preservationChanceP)
-- Calculates extra items that can't be doubled.
local extraItems = (totalActions * eco.extraItemChanceP * eco.extraItemAmount) + (totalActions * eco.flatExtraItems)
-- Calculates extra items that CAN be doubled.
local baseItems = (eco.outputsPerAction + eco.extraBaseItemChanceP * eco.extraBaseItems)
-- Total output
return (totalActions * baseItems * (1 + eco.duplicationChanceP)) + extraItems
end
 
--- Calculates a ratio between output to input.
-- @param itemEconomy (table) The ItemEconomy object containing ItemEconomy values.
-- @return (number) The input ratio of the crafting process.
function p.estimatedInputMultiplier(itemEconomy)
-- I'm fairly certain that the following holds true in any case.
return 1 / p.estimatedOutputMultiplier(itemEconomy)
end


    return (totalActions * (1 + duplicationP)) + extraItems
--- Estimates the input required for a given output amount in a crafting process based on ItemEconomy values.
-- This function provides a detailed breakdown of the calculation process.
-- @param outputAmount The total amount of output items desired.
-- @param itemEconomy The ItemEconomy object containing ItemEconomy values.
-- @return The estimated input required for the given output amount.
function p.estimatedInput(outputAmount, itemEconomy)
-- Again, fairly certain Input is just 1 / Output.
-- Replace with p.estimatedInputVerbose is this ever isn't the case.
local inputMultiplier =  1 / p.estimatedOutputMultiplier(itemEconomy)
return math.max(outputAmount * inputMultiplier, itemEconomy.inputsPerAction)
end
end


--
function p.estimatedInputVerbose(outputAmount, itemEconomy)
-- Calculates the expected input required for an output given the player's item economy modifiers.
local eco = itemEconomy:verify()
-- PreservationChance (number from 0 - 80)
 
-- DuplicationChance (number from 0 - 100)
outputAmount = outputAmount or eco.outputsPerAction
-- ExtraItemChance (number from 0 - ?)
local preserveAmount = outputAmount * eco.inputsPerAction * (1 - eco.preservationChanceP)
--
local duplicateAmount = eco.outputsPerAction + eco.outputsPerAction * eco.duplicationChanceP
function p.estimatedInput(outputAmount, preservationChance, duplicationChance, extraItemChance)
local extraBaseItems = eco.extraBaseItemChanceP * eco.extraBaseItems + eco.extraBaseItemChanceP * eco.extraBaseItems * eco.duplicationChanceP
-- Default values to zero if they haven't been provided.
local extraItems = eco.extraItemChanceP * eco.extraItemAmount
    preservationChance = preservationChance or 0
    duplicationChance = duplicationChance or 0
    extraItemChance = extraItemChance or 0


    local preservationP = clamp(preservationChance, 0, 80) / 100
-- Total input required for given output.
    local duplicationP = clamp(duplicationChance, 0, 100) / 100
local actualInput = preserveAmount / (duplicateAmount + extraBaseItems + extraItems + eco.flatExtraItems)
    local extraItemP = math.max(extraItemChance, 0) / 100
return math.max(actualInput, eco.inputsPerAction)
   
    local output = outputAmount or 0
   
    return (output - output * preservationP) / (1 + duplicationP + extraItemP)
end
end


--
--- Calculates if equipping the Ring Of Wealth will result in more items for the player.
-- Calculates if equipping the Ring Of Wealth will result in more items for the player.
-- @param itemEconomy The ItemEconomy object containing ItemEconomy values.
-- PreservationChance (number from 0 - 80)
-- @return TRUE if the Ring of Wealth is more beneficial than harmful.
-- DuplicationChance (number from 0 - 100)
function p.ringOfWealthHasEffect(itemEconomy)
-- ExtraItemChance (number from 0 - ?)
local rowEco = itemEconomy:copy():verify()
--
function p.ringOfWealthHasEffect(preservationChance, duplicationChance, extraItemChance)
-- Apply Ring of Wealth buffs.
-- Default values to zero if they haven't been provided.
rowEco.preservationChance = rowEco.preservationChance - 3
    preservationChance = preservationChance or 0
rowEco.duplicationChance = rowEco.duplicationChance + 7
    duplicationChance = duplicationChance or 0
    extraItemChance = extraItemChance or 0
   
local currentModifier = p.estimatedOutput(1, preservationChance, duplicationChance, extraItemChance)
local rowPreserve = math.max(0, preservationChance - 3)
local rowMultiplier = p.estimatedOutputMultiplier(rowEco)
local rowDupe = math.min(100, duplicationChance + 7)
local playerMultiplier = p.estimatedOutputMultiplier(itemEconomy)
local rowModifier = p.estimatedOutput(1, rowPreserve, rowDupe, extraItemChance)
return rowModifier > currentModifier
return rowMultiplier > playerMultiplier
end
end
p.ItemEconomy = ItemEconomy


return p
return p

Latest revision as of 00:03, 19 March 2024

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

local number = require('Module:Number')

local p = {}

local ItemEconomy = {
	-- Amount of items required per action.
	inputsPerAction,
	-- Amount of items created per action. (ie. 3 bolts per action).
	outputsPerAction,
	-- The chance from 0 to 80 to preserve resources.
	preservationChance,
	-- The chance from 0 to 100 to duplicate the crafting output.
	duplicationChance,
	-- The chance from 0 to 100 to get extra output items (not doubled).
	extraItemChance,
	-- The amount of extra items received, when the extraItemChance is rolled.
	extraItemAmount,
	-- The amount of extra items always received per action (not doubled).
	flatExtraItems,
	-- The chance to get extra base items (can be doubled).
	extraBaseItemChance,
	-- The amount of extra base items received.
	extraBaseItems
}

--- Constructor function for creating new ItemEconomy instances.
-- @return ItemEconomy An instance of the ItemEconomy class.
function ItemEconomy:new()
    local newObj = {}
    
    self.__index = self
    return setmetatable(newObj, self)
end

--- Verifies and updates the economy values of the ItemEconomy instance.
-- If any economy value is nil, it sets a default value.
-- If any economy value is out of range, clamp it to the nearest valid range.
-- @return ItemEconomy Returns a verified ItemEconomy object.
function ItemEconomy:verify()
	
    -- Set default values if some are nil
    self.inputsPerAction = self.inputsPerAction or 1
    self.outputsPerAction = self.outputsPerAction or 1
    self.preservationChance = self.preservationChance or 0
    self.duplicationChance = self.duplicationChance or 0
    self.extraItemChance = self.extraItemChance or 0
    self.extraItemAmount = self.extraItemAmount or 1
    self.flatExtraItems = self.flatExtraItems or 0
    self.extraBaseItemChance = self.extraBaseItemChance or 0
    self.extraBaseItems = self.extraBaseItems or 0
    
    -- Clamp economy values (clamp the verified copy values)
    self.preservationChanceP = number.clamp(self.preservationChance, 0, 80) / 100
    self.duplicationChanceP = number.clamp(self.duplicationChance, 0, 100) / 100
    self.extraItemChanceP = number.clamp(self.extraItemChance, 0, 100) / 100
    self.extraBaseItemChanceP = number.clamp(self.extraBaseItemChance, 0, 100) / 100
    
    return self
end

--- Creates a deep copy of ItemEconomy to prevent clashes with the caller.
function ItemEconomy:copy()
    local cpy = {}
    for k, v in pairs(self) do cpy[k] = v end
    
    return setmetatable(cpy, getmetatable(self))
end

--- Calculates a ratio between input to output.
-- @param itemEconomy (table) The ItemEconomy object containing ItemEconomy values.
-- @return (number) The output ratio of the crafting process.
function p.estimatedOutputMultiplier(itemEconomy)
	local minOutput = p.estimatedOutput(nil, itemEconomy)
	return minOutput / itemEconomy.inputsPerAction
end

--- Estimates the output of a crafting process based on input and ItemEconomy values.
-- @param inputAmount (number) The total amount of input items available for crafting.
-- @param itemEconomy (table) The ItemEconomy object containing ItemEconomy values.
-- @return (number) The estimated output of the crafting process.
function p.estimatedOutput(inputAmount, itemEconomy)
	local eco = itemEconomy:verify()

	-- Equal inputAmount to inputsPerAction to get 1 baseAction
	inputAmount = inputAmount or eco.inputsPerAction
	local baseActions = inputAmount / eco.inputsPerAction
	
	-- Can't craft with what you don't have...
	if inputAmount < eco.inputsPerAction then
		return 0
	end
	
	-- Calculate the effective actions taken.
	local totalActions = baseActions / (1 - eco.preservationChanceP)
	-- Calculates extra items that can't be doubled.
	local extraItems = (totalActions * eco.extraItemChanceP * eco.extraItemAmount) + (totalActions * eco.flatExtraItems)
	-- Calculates extra items that CAN be doubled.
	local baseItems = (eco.outputsPerAction + eco.extraBaseItemChanceP * eco.extraBaseItems)
	
	-- Total output
	return (totalActions * baseItems * (1 + eco.duplicationChanceP)) + extraItems
end

--- Calculates a ratio between output to input.
-- @param itemEconomy (table) The ItemEconomy object containing ItemEconomy values.
-- @return (number) The input ratio of the crafting process.
function p.estimatedInputMultiplier(itemEconomy)
	-- I'm fairly certain that the following holds true in any case.
	return 1 / p.estimatedOutputMultiplier(itemEconomy)
end

--- Estimates the input required for a given output amount in a crafting process based on ItemEconomy values.
-- This function provides a detailed breakdown of the calculation process.
-- @param outputAmount The total amount of output items desired.
-- @param itemEconomy The ItemEconomy object containing ItemEconomy values.
-- @return The estimated input required for the given output amount.
function p.estimatedInput(outputAmount, itemEconomy)
	-- Again, fairly certain Input is just 1 / Output.
	-- Replace with p.estimatedInputVerbose is this ever isn't the case.
	local inputMultiplier =  1 / p.estimatedOutputMultiplier(itemEconomy)
	return math.max(outputAmount * inputMultiplier, itemEconomy.inputsPerAction)
end

function p.estimatedInputVerbose(outputAmount, itemEconomy)
	local eco = itemEconomy:verify()

	outputAmount = outputAmount or eco.outputsPerAction
	local preserveAmount = outputAmount * eco.inputsPerAction * (1 - eco.preservationChanceP)
	local duplicateAmount = eco.outputsPerAction + eco.outputsPerAction * eco.duplicationChanceP
	local extraBaseItems = eco.extraBaseItemChanceP * eco.extraBaseItems + eco.extraBaseItemChanceP * eco.extraBaseItems * eco.duplicationChanceP
	local extraItems = eco.extraItemChanceP * eco.extraItemAmount

	-- Total input required for given output.
	local actualInput = preserveAmount / (duplicateAmount + extraBaseItems + extraItems + eco.flatExtraItems)
	return math.max(actualInput, eco.inputsPerAction)
end

--- Calculates if equipping the Ring Of Wealth will result in more items for the player.
-- @param itemEconomy The ItemEconomy object containing ItemEconomy values.
-- @return TRUE if the Ring of Wealth is more beneficial than harmful.
function p.ringOfWealthHasEffect(itemEconomy)
	local rowEco = itemEconomy:copy():verify()
	
	-- Apply Ring of Wealth buffs.
	rowEco.preservationChance = rowEco.preservationChance - 3
	rowEco.duplicationChance = rowEco.duplicationChance + 7
	
	local rowMultiplier = p.estimatedOutputMultiplier(rowEco)
	local playerMultiplier = p.estimatedOutputMultiplier(itemEconomy)
	
	return rowMultiplier > playerMultiplier
end

p.ItemEconomy = ItemEconomy

return p