Steam Locomotive Continued (2.0 + SE)


A steam locomotive fuelled by real coal, wood or solid fuel plus water pumped straight into its tank. Fuel and water are consumed gradually to build up steam pressure over time (fire, steam and water gauges in a boiler panel on the locomotive's window); pressure caps your top speed, and it decays if you let the fire or the water run dry. No water on board means no pressure, no matter how much fuel is loaded. Coal and solid fuel give the full speed ceiling; wood is slower but cleaner. Slower than diesel overall. Third step of the steam -> diesel -> electric train progression ladder. Locomotive art from Steam Locomotive (steamtrain-redux-redux) by IonShield (Unlicense/public domain). Framework based on fluidTrains by ksmonkey123 (MIT).

Content
2 months ago
2.0
229
Transportation Trains Fluids

b Firebox ejects valid fuel under overhaul mods (pyanodons) - cause + patch on request

a month ago

Really enjoying the steam → diesel → electric ladder, thanks for keeping these going.

Running 0.5.4 under pyanodons I hit two issues that make the locomotive close to unusable there. Both are one-line-ish fixes and neither changes vanilla behaviour, so I've included patches in case they're useful.

1. Every fuel except coal is ejected into the player's inventory

Repro: put any pyanodons chemical-category fuel (coke, etc.) into the firebox. It's accepted by the burner, then on the next update it's raked out and handed back to the nearest player — or spilled on the ground if nobody's nearby.

Cause is the allowlist in control.lua:

local FUELS = {
    coal = 190 / 216,
    wood = (190 * 0.8) / 216,
    ["solid-fuel"] = 190 / 216
}

used as a validity gate:

if slot1.valid_for_read and not FUELS[slot1.name] then
    ...
    eject_item(loco, name, count)
    slot1.clear()
end

Any item not named there is rejected regardless of whether the burner accepts it, so overhauls that add their own fuels lose them.

Since 2.0 fuel inventories hard-reject items whose category the burner doesn't carry, anything that reaches slot 1 is already known-burnable — the allowlist is doing a check the engine has done. Suggested fix: keep the table as tuned ceiling overrides rather than an allowlist, default everything else to coal's ceiling, and restrict the ejection branch to the daredevil fuels. Coal/wood/solid-fuel keep their exact current speeds.

2. Wood can't be inserted at all under pyanodons

Different mechanism — no script involved. prototypes/entities.lua hardcodes:

burner.fuel_categories = {"chemical"}

but pycoalprocessing moves wood into a new biomass category (prototypes/updates/base-updates.lua) and widens the vanilla locomotive to {"chemical", "biomass"} (prototypes/updates/entity-updates.lua). A chemical-only firebox therefore refuses wood at the slot.

Suggested fix, in data-final-fixes.lua — mirror whatever the vanilla locomotive ended up with:

local steam_loco = data.raw.locomotive and data.raw.locomotive["tp-steam-locomotive"]
local vanilla_loco = data.raw.locomotive and data.raw.locomotive["locomotive"]
local steam_burner = steam_loco and (steam_loco.burner or steam_loco.energy_source)
local vanilla_burner = vanilla_loco and (vanilla_loco.burner or vanilla_loco.energy_source)

if steam_burner and vanilla_burner and vanilla_burner.type == "burner" then
    local categories = vanilla_burner.fuel_categories
        or (vanilla_burner.fuel_category and {vanilla_burner.fuel_category})
    if categories and #categories > 0 then
        steam_burner.fuel_categories = table.deepcopy(categories)
        steam_burner.fuel_category = nil
    end
end

This needs no optional dependency — overhauls do this work in data-updates, and data-final-fixes always runs after every data-updates pass. In vanilla it's a no-op (copies {"chemical"} back onto itself).

Notes

  • Worth knowing: pyanodons also files rocket fuel under a jerry category, so the rocket-fuel daredevil path simply never triggers there — the engine rejects it at the slot. Nuclear fuel stays chemical, so that one still works.
  • I've been running both changes locally without trouble, but I haven't playtested the balance implications of non-vanilla fuels all sharing coal's speed ceiling — that's a judgement call that's yours to make, and deriving the ceiling from fuel_value instead would be the obvious alternative.
  • Happy to send the full unified diff against 0.5.4 (also touches changelog/info.json for a 0.5.5 bump) if that's easier than patching by hand — just say where.
a day ago

Thanks for this. I'll run it into the code and see if anything bad happens my end

a day ago

Both spot on, and the diagnoses saved me the digging — thank you. Fixed in 0.5.5. The allowlist is gone: it was re-checking something the engine already guarantees, exactly as you said. Fuels without a hand-tuned speed now derive their ceiling from fuel value relative to coal (capped, and floored so nothing crawls) rather than all sharing coal's — coal, wood and solid fuel are unchanged. The firebox also mirrors the vanilla locomotive's fuel categories in data-final-fixes, so wood works under py again. Amusingly, if py puts jerry on the vanilla locomotive, that mirror hands it to us too — so the rocket-fuel surprise may find you after all. No need for the diff; it was a small change and I wanted to walk each line myself.

New response