Jump to content

Module:Rolling Stock

From Steam & Steel

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

local module = {}

-- PLEASE add trailing commas to every line in a table - it makes it easier to edit in the future!
-- do not add ambiguous information or guess-work, without proper reasoning - test and confirm in-game to your best ability!

-- leave notes in the form of comments if necessary.

local page_title = mw.title.getCurrentTitle()
-- mw is a mediawiki global (i think)
local page_name = page_title.fullText

-- added: MAPLE RIDGE
-- WEIGHT IS IN TONS

module.rolling_stock = {
	["14' Stake Wagon"] = {
		page = "14' Stake Wagon",
		type = "cargo",
		image = "14StakeWagonDefault.png",
		buy_price = 555,
		
		weight = 4.3,
		
		cargo = {
			["Logs"] = 4.7,
			["Rails"] = 3.1,
			["Pipes"] = 4.7,
			["Iron Ingots"] = 2,
			["Copper Ingots"] = 2,
			["Aluminium Ingots"] = 4,
			["Beams"] = 2.3,
		}
	},
	["8 Ton Ore Hopper"] = {
		page = "8 Ton Ore Hopper",
		type = "cargo",
		image = "8TonOreHopper.png",
		buy_price = 684,
		
		weight = 4.8,
		paintable = true,
		
		cargo = {
			["Copper Ore"] = 4.4,
			["Bauxite Ore"] = 4.4,
			["Gold Ore"] = 4.4,
			["Iron Ore"] = 4.4,
			["Wood Pulp"] = 4.4,
			["Coal"] = 4.4,
			["Clay"] = 4.4,
			["Sand"] = 4.4,
			["Gravel"] = 4.4,
			["Grain"] = 15,
		}
	},
	["17' Stake Wagon"] = {
		page = "Stake_Wagons",
		type = "cargo",
		image = "Screenshot 2023-07-20 030322.png",
		buy_price = 705,
		
		weight = 6.3,
		
		cargo = {
			["Logs"] = 6,
			["Rails"] = 4,
			["Pipes"] = 6,
			["Iron Ingots"] = 2,
			["Copper Ingots"] = 2,
			["Aluminium Ingots"] = 4,
			["Beams"] = 3,
		}
	},
	["20' Flat Wagon"] = {
		page = "Flat_Wagon",
		type = "cargo",
		image = "Screenshot 2023-07-20 030655.png",
		buy_price = 821,
		
		weight = 4.8,
		
		cargo = {
			["Iron Ingots"] = 2,
			["Copper Ingots"] = 2,
			["Aluminium Ingots"] = 4,
			["Cut Stone"] = 5,
			["Food"] = 12,
			["Tools"] = 5,
			["Grain"] = 6,
			["Lumber"] = 4,
			["Leather"] = 12,
			["Bricks"] = 4,
			["Paper"] = 3,
		}
	},
	["12 Ton Van"] = {
		page = "Van",
		type = "cargo",
		image = "Screenshot 2023-07-20 030829.png",
		buy_price = 837,
		
		weight = 5,
		
		cargo = {
			["Copper Ingots"] = 4,
			["Leather"] = 20,
			["Uncut Gems"] = 20,
			["Jewelry"] = 20,
			["Food"] = 20,
			["Fish"] = 20,
			["Tools"] = 20,
			["Textiles"] = 20,
			["Grain"] = 24,
		}
	},
	["10 Ton Ballast Wagon"] = {
		page = "Ballast Wagon",
		type = "cargo",
		image = "Screenshot 2023-07-20 031422.png",
		buy_price = 848,
		
		weight = 5,
		
		cargo = {
			["Iron Ore"] = 5,
			["Bauxite Ore"] = 5,
			["Copper Ore"] = 5,
			["Gold Ore"] = 5,
			["Coal"] = 5,
			["Gravel"] = 5,
			["Sand"] = 5,
			["Clay"] = 5,
			["Wood Pulp"] = 5,
			
			["Grain"] = 18,
			["Rum"] = 20,
			["Cordwood"] = 6,
		}
	},
	["20' Heavy Stake Wagon"] = {
		page = "Heavy_Well_Wagon",
		type = "cargo",
		image = "Heavywellwagon.webp",
		buy_price = 1176,
		
		weight = 13.8,
		
		cargo = {
			["Logs"] = 9.7,
			["Rails"] = 8,
			["Pipes"] = 8,
			["Iron Ingots"] = 4.8,
			["Copper Ingots"] = 5.4,
			["Machinery"] = 1,
			["Beams"] = 6,
		}
	},
	["10 Ton Tank Wagon"] = {
		page = "10_Ton_Tank_Wagon",
		type = "cargo",
		image = "10TTankThumb.png",
		buy_price = 1248,
		
		weight = 6,
		
		cargo = {
			["Grease"] = 6,
			["Chemicals"] = 6,
			["Crude Oil"] = 6,
			["Water"] = 6,
			["Kerosene"] = 28,
			["Rum"] = 28,
		}
	},
	["25' Stake Wagon"] = {
		page = "Stake_Wagons",
		type = "cargo",
		image = "Screenshot 2023-07-20 030507.png",
		buy_price = 1485,
		
		weight = 10,
		
		cargo = {
			["Logs"] = 10.4,
			["Rails"] = 8,
			["Pipes"] = 12,
			["Iron Ingots"] = 4,
			["Copper Ingots"] = 4,
			["Aluminium Ingots"] = 8,
			["Beams"] = 5.2,
		}
	},
	["16t Hopper Wagon"] = {
		page = "16t_Hopper_Wagon",
		type = "cargo",
		image = "16tHopperThumb.jpg",
		buy_price = 1646,
		
		weight = 8.3,
		
		cargo = {
			["Iron Ore"] = 11.1,
			["Bauxite Ore"] = 11.1,
			["Copper Ore"] = 11.1,
			["Gold Ore"] = 11.1,
			["Coal"] = 11.1,
			
			["Gravel"] = 11.1,
			["Sand"] = 11.1,
			["Clay"] = 11.1,
			["Wood Pulp"] = 11.1,
		}
	},
	["27' Cattle Van"] = {
		page = "Cattle_Van",
		type = "cargo",
		image = "Screenshot 2023-07-20 031855.png",
		buy_price = 1890,
		
		weight = 15,
		
		cargo = {
			["Cattle"] = 4,
		}
	},
	["14 Ton Open Wagon"] = {
		page = "Open_Wagon",
		type = "cargo",
		image = "Open_wagon_default.png",
		buy_price = 1973,
		
		weight = 7.9,
		paintable = true,
		
		cargo = {
			["Iron Ore"] = 8.1,
			["Bauxite Ore"] = 8.1,
			["Copper Ore"] = 8.1,
			["Gold Ore"] = 8.1,
			["Coal"] = 8.1,
			["Gravel"] = 8.1,
			["Sand"] = 8.1,
			["Clay"] = 8.1,
			["Wood Pulp"] = 8.1,
			
			["Rum"] = 42.1,
			["Grain"] = 31.2,
			["Lumber"] = 5.9,
			["Bricks"] = 5.9,
			["Cordwood"] = 11.3,
		}
	},
	["16 Ton Tank Wagon"] = {
		page = "16_Ton_Tank_Wagon",
		type = "cargo",
		image = "16TonTankWagon.png",
		buy_price = 1998,
		
		weight = 6,
		paintable = true,
		
		cargo = {
			["Grease"] = 12.6,
			["Chemicals"] = 12.6,
			["Crude Oil"] = 12.6,
			["Water"] = 12.6,
			["Kerosene"] = 44.2,
			["Rum"] = 44.2,
		}
	},
	["18 Ton Covered Van"] = {
		page = "Covered_Van",
		type = "cargo",
		image = "Covered_van_default.png",
		buy_price = 2037,
		
		weight = 8.1,
		paintable = true,
		
		cargo = {
			["Copper Ingots"] = 4,
			["Leather"] = 33.1,
			["Food"] = 33.1,
			["Fish"] = 33.1,
			["Tools"] = 41.4,
			["Textiles"] = 33.1,
			["Jewelry"] = 33.1,
			["Uncut Gems"] = 33.1,
			["Grain"] = 49.5,
		}
	},
	["20t Brake Van"] = {
		page = "Brake_Van",
		type = "cargo",
		image = nil,
		buy_price = 2190,
		
		weight = 21,
		paintable = true,
		
		description = "Holds up to 4 players.",
	},
	["20' Passenger Wagon"] = {
		page = "20' Passenger Wagon",
		type = "cargo",
		image = "Passenger Wagon QV.png",
		buy_price = 2037,
		
		weight = 11.1,
		paintable = true,
		
		description = "Holds up to 8 players.",
	},
	["22' Flat Bulkhead"] = {
		page = "Flat_Bulkhead",
		type = "cargo",
		image = nil,
		buy_price = 2235,
		
		weight = 13.5,
		
		cargo = {
			["Iron Ingots"] = 3,
			["Copper Ingots"] = 3,
			["Aluminium Ingots"] = 3,
			["Cordwood"] = 23.6,
			["Food"] = 21,
			["Tools"] = 14,
			["Cut Stone"] = 14,
			["Lumber"] = 10,
			["Bricks"] = 10,
			["Leather"] = 21,
			["Paper"] = 4,
		}
	},
	["20 Ton Hopper Wagon"] = {
		page = "20_Ton_Hopper_Wagon",
		type = "cargo",
		image = "HeavyHopperThumb.png",
		buy_price = 2396,
		
		weight = 9.8,
		paintable = true,
		
		cargo = {
			["Iron Ore"] = 13.5,
			["Bauxite Ore"] = 13.5,
			["Copper Ore"] = 13.5,
			["Gold Ore"] = 13.5,
			["Coal"] = 13.5,
			
			["Gravel"] = 13.5,
			["Sand"] = 13.5,
			["Clay"] = 13.5,
			["Wood Pulp"] = 13.5,
		}
	},

	["KdNS Type 2An'2 Class A0"] = {
		page = "Class_A0",
		short_name = "Class A0",
		type = "locomotive",
		subtype = "KdNS",
		image = "Wiki image.png",
		buy_price = 5114,
		
		weight = 9.1,
		
		locomotive = {
			max_speed = 26,
			max_coal = 0,
			max_power = 11737
		},
	    description = "Starter engine for [[Misty Summit]]."
	},
	["RSR Type B'n2st Class A1"] = {
		page = "Class_A1",
		short_name = "Class A1",
		type = "locomotive",
		subtype = "RSR",
		image = "ClassA1.png",
		buy_price = 6314,
		
		weight = 12.3,
		
		locomotive = {
			max_speed = 21,
			max_coal = 0,
			max_power = 14671
		}
	},
	["RSR Type B'n2 Class A1-1"] = {
		page = "Class_A1",
		short_name = "Class A1-1",
		type = "locomotive",
		subtype = "RSR",
		image = "Class A1-1.png",
		buy_price = nil,
		
		weight = 21,
		
		locomotive = {
			max_speed = 21,
			max_coal = 0,
			max_power = 14671
		},
		description = "Starter engine for [[Stormy Coast]]. Identical to the [[Class A1]], but missing the saddle tank."
	},
	["StiG Type Dn'WT Coffeepot"] = {
		page = "Coffeepot",
		short_name = "Coffeepot",
		type = "locomotive",
		subtype = "StiG",
		image = "CoffeepotMain.png",
		buy_price = 7214,
		
		weight = 14.1,
		
		locomotive = {
			max_speed = 14,
			max_coal = 400,
			max_power = 15539
		},
	},
	["RSR Type 1B'n2st Class A2"] = {
		page = "Class_A2",
		short_name = "Class A2",
		type = "locomotive",
		subtype = "RSR",
		image = "ClassA2.png",
		buy_price = 7064,
		
		weight = 15.8,
		
		locomotive = {
			max_speed = 26,
			max_coal = 0,
			max_power = 13796
		},
	
		description = "Starter engine for [[Maple Ridge]]."
	},
	["RSR Type 1A1t Class C"] = {
		page = "Class_C",
		short_name = "Class C",
		type = "locomotive",
		subtype = "RSR",
		image = "Classc.png",
		buy_price = 9462,
		
		weight = 21.5,
		
		locomotive = {
			max_speed = 33,
			max_coal = 650,
			max_power = 9769
		},
	
		description = "Starter engine for most maps."
	},
	["RSR Type 1BST Class A"] = {
		page = "Class_A",
		short_name = "Class A",
		type = "locomotive",
		subtype = "RSR",
		image = "Classa.png",
		buy_price = 10197,
		not_in_shop = true,
		
		weight = 21.5,
		
		locomotive = {
			max_speed = 26,
			max_coal = 320,
			max_power = 15522
		},
	
		description = "Replaced with Class A1 and Class A2 on July 31st 2023. Its default color is a unique soft blue inaccessible from the shop."
	},
	["KdNS Type Bn'2 Class D1"] = {
		page = "Class_D1",
		short_name = "Class D1",
		type = "locomotive",
		subtype = "KdNS",
		image = "ClassD1Main.png",
		buy_price = 11114,
		
		weight = 22.6,
		
		locomotive = {
			max_speed = 24,
			max_coal = 0,
			max_power = 23411
		},
	
		description = "Starter engine for [[Hazel Sierra]]."
	},
	["RSR Type C'n2 Class G"] = {
		page = "Class_G",
		short_name = "Class G",
		type = "locomotive",
		subtype = "RSR",
		image = "Classg.png",
		buy_price = 14152,
		
		weight = 26.5,
		
		locomotive = {
			max_speed = 19,
			max_coal = 0,
			max_power = 29809
		},
	},
	["RSR Type 1A1'N2 Class F"] = {
		page = "Class_F",
		short_name = "Class F",
		type = "locomotive",
		subtype = "RSR",
		image = "F class.png",
		buy_price = 17555,
		
		weight = 25.5,
		
		locomotive = {
			max_speed = 41,
			max_coal = 0,
			max_power = 20684
		},
	},
	["KdNS Type C'nt Class N"] = {
		page = "Class_N",
		short_name = "Class N",
		type = "locomotive",
		subtype = "KdNS",
		image = "N class.png",
		buy_price = 19602,
		
		weight = 26.5,
		
		locomotive = {
			max_speed = 19,
			max_coal = 700,
			max_power = 25048
		},
	},
	["RSR Type B1'n2t Class E"] = {
		page = "Class_E",
		short_name = "Class E",
		type = "locomotive",
		subtype = "RSR",
		image = "Classe.png",
		buy_price = 20817,
		
		weight = 26,
		
		locomotive = {
			max_speed = 26,
			max_coal = 1080,
			max_power = 20527
		},
	},
	["KdNS Type C'n2 Class B2"] = {
		page = "Class_B2",
		short_name = "Class B2",
		type = "locomotive",
		subtype = "KdNS",
		image = "Screenshot 2023-12-21 at 12.32.15 PM.png",
		buy_price = 23652,
		
		weight = 31.5,
		
		locomotive = {
			max_speed = 29,
			max_coal = 0,
			max_power = 32466
		},
	},
    ["RSR Type 1B'WT Class I"] = {
		page = "Class_I",
		short_name = "Class I",
		type = "locomotive",
		subtype = "RSR",
		image = "RSR Class I.png",
		buy_price = 25655,
		
		weight = 33,
		
		locomotive = {
			max_speed = 46,
			max_coal = 750,
			max_power = 24513
		},
	},
	["RSR Type C'N2 Class K1"] = {
		page = "Class_K1",
		short_name = "Class K1",
		type = "locomotive",
		subtype = "RSR",
		image = "ClassK1Main.png",
		buy_price = 26244,
		
		weight = 32.9,
		
		locomotive = {
			max_speed = 34,
			max_coal = 0,
			max_power = 34348
		},
	},
	["KdNS Type 2'B'n2 Class B"] = {
		page = "Class_B",
		short_name = "Class B",
		type = "locomotive",
		subtype = "KdNS",
		image = "ClassBSide.png",
		buy_price = 26652,
		
		weight = 31.5,
		
		locomotive = {
			max_speed = 56,
			max_coal = 0,
			max_power = 30653
		},
	},
	["RSR Type B2'N2 Class J1"] = {
		page = "Class_J1",
		short_name = "Class J1",
		type = "locomotive",
		subtype = "RSR",
		image = "J1.png",
		buy_price = 27111,
		
		weight = 35.5,
		
		locomotive = {
			max_speed = 32,
			max_coal = 0,
			max_power = 37270
		},
	},
	["RSR Type 1C'N2 Class J2"] = {
		page = "Class_J2",
		short_name = "Class J2",
		type = "locomotive",
		subtype = "RSR",
		image = "J2 Right side.png",
		buy_price = 27774,
		
		weight = 35.5,
		
		locomotive = {
			max_speed = 38,
			max_coal = 0,
			max_power = 39796
		},
	},
	["KdNS Type Dn Class H"] = {
		page = "Class_H",
		short_name = "Class H",
		type = "locomotive",
		subtype = "KdNS",
		image = "H class.png",
		buy_price = 32652,
		
		weight = 40.5,
		
		locomotive = {
			max_speed = 19,
			max_coal = 1372,
			max_power = 44478
		},
	},
    ["RSR Type C1'T Class P"] = {
		page = "Class_P",
		short_name = "Class P",
		type = "locomotive",
		subtype = "RSR",
		image = "Screenshot 2025-02-27 214340.png",
		buy_price = 34655,
		
		weight = 37,
		
		locomotive = {
			max_speed = 51,
			max_coal = 1440,
			max_power = 30047
		},
	},
	["RSR Type C1'NST Class K2"] = {
		page = "Class_K2",
		short_name = "Class K2",
		type = "locomotive",
		subtype = "RSR",
		image = "ClassK2Main.png",
		buy_price = 33744,
		
		weight = 42.9,
		
		locomotive = {
			max_speed = 24,
			max_coal = 1300,
			max_power = 41991
		},
	},
	["KdNS Type Dn Class H2"] = {
		page = "Class_H2",
		short_name = "Class H2",
		type = "locomotive",
		subtype = "KdNS",
		image = "Class H2 Natasha TLR.png",
		buy_price = 37152,
		
		weight = 39.8,
		
		locomotive = {
			max_speed = 30,
			max_coal = 0,
			max_power = 45227
		},
	},
}

