Skip to content
Merged
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 @@ -153,7 +153,7 @@ class ProductionUpdateInterface
virtual ProductionID requestUniqueUnitID() = 0;

virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual void cancelUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual Bool cancelUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const = 0;
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0;

Expand Down Expand Up @@ -209,7 +209,7 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface,
virtual ProductionID requestUniqueUnitID() override { ProductionID tmp = m_uniqueID; m_uniqueID = (ProductionID)(m_uniqueID+1); return tmp; }

virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ) override; ///< queue upgrade "research"
virtual void cancelUpgrade( const UpgradeTemplate *upgrade ) override; ///< cancel upgrade "research"
virtual Bool cancelUpgrade( const UpgradeTemplate *upgrade ) override; ///< cancel upgrade "research"
virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const override; ///< is the upgrade in our production queue already
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const override; ///< count number of units with matching unit type in the production queue

Expand Down Expand Up @@ -239,10 +239,12 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface,

protected:


void addToProductionQueue( ProductionEntry *production ); ///< add to *END* of production queue list
void removeFromProductionQueue( ProductionEntry *production ); ///< remove production from the queue list

Bool cancelUpgrade( ProductionEntry *production );
Bool cancelUnitCreate( ProductionEntry *production );

void updateDoors(); ///< update the door behavior

struct DoorInfo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,19 +323,11 @@ Bool ProductionUpdate::queueUpgrade( const UpgradeTemplate *upgrade )
//-------------------------------------------------------------------------------------------------
/** Cancel an upgrade being produced here */
//-------------------------------------------------------------------------------------------------
void ProductionUpdate::cancelUpgrade( const UpgradeTemplate *upgrade )
Bool ProductionUpdate::cancelUpgrade( const UpgradeTemplate *upgrade )
{

// sanity
if( upgrade == nullptr )
return;

// get the player
Player *player = getObject()->getControllingPlayer();

// sanity, you can't cancel it if the player isn't actually building one
if( upgrade->getUpgradeType() == UPGRADE_TYPE_PLAYER && player->hasUpgradeInProduction( upgrade ) == FALSE )
return;
return FALSE;

//
// find the production entry for this upgrade in the queue here, there can only be one
Expand All @@ -344,34 +336,15 @@ void ProductionUpdate::cancelUpgrade( const UpgradeTemplate *upgrade )
ProductionEntry *production;
for( production = m_productionQueue; production; production = production->m_next )
{

if( production->m_type == PRODUCTION_UPGRADE &&
production->m_upgradeToResearch == upgrade )
break;
{
return cancelUpgrade( production );
}

}

// sanity, entry not found
if( production == nullptr )
return;

// refund money back to the player
Money *money = player->getMoney();
money->deposit( production->m_upgradeToResearch->calcCostToBuild( player ), TRUE, FALSE );

// remove this production from the queue
removeFromProductionQueue( production );

// delete production instance
deleteInstance(production);

//
// remove the IN_PRODUCTION status of this upgrade from the player, object upgrades don't
// have any other IN_PRODUCTION status other than their existence in the build queue
//
if( upgrade->getUpgradeType() == UPGRADE_TYPE_PLAYER )
player->removeUpgrade( upgrade );

return FALSE;
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -465,33 +438,11 @@ Bool ProductionUpdate::cancelUnitCreate( ProductionID productionID )
ProductionEntry *production;
for( production = m_productionQueue; production; production = production->m_next )
{

// are we at the one we want get rid of it
if( production->m_productionID == productionID )
{

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 FALSE;
#endif

// give the player the cost of the object back
Money *money = player->getMoney();
money->deposit( production->m_objectToProduce->calcCostToBuild( player ), TRUE, FALSE );

// remove from queue list
removeFromProductionQueue( production );

// delete the production entry
deleteInstance(production);

return TRUE;

return cancelUnitCreate( production );
}

}

return FALSE;
Expand All @@ -516,7 +467,7 @@ void ProductionUpdate::cancelAllUnitsOfType( const ThingTemplate *unitType)
ProductionEntry *temp = production->m_next;

// cancel the production
cancelUnitCreate( production->getProductionID() );
cancelUnitCreate( production );

// advance
production = temp;
Expand Down Expand Up @@ -702,7 +653,7 @@ UpdateSleepTime ProductionUpdate::update()
// Don't cancel dozers in the queue. jba.
if (!production->getProductionObject()->isKindOf(KINDOF_DOZER))
{
if( cancelUnitCreate(production->getProductionID()) )
if( cancelUnitCreate(production) )
return UPDATE_SLEEP_NONE;
}

Expand Down Expand Up @@ -1091,6 +1042,66 @@ void ProductionUpdate::removeFromProductionQueue( ProductionEntry *production )

}

