Module:Stat Factors Table

From RimWorld Wiki
Revision as of 15:18, 25 February 2025 by Arcangelus (talk | contribs)
Jump to navigation Jump to search

This module is meant to be used by Template:Stat Factors Table Row, which in turn is meant to be used alogside Template:Stat Factors Table.

This module returns the rows used in said table. It accept 8 inputs: skillBase, skillBonus, statMin, statMax, capImportance, capLimit, resultCols, LV, Ln

Any value not given is assumed 0. There are exceptions for the default values of Stat Maximum (99999999) and statMin (0), both of which are defined on Template:Stat Factors Table.

This can probably be further improved. Regardless, this represents a 71% improvement over the ParserFunctions method.

Examples:

{{Stat Factors Table}}

on the Butchery Efficiency page would produce:

Cooking Skill Level CollapseButchery Efficiency
100% Manipulation 125% Manipulation 150% Manipulation
0 75%91.88% 108.75%
1 77.5%94.94% 112.38%
2 80%98% 116%
3 82.5%101.06% 119.62%
4 85%104.13% 123.25%
5 87.5%107.19% 126.88%
6 90%110.25% 130.5%
7 92.5%113.31% 134.13%
8 95%116.38% 137.75%
9 97.5%119.44% 141.37%
10 100%122.5% 145%
11 102.5%125.56% 148.62%
12 105%128.63% 150%
13 107.5%131.69% 150%
14 110%134.75% 150%
15 112.5%137.81% 150%
16 115%140.88% 150%
17 117.5%143.94% 150%
18 120%147% 150%
19 122.5%150% 150%
20 125%150% 150%
{{Stat Factors Table|Foraged Food Amount}}

on any page would produce:

Plants Skill Level CollapseForaged Food Amount
100% Sight 125% Sight 150% Sight
0 0%0% 0%
1 9%11.03% 13.05%
2 18%22.05% 26.1%
3 27%33.08% 39.15%
4 36%44.1% 52.2%
5 45%55.13% 65.25%
6 54%66.15% 78.3%
7 63%77.18% 91.35%
8 72%88.2% 104.4%
9 81%99.23% 117.45%
10 90%110.25% 130.5%
11 99%121.28% 143.55%
12 108%132.3% 156.6%
13 117%143.33% 169.65%
14 126%154.35% 182.7%
15 135%165.38% 195.75%
16 144%176.4% 208.8%
17 153%187.43% 221.85%
18 162%198.45% 234.9%
19 171%209.48% 247.95%
20 180%220.5% 261%

Example when limit is 100%:

{{Stat Factors Table|Arrest Success Chance}}

it produces:

Social Skill Level CollapseArrest Success Chance
0 60%
1 67.5%
2 75%
3 82.5%
4 90%
5 97.5%
6 100%
7 100%
8 100%
9 100%
10 100%
11 100%
12 100%
13 100%
14 100%
15 100%
16 100%
17 100%
18 100%
19 100%
20 100%

Example when limit is >100% but <125%: Note: Research Speed is not an appropriate use of the template, as it relies equally on two different capacities, however, at the time of writing no compatible example of an inter-column limit exists:

{{Stat Factors Table|Research Speed }}

on any page would produce:

Intellectual Skill Level CollapseResearch Speed
100% Manipulation 110%+ Manipulation
0 8%9%
1 19.5%21.94%
2 31%34.88%
3 42.5%47.81%
4 54%60.75%
5 65.5%73.69%
6 77%86.63%
7 88.5%99.56%
8 100%112.5%
9 111.5%125.44%
10 123%138.38%
11 134.5%151.31%
12 146%164.25%
13 157.5%177.19%
14 169%190.13%
15 180.5%203.06%
16 192%216%
17 203.5%228.94%
18 215%241.88%
19 226.5%254.81%
20 238%267.75%

Example when skills have to be specifically defined:

{{Stat Factors Table|Plant Harvest Yield|l0=0.60|l1=0.70|l2=0.75|l3=0.80|l4=0.85|l5=0.90|l6=0.95|l7=0.98|l8=1.00|l9=1.01|l10=1.02|l11=1.03|l12=1.04|l13=1.05|l14=1.06|l15=1.07|l16=1.08|l17=1.09|l18=1.10|l19=1.12|l20=1.13}}

it produces:

Plants Skill Level CollapsePlant Harvest Yield
100% Manipulation 125% Manipulation 150% Manipulation
0 60%64.5% 69%
1 130%139.75% 149.5%
2 150%150% 150%
3 150%150% 150%
4 150%150% 150%
5 150%150% 150%
6 150%150% 150%
7 150%150% 150%
8 150%150% 150%
9 150%150% 150%
10 150%150% 150%
11 150%150% 150%
12 150%150% 150%
13 150%150% 150%
14 150%150% 150%
15 150%150% 150%
16 150%150% 150%
17 150%150% 150%
18 150%150% 150%
19 150%150% 150%
20 150%150% 150%

Medical Skill Level CollapseMedical Surgery Success Chance
100% Manipulation 125% Manipulation 150% Manipulation
0 1%1% 1%
1 120%150% 180%
2 260%325% 390%
3 420%525% 630%
4 600%750% 900%
5 800%1000% 1200%
6 1020%1275% 1530%
7 1225%1531.25% 1837.5%
8 1440%1800% 2160%
9 1665%2081.25% 2497.5%
10 1900%2375% 2850%
11 2112%2640% 3168%
12 2328%2910% 3492%
13 2548%3185% 3822%
14 2772%3465% 4158%
15 3000%3750% 4500%
16 3232%4040% 4848%
17 3468%4335% 5202%
18 3708%4635% 5562%
19 3952%4940% 5928%
20 4200%5250% 6300%

local getArgs -- lazily initialized
local p = {}
local wrap = {} -- Holds wrapper functions that process arguments from #invoke. These act as intemediary between functions meant for #invoke and functions meant for Lua.

local function unpackNumberArgs(args)
	-- Returns an unpacked list of arguments specified with numerical keys.
	local ret = {}
	for k, v in pairs(args) do
		if type(k) == 'number' then
			table.insert(ret, v)
		end
	end
	return unpack(ret)
end

--Stat Factors Table Row

function wrap.TableRow(args)
	return p._TableRow(unpackNumberArgs(args))
end
function p._TableRow(skillBase, skillBonus, statMin, statMax, capImportance, capLimit, resultCols, LV, Ln)
	--Remove local if these variables are to be used somewhere else. 
	local argumentos={skillBase,skillBonus,statMin,statMax,capImportance,capLimit,resultCols,LV,Ln}
	
	for i = 1,8 do --This should prevent errors if a number is not defined.
		if type(argumentos[i])~='number' then
			if argumentos[6] then -- In case capLimit is not correctly set.
				argumentos[6]=1000
			else
				argumentos[i]=0
			end
		end
	end
	skillBase,skillBonus,statMin,statMax,capImportance,capLimit,resultCols,LV,Ln = argumentos[1],argumentos[2],argumentos[3],argumentos[4],argumentos[5],argumentos[6],argumentos[7],argumentos[8]
	-- Do note that statMin, statMax are handled by "Template:Stat Factors Table" (including defaults)

	if tonumber(Ln)==nil then --Sanitizes input and allows for Ln=0.
		factor = skillBase + (tonumber(skillBonus) or 0 ) * LV
	else
		factor = Ln
	end

	local Pval = math.min(math.max(factor,statMin),statMax)
	R_Pval = tostring(math.floor(Pval*10000+0.5)/100).."%" -- This formats the number as a 2 digit percent value, rounded up.
