diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp index ea5a60488e3..8b94a95d33e 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp @@ -470,8 +470,15 @@ void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) if( production->m_productionID == productionID ) { - // give the player the cost of the object back Player *player = getObject()->getControllingPlayer(); + +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix arcticdolphin 07/09/2026 No cancel once the batch has started producing. + if( production->getProductionQuantityRemaining() < production->getProductionQuantity() ) + return; +#endif + + // give the player the cost of the object back Money *money = player->getMoney(); money->deposit( production->m_objectToProduce->calcCostToBuild( player ), TRUE, FALSE ); @@ -659,7 +666,7 @@ UpdateSleepTime ProductionUpdate::update() // if we've become OBJECT_STATUS_SOLD, halt all production ... leave things in the // queue because if the sell process completes we get money back for them, for now we // will be just frozen in time - // Actually, there will be nothing in the queue since everything gets cancel/refunded + // Actually, there will usually be nothing in the queue since everything gets cancel/refunded // at the start of sell, but we still don't want to do anything here. // if( us->getStatusBits().test( OBJECT_STATUS_SOLD ) ) @@ -693,10 +700,17 @@ UpdateSleepTime ProductionUpdate::update() // Don't cancel dozers in the queue. jba. if (!production->getProductionObject()->isKindOf(KINDOF_DOZER)) { - +#if RETAIL_COMPATIBLE_CRC cancelUnitCreate(production->getProductionID()); return UPDATE_SLEEP_NONE; - +#else + // TheSuperHackers @bugfix arcticdolphin 07/09/2026 Only cancel an untouched batch. + if( production->getProductionQuantityRemaining() == production->getProductionQuantity() ) + { + cancelUnitCreate(production->getProductionID()); + return UPDATE_SLEEP_NONE; + } +#endif } } @@ -1134,24 +1148,28 @@ void ProductionUpdate::cancelAndRefundAllProduction() { // Empirically, in release the code can loop forever. So we limit to 100 passes. jba. [8/31/2003] const Int productionLimit = 100;// With luck, we never queue up 100 units. [8/31/2003] - Int i; - for (i=0; im_next; + + if( production->getProductionType() == PRODUCTION_UNIT ) + cancelUnitCreate( production->getProductionID() ); + else if( production->getProductionType() == PRODUCTION_UPGRADE ) + cancelUpgrade( production->getProductionUpgrade() ); + else { - if( m_productionQueue->getProductionType() == PRODUCTION_UNIT ) - cancelUnitCreate( m_productionQueue->getProductionID() ); - else if( m_productionQueue->getProductionType() == PRODUCTION_UPGRADE ) - cancelUpgrade( m_productionQueue->getProductionUpgrade() ); - else - { - // unknown production type - DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", - m_productionQueue->getProductionType() )); - return; - } + // unknown production type + DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", + production->getProductionType() )); + return; } + + production = nextProduction; + ++i; } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp index e540ac948d9..3fd58400344 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp @@ -470,8 +470,15 @@ void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) if( production->m_productionID == productionID ) { - // give the player the cost of the object back Player *player = getObject()->getControllingPlayer(); + +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix arcticdolphin 07/09/2026 No cancel once the batch has started producing. + if( production->getProductionQuantityRemaining() < production->getProductionQuantity() ) + return; +#endif + + // give the player the cost of the object back Money *money = player->getMoney(); money->deposit( production->m_objectToProduce->calcCostToBuild( player ), TRUE, FALSE ); @@ -659,7 +666,7 @@ UpdateSleepTime ProductionUpdate::update() // if we've become OBJECT_STATUS_SOLD, halt all production ... leave things in the // queue because if the sell process completes we get money back for them, for now we // will be just frozen in time - // Actually, there will be nothing in the queue since everything gets cancel/refunded + // Actually, there will usually be nothing in the queue since everything gets cancel/refunded // at the start of sell, but we still don't want to do anything here. // if( us->getStatusBits().test( OBJECT_STATUS_SOLD ) ) @@ -693,10 +700,17 @@ UpdateSleepTime ProductionUpdate::update() // Don't cancel dozers in the queue. jba. if (!production->getProductionObject()->isKindOf(KINDOF_DOZER)) { - +#if RETAIL_COMPATIBLE_CRC cancelUnitCreate(production->getProductionID()); return UPDATE_SLEEP_NONE; - +#else + // TheSuperHackers @bugfix arcticdolphin 07/09/2026 Only cancel an untouched batch. + if( production->getProductionQuantityRemaining() == production->getProductionQuantity() ) + { + cancelUnitCreate(production->getProductionID()); + return UPDATE_SLEEP_NONE; + } +#endif } } @@ -1138,23 +1152,27 @@ void ProductionUpdate::cancelAndRefundAllProduction() { // Empirically, in release the code can loop forever. So we limit to 100 passes. jba. [8/31/2003] const Int productionLimit = 100;// With luck, we never queue up 100 units. [8/31/2003] - Int i; - for (i=0; im_next; + + if( production->getProductionType() == PRODUCTION_UNIT ) + cancelUnitCreate( production->getProductionID() ); + else if( production->getProductionType() == PRODUCTION_UPGRADE ) + cancelUpgrade( production->getProductionUpgrade() ); + else { - if( m_productionQueue->getProductionType() == PRODUCTION_UNIT ) - cancelUnitCreate( m_productionQueue->getProductionID() ); - else if( m_productionQueue->getProductionType() == PRODUCTION_UPGRADE ) - cancelUpgrade( m_productionQueue->getProductionUpgrade() ); - else - { - // unknown production type - DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", m_productionQueue->getProductionType() )); - return; - } + // unknown production type + DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", production->getProductionType() )); + return; } + + production = nextProduction; + ++i; } }