//-------------------------------------------------------------------------------------------------
Bool ProductionUpdate::cancelUpgrade( ProductionEntry *production )
{
DEBUG_ASSERTCRASH(production->getProductionType() == PRODUCTION_UPGRADE,
("ProductionUpdate::cancelUpgrade - called with wrong production type"));

Player *player = getObject()->getControllingPlayer();
const UpgradeTemplate *upgrade = production->getProductionUpgrade();

// sanity, you can't cancel it if the player isn't actually building one
if( upgrade->getUpgradeType() == UPGRADE_TYPE_PLAYER && player->hasUpgradeInProduction( upgrade ) == FALSE )
return FALSE;

// refund money back to the player
Money *money = player->getMoney();
money->deposit( production->m_upgradeToResearch->calcCostToBuild( player ), TRUE, FALSE );

// remove this production from the queue
removeFromProductionQueue( production );

// delete production instance
deleteInstance(production);

//
// remove the IN_PRODUCTION status of this upgrade from the player, object upgrades don't
// have any other IN_PRODUCTION status other than their existence in the build queue
//
if( upgrade->getUpgradeType() == UPGRADE_TYPE_PLAYER )
player->removeUpgrade( upgrade );

return TRUE;
}

//-------------------------------------------------------------------------------------------------
Bool ProductionUpdate::cancelUnitCreate( ProductionEntry *production )
{
DEBUG_ASSERTCRASH(production->getProductionType() == PRODUCTION_UNIT,
("ProductionUpdate::cancelUnitCreate - called with wrong production type"));

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 FALSE;
#endif

// give the player the cost of the object back
Money *money = player->getMoney();
money->deposit( production->m_objectToProduce->calcCostToBuild( player ), TRUE, FALSE );

// remove from queue list
removeFromProductionQueue( production );

// delete the production entry
deleteInstance(production);

return TRUE;
}

//-------------------------------------------------------------------------------------------------
/** Is the upgrade already in the production queue. Note that you can only have one
* production entry for any given upgrade in the queue */
Expand Down Expand Up @@ -1139,36 +1150,46 @@ void ProductionUpdate::onDie( const DamageInfo *damageInfo )
// ------------------------------------------------------------------------------------------------
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]
// 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; i < productionLimit && m_productionQueue; ++i)
{
ProductionEntry *production = m_productionQueue;

Int i = 0;
ProductionEntry *production = m_productionQueue;
while( production != nullptr && i < productionLimit )
{
ProductionEntry *nextProduction = production->m_next;

if( production->getProductionType() == PRODUCTION_UNIT )
{
if( !cancelUnitCreate( production->getProductionID() ) )
{
removeFromProductionQueue( production );
deleteInstance( production );
}
}
else if( production->getProductionType() == PRODUCTION_UPGRADE )
cancelUpgrade( production->getProductionUpgrade() );
else
{
// unknown production type
DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'",
production->getProductionType() ));
return;
}

production = nextProduction;
++i;
}
if( production->getProductionType() == PRODUCTION_UNIT )
{
if( !cancelUnitCreate( production ) )
{
#if RETAIL_COMPATIBLE_CRC
DEBUG_CRASH(("This code path cannot be reached"));
#endif
// Unable to cancel for a refund... delete anyway.
removeFromProductionQueue( production );
deleteInstance( production );
}
}
else if( production->getProductionType() == PRODUCTION_UPGRADE )
{
if( !cancelUpgrade( production ) )
{
#if RETAIL_COMPATIBLE_CRC
// Cannot cancel the head production... this loop is stuck now and can quit.
return;
#else
// Unable to cancel for a refund... delete anyway.
removeFromProductionQueue( production );
deleteInstance( production );
#endif
}
}
else
{
// unknown production type
DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", production->getProductionType() ));
return;
}
}
}

// ------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class ProductionUpdateInterface
virtual ProductionID requestUniqueUnitID() = 0;

virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual void cancelUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual Bool cancelUpgrade( const UpgradeTemplate *upgrade ) = 0;
virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const = 0;
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0;

Expand Down Expand Up @@ -209,7 +209,7 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface,
virtual ProductionID requestUniqueUnitID() override { ProductionID tmp = m_uniqueID; m_uniqueID = (ProductionID)(m_uniqueID+1); return tmp; }

virtual Bool queueUpgrade( const UpgradeTemplate *upgrade ) override; ///< queue upgrade "research"
virtual void cancelUpgrade( const UpgradeTemplate *upgrade ) override; ///< cancel upgrade "research"
virtual Bool cancelUpgrade( const UpgradeTemplate *upgrade ) override; ///< cancel upgrade "research"
virtual Bool isUpgradeInQueue( const UpgradeTemplate *upgrade ) const override; ///< is the upgrade in our production queue already
virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const override; ///< count number of units with matching unit type in the production queue

Expand Down Expand Up @@ -239,10 +239,12 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface,

protected:


void addToProductionQueue( ProductionEntry *production ); ///< add to *END* of production queue list
void removeFromProductionQueue( ProductionEntry *production ); ///< remove production from the queue list

Bool cancelUpgrade( ProductionEntry *production );
Bool cancelUnitCreate( ProductionEntry *production );

void updateDoors(); ///< update the door behavior

struct DoorInfo
Expand Down
Loading
Loading