--	R_Pval = string.format("%.2f", Pval*100).."%" -- While Easier to parse, this has the issue of forcing 2 decimals for all numbers.
	if tonumber(resultCols)>1 then
		Pval = factor * ( 1 + capImportance * math.min(capLimit-1, 0.25))
		Pval = math.min(math.max(Pval,statMin),statMax)
		R_Sval="<td>"..tostring(math.floor(Pval*10000+0.5)/100).."% </td>"
	else
		R_Sval=""
	end

	if tonumber(resultCols)>2 then
		Pval = factor * ( 1 + capImportance * math.min(capLimit-1, 0.5))
		Pval = math.min(math.max(Pval,statMin),statMax)
		R_Tval="<td>"..tostring(math.floor(Pval*10000+0.5)/100).."% </td>"
	else
		R_Tval=""
	end
	
	return "|-\r\n!"..LV.."\r\n|"..R_Pval..R_Sval..R_Tval
	-- There are more efficient ways, but this works.
end

-- Deep Drill Speed custom version. Includes Time in minutes (at x1 speed)
function wrap.Table_DDS(args)
	return p._Table_DDS(unpackNumberArgs(args))
end
function p._Table_DDS(skillBase, skillBonus, capImportance)
	--statMin=0 so omitted, skill uncapped so statMax omitted.
	local argumentos={skillBase, skillBonus, capImportance}

	for i = 1,3 do --This should prevent errors if a number is not defined.
		if type(argumentos[i])~='number' then
			argumentos[i]=0
		end
	end
	skillBase,skillBonus,capImportance = argumentos[1],argumentos[2],argumentos[3]

	-- If needed, the Header can be moved outside
	local Header = '{| class = "mw-collapsible wikitable" width="180" style="text-align: center;"\r\n' -- May just call it from outside.
	Header = Header..'! rowspan=2 | {{#show: Deep Drilling Speed|?Skill}} Skill Level'..'\r\n'
	Header = Header..'! colspan=3 | Deep Drilling Speed<br/>(Real time at 1x speed)'..'\r\n'
	Header = Header..'|-\r\n'
	Header = Header..'! 100% Manipulation !! 125% Manipulation !! 150% Manipulation'..'\r\n'..'|-'..'\r\n'
	local line, cuerpo = "", ""
	local factor = 0
	local val1, val2, val3 = 0,0,0
	local time1, time2, time3 = 0,0,0
	
	for i = 0, 20 do --This creates the table itself.
		line = "|-\r\n!"..i.."\r\n|" --Just for order
		factor = skillBase + tonumber(skillBonus) * i
		val1 = math.max(factor, 0)
		time1 = 14000/(val1*3600) -- This is time in minutes.
		-- This formats the number as a percent value with X decimals, rounded up. Change to %.0f for no decimals.
		R_Pval= string.format("%.1f", val1*100).."% <br/>"..string.format("(%.2f min)", time1)

		val2 = factor * ( 1 + capImportance * 0.25)
		val2 = math.max(val2, 0)
		time2 = 14000/(val2*3600)
		R_Sval= string.format("<td>%.1f", val2*100).."% <br/>"..string.format("(%.2f min)", time2).."</td>"

		val3 = factor * ( 1 + capImportance * 0.5)
		val3 = math.max(val3, 0)
		time3 = 14000/(val3*3600)
		R_Tval= string.format("<td>%.1f", val3*100).."% <br/>"..string.format("(%.2f min)", time3).."</td>"
		
		cuerpo = cuerpo..line..R_Pval..R_Sval..R_Tval.."\r\n"
	end

	return Header..cuerpo.."|}" --This should be the entire table. I may be a space short.
end

--[[
Wrapper function that does basic argument processing. This ensures that all functions from #invoke can use either the current
frame or the parent frame, and it also trims whitespace for all arguments and removes blank arguments.
]]

local mt = { __index = function(t, k)
	return function(frame)
		if not getArgs then
			getArgs = require('Module:Arguments').getArgs
		end
		return wrap[k](getArgs(frame))  -- Argument processing is left to Module:Arguments. Whitespace is trimmed and blank arguments are removed.
	end
end }

return setmetatable(p, mt)


-- END OF MODULE