From 14f1833371f7da3286111133fc6ab3066d12c5e5 Mon Sep 17 00:00:00 2001 From: Nikolay Borodin Date: Fri, 13 Dec 2024 19:04:41 +0200 Subject: [PATCH 1/6] Cancel previous template when producing a new template in factories --- src/droiddef.h | 2 ++ src/structure.cpp | 23 +++++++++++++++++++++++ src/template.cpp | 16 ++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/droiddef.h b/src/droiddef.h index d84255fd1fe..b9e0fd6e559 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; diff --git a/src/structure.cpp b/src/structure.cpp index 6e5b4477a58..f0db55cb980 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -6327,6 +6327,29 @@ 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, + // cancel the current production instead of increasing the counter + if (psFactory->psSubject && *psFactory->psSubject != *psTemplate) + { + bool bFound = false; + for (auto templ : apsTemplateList) + { + if (*templ == *psFactory->psSubject) + { + bFound = true; + break; + } + } + + if (!bFound) + { + cancelProduction(psStructure, ModeImmediate, false); + factoryProdAdjust(psStructure, psTemplate, add); + return; + } + } + 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. diff --git a/src/template.cpp b/src/template.cpp index b7e2e317911..bbf83dae293 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -524,6 +524,22 @@ DROID_TEMPLATE::DROID_TEMPLATE() // This constructor replaces a memset in scrAs 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]]; From c2e40cd98f3bf075feeab2244803e71966f21afa Mon Sep 17 00:00:00 2001 From: Nikolay Borodin Date: Sat, 14 Dec 2024 14:51:35 +0200 Subject: [PATCH 2/6] Finish the previous template to proceed to the new one --- src/droiddef.h | 1 + src/hci/manufacture.cpp | 5 ++++- src/structure.cpp | 35 +++++++++++++++++++++-------------- src/template.cpp | 1 + 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/droiddef.h b/src/droiddef.h index b9e0fd6e559..5fd70e4d999 100644 --- a/src/droiddef.h +++ b/src/droiddef.h @@ -85,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 f0db55cb980..1073199f95b 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -6234,6 +6234,21 @@ void doNextProduction(STRUCTURE *psStructure, DROID_TEMPLATE *current, QUEUE_MOD { DROID_TEMPLATE *psNextTemplate = factoryProdUpdate(psStructure, current); + if (current) + { + auto it = std::find_if(apsTemplateList.begin(), apsTemplateList.end(), [current](const auto &templ) { + return *templ == *current; + }); + + if (it == apsTemplateList.end() && current->next) + { + structSetManufacture(psStructure, current->next, ModeImmediate); + // Increase the production counter, because we produced the old template + factoryProdAdjust(psStructure, current->next, true); + return; + } + } + if (psNextTemplate != nullptr) { structSetManufacture(psStructure, psNextTemplate, ModeQueue); // ModeQueue instead of mode, since production lists aren't currently synchronised. @@ -6329,24 +6344,16 @@ 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 + // save new template into the old one if (psFactory->psSubject && *psFactory->psSubject != *psTemplate) { - bool bFound = false; - for (auto templ : apsTemplateList) - { - if (*templ == *psFactory->psSubject) - { - bFound = true; - break; - } - } + auto it = std::find_if(apsTemplateList.begin(), apsTemplateList.end(), [psFactory](const auto &templ) { + return *templ == *psFactory->psSubject; + }); - if (!bFound) + if (it == apsTemplateList.end()) { - cancelProduction(psStructure, ModeImmediate, false); - factoryProdAdjust(psStructure, psTemplate, add); - return; + psFactory->psSubject->next = psTemplate; } } diff --git a/src/template.cpp b/src/template.cpp index bbf83dae293..3c6ec424508 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -519,6 +519,7 @@ 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); From ecec61fb4a33e94ee75e85568d57101c664dc7bf Mon Sep 17 00:00:00 2001 From: Nikolay Borodin Date: Sat, 14 Dec 2024 15:06:12 +0200 Subject: [PATCH 3/6] Simplify the code and use ModeQueue --- src/structure.cpp | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/structure.cpp b/src/structure.cpp index 1073199f95b..108859e0791 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -6234,19 +6234,12 @@ void doNextProduction(STRUCTURE *psStructure, DROID_TEMPLATE *current, QUEUE_MOD { DROID_TEMPLATE *psNextTemplate = factoryProdUpdate(psStructure, current); - if (current) + if (current && current->next) { - auto it = std::find_if(apsTemplateList.begin(), apsTemplateList.end(), [current](const auto &templ) { - return *templ == *current; - }); - - if (it == apsTemplateList.end() && current->next) - { - structSetManufacture(psStructure, current->next, ModeImmediate); - // Increase the production counter, because we produced the old template - factoryProdAdjust(psStructure, current->next, true); - return; - } + structSetManufacture(psStructure, current->next, ModeQueue); + // Increase the production counter, because we produced the old template + factoryProdAdjust(psStructure, current->next, true); + return; } if (psNextTemplate != nullptr) From 20f3cbcd9e3d51d62cf711abcab2eb6daaef0c42 Mon Sep 17 00:00:00 2001 From: Nikolay Borodin Date: Sat, 14 Dec 2024 15:16:42 +0200 Subject: [PATCH 4/6] Code refactoring --- src/structure.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structure.cpp b/src/structure.cpp index 108859e0791..218fb19d482 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -6232,8 +6232,6 @@ void releaseProduction(STRUCTURE *psBuilding, QUEUE_MODE mode) void doNextProduction(STRUCTURE *psStructure, DROID_TEMPLATE *current, QUEUE_MODE mode) { - DROID_TEMPLATE *psNextTemplate = factoryProdUpdate(psStructure, current); - if (current && current->next) { structSetManufacture(psStructure, current->next, ModeQueue); @@ -6242,6 +6240,8 @@ void doNextProduction(STRUCTURE *psStructure, DROID_TEMPLATE *current, QUEUE_MOD return; } + DROID_TEMPLATE *psNextTemplate = factoryProdUpdate(psStructure, current); + if (psNextTemplate != nullptr) { structSetManufacture(psStructure, psNextTemplate, ModeQueue); // ModeQueue instead of mode, since production lists aren't currently synchronised. @@ -6340,7 +6340,7 @@ void factoryProdAdjust(STRUCTURE *psStructure, DROID_TEMPLATE *psTemplate, bool // save new template into the old one if (psFactory->psSubject && *psFactory->psSubject != *psTemplate) { - auto it = std::find_if(apsTemplateList.begin(), apsTemplateList.end(), [psFactory](const auto &templ) { + auto it = std::find_if(apsTemplateList.begin(), apsTemplateList.end(), [psFactory](const DROID_TEMPLATE *templ) { return *templ == *psFactory->psSubject; }); From 1d429610584afb3ca723badf9857ea5dd9e62525 Mon Sep 17 00:00:00 2001 From: Nikolay Borodin Date: Sat, 14 Dec 2024 16:36:10 +0200 Subject: [PATCH 5/6] Removed factoryProdAdjust --- src/structure.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/structure.cpp b/src/structure.cpp index 218fb19d482..1b7dedbf01f 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -6235,8 +6235,6 @@ void doNextProduction(STRUCTURE *psStructure, DROID_TEMPLATE *current, QUEUE_MOD if (current && current->next) { structSetManufacture(psStructure, current->next, ModeQueue); - // Increase the production counter, because we produced the old template - factoryProdAdjust(psStructure, current->next, true); return; } From 4ce8671a8af51a3fddee7cdd9a08b32c55e7bf4e Mon Sep 17 00:00:00 2001 From: Nikolay Borodin Date: Sat, 14 Dec 2024 17:19:39 +0200 Subject: [PATCH 6/6] Fixed issues on queue overflow --- src/structure.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/structure.cpp b/src/structure.cpp index 1b7dedbf01f..dea42bd8131 100644 --- a/src/structure.cpp +++ b/src/structure.cpp @@ -6397,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))