function numWithCommas(n) -- we love stack overflow
	return tostring(math.floor(n)):reverse():gsub("(%d%d%d)","%1,")
		:gsub(",(%-?)$","%1"):reverse()
end -- todo: move into a helper function

function getRollingStockPageRow(frame)
	-- Stock Name|Shortened Name
	local stock, short_name = frame.args[1], frame.args[2]
	
	local out = "|-\n| style=\"text-align:center;\" |<u>[[" .. module.rolling_stock[stock].page .. "|" .. (short_name and module.rolling_stock[stock].short_name or stock) ..  "]]</u>\n"
	.."\n|" ..(module.rolling_stock[stock].image and ("[[File:" .. (module.rolling_stock[stock].image) .. "|thumb|link=" .. module.rolling_stock[stock].page .. "]]") or "")
	.."\n|style=\"text-align:center;\"|"
	
	if not module.rolling_stock[stock].buy_price then
		out = out .. "Not available to purchase."
	else
		if module.rolling_stock[stock].not_in_shop then
			out = out .. "No longer available to purchase. Was: "
		end
		out = out .. "$" .. numWithCommas(module.rolling_stock[stock].buy_price)
		.."<br/><i>$" .. numWithCommas(math.ceil(module.rolling_stock[stock].buy_price * 0.8 + 10))  --[[
			Trainworks multiplier and also add 10 for some reason?
		]] .. " w/ Trainworks</i>"
	end
	
	out = out .. "\n| style=\"text-align:center;\" |" .. module.rolling_stock[stock].weight .. "t"
	
	out = out .. "\n| style=\"text-align:center;\" |"
	if module.rolling_stock[stock].cargo then
		out = out .. "Holds cargo<br/>"
		
		local sortable_cargo = {}
		for name, amount in pairs(module.rolling_stock[stock].cargo) do
			table.insert(sortable_cargo, {name = name, amount = amount})
		end
		table.sort(sortable_cargo, function(a, b) return a.amount > b.amount end)
		
		for _, info in pairs(sortable_cargo) do
			out = out .. info.amount .. " [[".. info.name .. "]], "
		end
		out = out:sub(1, out:len()-2) -- remove trailing comma
	end
	
	if module.rolling_stock[stock].locomotive then
		out = out .. "Locomotive Stats:"
		.."<br/>Max Power: " .. module.rolling_stock[stock].locomotive.max_power
		.."<br/>Max Speed: " .. module.rolling_stock[stock].locomotive.max_speed
		.."<br/>Max Coal: " .. module.rolling_stock[stock].locomotive.max_coal
	end
	
	if module.rolling_stock[stock].description then
		out = out .. "<br/>" .. module.rolling_stock[stock].description
	end
	
	return out
