diff --git a/src/droiddef.h b/src/droiddef.h index d84255fd1fe..5fd70e4d999 100644 --- a/src/droiddef.h +++ b/src/droiddef.h @@ -56,6 +56,8 @@ typedef std::vector OrderList; struct DROID_TEMPLATE : public BASE_STATS { DROID_TEMPLATE(); + bool operator==(const DROID_TEMPLATE& other) const; + bool operator!=(const DROID_TEMPLATE& other) const; BODY_STATS* getBodyStats() const; BRAIN_STATS* getBrainStats() const; @@ -83,6 +85,7 @@ struct DROID_TEMPLATE : public BASE_STATS bool prefab; ///< Not player designed, not saved, never delete or change bool stored; ///< Stored template bool enabled; ///< Has been enabled + DROID_TEMPLATE* next; ///< The new template }; static inline DROID_TEMPLATE *castDroidTemplate(BASE_STATS *stats) diff --git a/src/hci/manufacture.cpp b/src/hci/manufacture.cpp index 22fd363eda1..511c31080a1 100644 --- a/src/hci/manufacture.cpp +++ b/src/hci/manufacture.cpp @@ -419,7 +419,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->psSubject && manufacture->psSubject->next) ? + 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 6e5b4477a58..dea42bd8131 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -6232,6 +6232,12 @@ void releaseProduction(STRUCTURE *psBuilding, QUEUE_MODE mode) void doNextProduction(STRUCTURE *psStructure, DROID_TEMPLATE *current, QUEUE_MODE mode) { + if (current && current->next) + { + structSetManufacture(psStructure, current->next, ModeQueue); + return; + } + DROID_TEMPLATE *psNextTemplate = factoryProdUpdate(psStructure, current); if (psNextTemplate != nullptr) @@ -6327,6 +6333,21 @@ void factoryProdAdjust(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate, bool ASSERT_OR_RETURN(, psTemplate != nullptr, "NULL template"); FACTORY *psFactory = &psStructure->pFunctionality->factory; + + // the droid template being produced is different from the one we want to make, + // save new template into the old one + if (psFactory->psSubject && *psFactory->psSubject != *psTemplate) + { + auto it = std::find_if(apsTemplateList.begin(), apsTemplateList.end(), [psFactory](const DROID_TEMPLATE *templ) { + return *templ == *psFactory->psSubject; + }); + + if (it == apsTemplateList.end()) + { + psFactory->psSubject->next = psTemplate; + } + } + if (psFactory->psAssemblyPoint->factoryInc >= asProductionRun[psFactory->psAssemblyPoint->factoryType].size()) { asProductionRun[psFactory->psAssemblyPoint->factoryType].resize(psFactory->psAssemblyPoint->factoryInc + 1); // Don't have a production list, create it. @@ -6376,6 +6397,10 @@ void factoryProdAdjust(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate, bool //need to check if this was the template that was mid-production if (getProduction(psStructure, FactoryGetTemplate(psFactory)).numRemaining() == 0) { + if (psFactory->psSubject && psFactory->psSubject->next) + { + return; + } doNextProduction(psStructure, FactoryGetTemplate(psFactory), ModeQueue); } else if (!StructureIsManufacturingPending(psStructure)) diff --git a/src/template.cpp b/src/template.cpp index b7e2e317911..3c6ec424508 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -519,11 +519,28 @@ DROID_TEMPLATE::DROID_TEMPLATE() // This constructor replaces a memset in scrAs , prefab(false) , stored(false) , enabled(false) + , next(nullptr) { std::fill_n(asParts, DROID_MAXCOMP, static_cast(0)); std::fill_n(asWeaps, MAX_WEAPONS, 0); } +bool DROID_TEMPLATE::operator==(const DROID_TEMPLATE &other) const +{ + return numWeaps == other.numWeaps && + droidType == other.droidType && + multiPlayerID == other.multiPlayerID && + prefab == other.prefab && + enabled == other.enabled && + std::equal(std::begin(asParts), std::end(asParts), std::begin(other.asParts)) && + std::equal(std::begin(asWeaps), std::end(asWeaps), std::begin(other.asWeaps)); +} + +bool DROID_TEMPLATE::operator!=(const DROID_TEMPLATE &other) const +{ + return !(*this == other); +} + BODY_STATS* DROID_TEMPLATE::getBodyStats() const { return &asBodyStats[asParts[COMP_BODY]];