diff --git a/src/hci/manufacture.cpp b/src/hci/manufacture.cpp index 22fd363eda1..f02174c520b 100644 --- a/src/hci/manufacture.cpp +++ b/src/hci/manufacture.cpp @@ -168,7 +168,8 @@ void ManufactureController::updateManufactureOptionsList() DROID_TEMPLATE *ManufactureController::getObjectStatsAt(size_t objectIndex) const { auto factory = getFactoryOrNullptr(getObjectAt(objectIndex)); - return factory == nullptr ? nullptr : factory->psSubject; + auto subject = factory->psSubjectObsolete ? factory->psSubjectObsolete.get() : factory->psSubject; + return factory == nullptr ? nullptr : subject; } void ManufactureController::refresh() @@ -419,7 +420,10 @@ class ManufactureStatsButton: public StatsButton auto productionRemaining = getProduction(factory, droidTemplate).numRemaining(); if (productionRemaining > 0 && factory && StructureIsManufacturingPending(factory)) { - productionRunSizeLabel->setString(WzString::fromUtf8(astringf("%d", productionRemaining))); + auto manufacture = StructureGetFactory(factory); + productionRunSizeLabel->setString(manufacture->psSubjectObsolete ? + WzString::fromUtf8(astringf("1+%d", productionRemaining)) : + WzString::fromUtf8(astringf("%d", productionRemaining))); productionRunSizeLabel->show(); } else diff --git a/src/structure.cpp b/src/structure.cpp index f0db55cb980..24f78f87f87 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -1099,14 +1099,20 @@ static void refundFactoryBuildPower(STRUCTURE *psBuilding) ASSERT_OR_RETURN(, psBuilding && psBuilding->isFactory(), "structure not a factory"); FACTORY *psFactory = &psBuilding->pFunctionality->factory; + // We started building, so give the power back that was used. + if (psFactory->psSubjectObsolete) + { + if (psFactory->buildPointsRemaining < (int)calcTemplateBuild(psFactory->psSubjectObsolete.get())) + { + addPower(psBuilding->player, calcTemplatePower(psFactory->psSubjectObsolete.get())); + } + } if (psFactory->psSubject) { if (psFactory->buildPointsRemaining < (int)calcTemplateBuild(psFactory->psSubject)) { - // We started building, so give the power back that was used. addPower(psBuilding->player, calcTemplatePower(psFactory->psSubject)); } - } } @@ -2071,6 +2077,7 @@ static bool setFunctionality(STRUCTURE *psBuilding, STRUCTURE_TYPE functionType) FACTORY *psFactory = &psBuilding->pFunctionality->factory; psFactory->psSubject = nullptr; + psFactory->psSubjectObsolete = nullptr; // Default the secondary order - AB 22/04/99 psFactory->secondaryOrder = DSS_ARANGE_LONG | DSS_REPLEV_NEVER | DSS_ALEV_ALWAYS | DSS_HALT_GUARD; @@ -3216,7 +3223,14 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) case REF_CYBORG_FACTORY: case REF_VTOL_FACTORY: { - pSubject = psStructure->pFunctionality->factory.psSubject; + if (psStructure->pFunctionality->factory.psSubjectObsolete) + { + pSubject = psStructure->pFunctionality->factory.psSubjectObsolete.get(); + } + else + { + pSubject = psStructure->pFunctionality->factory.psSubject; + } structureMode = REF_FACTORY; //check here to see if the factory's commander has died if (psStructure->pFunctionality->factory.psCommander && @@ -3508,11 +3522,23 @@ static void aiUpdateStructure(STRUCTURE *psStructure, bool isMission) //script callback, must be called after factory was flagged as idle if (bDroidPlaced) { + bool bObsolete = false; + if (psFactory->psSubjectObsolete) + { + pSubject = psFactory->psSubject; + bObsolete = true; + } + //reset the start time psFactory->timeStarted = ACTION_START_TIME; psFactory->psSubject = nullptr; + psFactory->psSubjectObsolete = nullptr; doNextProduction(psStructure, (DROID_TEMPLATE *)pSubject, ModeImmediate); + if (bObsolete) + { + factoryProdAdjust(psStructure, (DROID_TEMPLATE *)pSubject, true); + } cbNewDroid(psStructure, psDroid); } @@ -6169,6 +6195,7 @@ void cancelProduction(STRUCTURE *psBuilding, QUEUE_MODE mode, bool mayClearProdu //clear the factory's subject refundFactoryBuildPower(psBuilding); psFactory->psSubject = nullptr; + psFactory->psSubjectObsolete = nullptr; delPowerRequest(psBuilding); } @@ -6329,7 +6356,7 @@ void factoryProdAdjust(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate, bool FACTORY *psFactory = &psStructure->pFunctionality->factory; // the droid template being produced is different from the one we want to make, - // cancel the current production instead of increasing the counter + // update the current production instead of increasing the counter if (psFactory->psSubject && *psFactory->psSubject != *psTemplate) { bool bFound = false; @@ -6344,9 +6371,9 @@ void factoryProdAdjust(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate, bool if (!bFound) { - cancelProduction(psStructure, ModeImmediate, false); - factoryProdAdjust(psStructure, psTemplate, add); - return; + psFactory->psSubjectObsolete = std::make_unique(); + *psFactory->psSubjectObsolete = *psFactory->psSubject; + *psFactory->psSubject = *psTemplate; } } diff --git a/src/structuredef.h b/src/structuredef.h index 91db40ced26..35837b1f511 100644 --- a/src/structuredef.h +++ b/src/structuredef.h @@ -205,6 +205,8 @@ struct FACTORY UBYTE loopsPerformed; /* how many times the loop has been performed*/ DROID_TEMPLATE *psSubject; ///< The subject the structure is working on. DROID_TEMPLATE *psSubjectPending; ///< The subject the structure is going to working on. (Pending = not yet synchronised.) + std::unique_ptr + psSubjectObsolete; ///< Old droid template that will be deleted after production ends. StatusPending statusPending; ///< Pending = not yet synchronised. unsigned pendingCount; ///< Number of messages sent but not yet processed. UDWORD timeStarted; /* The time the building started on the subject*/