end

function module.getRollingStockStorage(frame)
	local stock = frame.args[1]
	out =  ""
		
	local sortable_cargo = {}
	for name, amount in pairs(module.rolling_stock[stock].cargo) do
		table.insert(sortable_cargo, {name = name, amount = amount})
	end
	table.sort(sortable_cargo, function(a, b) return a.amount > b.amount end)
	
	for _, info in pairs(sortable_cargo) do
		out = out .. info.amount .. " [[".. info.name .. "]], "
	end
	out = out:sub(1, out:len()-2) -- remove trailing comma
	
	return out
end

function module.getRollingStockPage(frame)
	local stock_type, short_name = frame.args[1], frame.args[2]
	short_name = short_name == "true"
	
	local out = ""
	
	local sortable_stock = {}
	for name, info in pairs(module.rolling_stock) do
		if info.type == stock_type then
			info.name = name
			table.insert(sortable_stock, info)
		end
	end
	table.sort(sortable_stock, function(a, b) return (a.buy_price or math.huge) < (b.buy_price or math.huge) end)
	for _, info in pairs(sortable_stock) do
		out = out .. getRollingStockPageRow({args = {info.name, short_name}}) .. "\n"
	end
	
	return out
end

function module.getCargoStorage(frame)
	local valid_stock = {}
	
	for stock, info in pairs(module.rolling_stock) do
		if info.cargo and info.cargo[frame.args[1]] then -- continue isnt a valid keyword :c (i blame greg)
			--out = out .. stock .. ": " .. info.cargo[frame.args[1]]
			-- i write these comments for nobody, nobody will even open this page
			table.insert(valid_stock, {name = stock, page = info.page, amount = info.cargo[frame.args[1]]})
		end
	end
	
	table.sort(valid_stock, function(a, b) return a.amount > b.amount end)
	
	for index, info in pairs(valid_stock) do
		valid_stock[index] = "[[" .. info.page .. "|" .. info.name .. "]]: " .. info.amount
	end
	
	return table.concat(valid_stock, "<br/>")
end

function module.getStringList(frame)
	-- Stock Type|Formatting String|Separator
	local stock_type, formatting, separator, stock_subtype = frame.args[1], (frame.args[2] or "%s"), (frame.args[3] or ""), (frame.args[4])
	
	local out = ""
	
	local sortable_stock = {}
	
	for name, info in pairs(module.rolling_stock) do
		if ((not stock_type) or info.type == stock_type) and ((not stock_subtype) or info.subtype == stock_subtype) then
			info.name = name
			table.insert(sortable_stock, info)
		end
	end
	table.sort(sortable_stock, function(a, b) return (a.buy_price or math.huge) < (b.buy_price or math.huge) end)
	
	for _, info in pairs(sortable_stock) do
		out = out .. formatting:gsub("{name}", info.short_name or info.name):gsub("{page}", info.page or info.name) .. (separator or "")
	end
	
	out = out:sub(1, out:len()-separator:len()) -- remove trailing comma
	out = out:gsub("\\([nt])", {n="\n", t="\t"}) -- fix formatting
	return out
end

function module.getValue(frame)
	-- Stock Name|Property
	local stock, property = frame.args[1], frame.args[2]
	if not stock then
		stock = page_name
	end
	return module.rolling_stock[stock][property]
end

return module