start the next production cycle in the tick the last one completed

This commit is contained in:
2026-08-12 21:27:25 +02:00
parent dd061082fb
commit 0b859bd1a4
2 changed files with 83 additions and 32 deletions

View File

@@ -513,17 +513,22 @@ void BuildingSystem::tickProduction(FactoryState& state, Tick currentTick)
// recipe is selected or auto-chosen.
if (building.production)
{
if (currentTick >= building.production->completesAt)
if (currentTick < building.production->completesAt)
{
for (const Item& item : building.production->chosenOutputs)
{
building.outputBuffer.items.push_back(item);
}
building.production = std::nullopt;
continue;
}
// Whether we just completed or are still running, do not start
// another cycle in the same tick.
continue;
for (const Item& item : building.production->chosenOutputs)
{
building.outputBuffer.items.push_back(item);
}
building.production = std::nullopt;
// Fall through to the start attempt below rather than idling for a tick,
// so a cycle takes exactly its recipe duration and a building fed to
// capacity produces at the configured rate (REQ-MAT-CYCLE). The start
// code runs once per building per tick, so at most one cycle begins here
// even when a duration rounds to zero ticks. The outputs just deposited
// count against the space check, so a cycle whose output no longer fits
// waits, exactly as it would have on the following tick.
}
// Idle: gather the candidate recipes to try. Auto-recipe buildings
@@ -612,26 +617,29 @@ void BuildingSystem::tickShipyardProduction(FactoryState& state, Tick currentTic
// If a cycle is in progress, check for completion.
if (building.production)
{
if (currentTick >= building.production->completesAt)
if (currentTick < building.production->completesAt)
{
if (!building.outputPorts.empty())
{
const Port& p = building.outputPorts[0];
const QVector2D spawnPos(p.tile.x() + 0.5f, p.tile.y() + 0.5f);
// A shipyard builds exactly what the player configured and
// paid for. When no layout is set it produces a bare hull, so
// pass an explicit empty layout rather than nullopt: the latter
// would make ShipSystem fall back to the schematic's
// defaultModules (a wave-only loadout) and yield free weapons.
const std::optional<ShipLayoutConfig> layout =
building.shipLayout.has_value()
? building.shipLayout
: std::make_optional<ShipLayoutConfig>();
m_spawnShip(building.recipeId, spawnPos, layout);
}
building.production = std::nullopt;
continue;
}
continue;
if (!building.outputPorts.empty())
{
const Port& p = building.outputPorts[0];
const QVector2D spawnPos(p.tile.x() + 0.5f, p.tile.y() + 0.5f);
// A shipyard builds exactly what the player configured and
// paid for. When no layout is set it produces a bare hull, so
// pass an explicit empty layout rather than nullopt: the latter
// would make ShipSystem fall back to the schematic's
// defaultModules (a wave-only loadout) and yield free weapons.
const std::optional<ShipLayoutConfig> layout =
building.shipLayout.has_value()
? building.shipLayout
: std::make_optional<ShipLayoutConfig>();
m_spawnShip(building.recipeId, spawnPos, layout);
}
building.production = std::nullopt;
// Fall through and start the next cycle in this same tick, so a ship takes
// exactly its computed production time (REQ-BLD-SHIPYARD), as for the
// recipe buildings in tickProduction.
}
// Build combined materials list (base + modules).