Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class ProductionUpdateInterface
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0;

virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) = 0;
virtual void cancelUnitCreate( ProductionID productionID ) = 0;
virtual void cancelUnitCreate( ProductionID productionID, Bool forceCancel = FALSE ) = 0;
virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) = 0;

virtual void cancelAndRefundAllProduction() = 0;
Expand Down Expand Up @@ -209,7 +209,7 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface,
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const; ///< count number of units with matching unit type in the production queue

virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ); ///< queue unit to be produced
virtual void cancelUnitCreate( ProductionID productionID ); ///< cancel construction of unit with matching production ID
virtual void cancelUnitCreate( ProductionID productionID, Bool forceCancel = FALSE ); ///< cancel construction of unit with matching production ID
virtual void cancelAllUnitsOfType( const ThingTemplate *unitType); ///< cancel all production of type unitType

virtual void cancelAndRefundAllProduction(); ///< cancel and refund anything in the production queue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ Bool ProductionUpdate::queueCreateUnit( const ThingTemplate *unitType, Productio
//-------------------------------------------------------------------------------------------------
/** Cancel the construction of the unit with the matching production ID */
//-------------------------------------------------------------------------------------------------
void ProductionUpdate::cancelUnitCreate( ProductionID productionID )
void ProductionUpdate::cancelUnitCreate( ProductionID productionID, Bool forceCancel )
{

// search for the production entry in our queue
Expand All @@ -469,8 +469,16 @@ 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 08/03/2026 Prevent cancel once units are produced to avoid free unit exploit
if( !forceCancel && 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 );

Expand Down Expand Up @@ -692,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 13/03/2026 Let partial production finish naturally when script-disallowed.
if( production->getProductionQuantityRemaining() == production->getProductionQuantity() )
{
cancelUnitCreate(production->getProductionID());
return UPDATE_SLEEP_NONE;
}
#endif
}

}
Expand Down Expand Up @@ -1140,7 +1155,7 @@ void ProductionUpdate::cancelAndRefundAllProduction()
if( m_productionQueue )
{
if( m_productionQueue->getProductionType() == PRODUCTION_UNIT )
cancelUnitCreate( m_productionQueue->getProductionID() );
cancelUnitCreate( m_productionQueue->getProductionID(), TRUE );
else if( m_productionQueue->getProductionType() == PRODUCTION_UPGRADE )
cancelUpgrade( m_productionQueue->getProductionUpgrade() );
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class ProductionUpdateInterface
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0;

virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) = 0;
virtual void cancelUnitCreate( ProductionID productionID ) = 0;
virtual void cancelUnitCreate( ProductionID productionID, Bool forceCancel = FALSE ) = 0;
virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) = 0;

virtual void cancelAndRefundAllProduction() = 0;
Expand Down Expand Up @@ -214,7 +214,7 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface,
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const; ///< count number of units with matching unit type in the production queue

virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ); ///< queue unit to be produced
virtual void cancelUnitCreate( ProductionID productionID ); ///< cancel construction of unit with matching production ID
virtual void cancelUnitCreate( ProductionID productionID, Bool forceCancel = FALSE ); ///< cancel construction of unit with matching production ID
virtual void cancelAllUnitsOfType( const ThingTemplate *unitType); ///< cancel all production of type unitType

virtual void cancelAndRefundAllProduction(); ///< cancel and refund anything in the production queue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ Bool ProductionUpdate::queueCreateUnit( const ThingTemplate *unitType, Productio
//-------------------------------------------------------------------------------------------------
/** Cancel the construction of the unit with the matching production ID */
//-------------------------------------------------------------------------------------------------
void ProductionUpdate::cancelUnitCreate( ProductionID productionID )
void ProductionUpdate::cancelUnitCreate( ProductionID productionID, Bool forceCancel )
{

// search for the production entry in our queue
Expand All @@ -470,8 +470,16 @@ 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 08/03/2026 Prevent cancel once units are produced to avoid free unit exploit
if( !forceCancel && 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 );

Expand Down Expand Up @@ -693,10 +701,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 13/03/2026 Let partial production finish naturally when script-disallowed.
if( production->getProductionQuantityRemaining() == production->getProductionQuantity() )
{
cancelUnitCreate(production->getProductionID());
return UPDATE_SLEEP_NONE;
}
#endif
}

}
Expand Down Expand Up @@ -1145,7 +1160,7 @@ void ProductionUpdate::cancelAndRefundAllProduction()
if( m_productionQueue )
{
if( m_productionQueue->getProductionType() == PRODUCTION_UNIT )
cancelUnitCreate( m_productionQueue->getProductionID() );
cancelUnitCreate( m_productionQueue->getProductionID(), TRUE );
else if( m_productionQueue->getProductionType() == PRODUCTION_UPGRADE )
cancelUpgrade( m_productionQueue->getProductionUpgrade() );
else
Expand Down
Loading