| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: Upgrade.cpp //////////////////////////////////////////////////////////////////////////////
- // Author: Colin Day, March 2002
- // Desc: Upgrade system for players
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #define DEFINE_VETERANCY_NAMES
- #include "Common/Upgrade.h"
- #include "Common/Player.h"
- #include "Common/Xfer.h"
- #include "GameClient/InGameUI.h"
- #include "GameClient/Image.h"
- const char *TheUpgradeTypeNames[] =
- {
- "PLAYER",
- "OBJECT",
- NULL
- };
- // PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
- class UpgradeCenter *TheUpgradeCenter = NULL;
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // UPGRADE ////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- Upgrade::Upgrade( const UpgradeTemplate *upgradeTemplate )
- {
- m_template = upgradeTemplate;
- m_status = UPGRADE_STATUS_INVALID;
- m_next = NULL;
- m_prev = NULL;
- } // end Upgrade
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- Upgrade::~Upgrade( void )
- {
- } // end ~Upgrade
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void Upgrade::crc( Xfer *xfer )
- {
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void Upgrade::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // status
- xfer->xferUser( &m_status, sizeof( UpgradeStatusType ) );
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void Upgrade::loadPostProcess( void )
- {
- } // end loadPostProcess
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // UPGRADE TEMPLATE ///////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- const FieldParse UpgradeTemplate::m_upgradeFieldParseTable[] =
- {
- { "DisplayName", INI::parseAsciiString, NULL, offsetof( UpgradeTemplate, m_displayNameLabel ) },
- { "Type", INI::parseIndexList, TheUpgradeTypeNames, offsetof( UpgradeTemplate, m_type ) },
- { "BuildTime", INI::parseReal, NULL, offsetof( UpgradeTemplate, m_buildTime ) },
- { "BuildCost", INI::parseInt, NULL, offsetof( UpgradeTemplate, m_cost ) },
- { "ButtonImage", INI::parseAsciiString, NULL, offsetof( UpgradeTemplate, m_buttonImageName ) },
- { "ResearchSound", INI::parseAudioEventRTS, NULL, offsetof( UpgradeTemplate, m_researchSound ) },
- { "UnitSpecificSound", INI::parseAudioEventRTS, NULL, offsetof( UpgradeTemplate, m_unitSpecificSound ) },
- { "AcademyClassify", INI::parseIndexList, TheAcademyClassificationTypeNames, offsetof( UpgradeTemplate, m_academyClassificationType ) },
- { NULL, NULL, NULL, 0 } // keep this last
- };
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- UpgradeTemplate::UpgradeTemplate( void )
- {
- //Added By Sadullah Nader
- //Initialization(s) inserted
- m_cost = 0;
- //
- m_type = UPGRADE_TYPE_PLAYER;
- m_nameKey = NAMEKEY_INVALID;
- m_buildTime = 0.0f;
- m_next = NULL;
- m_prev = NULL;
- m_buttonImage = NULL;
- m_academyClassificationType = ACT_NONE;
- } // end UpgradeTemplate
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- UpgradeTemplate::~UpgradeTemplate( void )
- {
- } // end ~UpgradeTemplate
- //-------------------------------------------------------------------------------------------------
- /** Calculate the time it takes (in logic frames) for a player to build this UpgradeTemplate */
- //-------------------------------------------------------------------------------------------------
- Int UpgradeTemplate::calcTimeToBuild( Player *player ) const
- {
- #if defined(_DEBUG) || defined(_INTERNAL) || defined(_ALLOW_DEBUG_CHEATS_IN_RELEASE)
- if( player->buildsInstantly() )
- {
- return 1;
- }
- #endif
- ///@todo modify this by power state of player
- return m_buildTime * LOGICFRAMES_PER_SECOND;
- } // end calcTimeToBuild
- //-------------------------------------------------------------------------------------------------
- /** Calculate the cost takes this player to build this upgrade */
- //-------------------------------------------------------------------------------------------------
- Int UpgradeTemplate::calcCostToBuild( Player *player ) const
- {
- ///@todo modify this by any player handicaps
- return m_cost;
- } // end calcCostToBuild
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- static AsciiString getVetUpgradeName(VeterancyLevel v)
- {
- AsciiString tmp;
- tmp = "Upgrade_Veterancy_";
- tmp.concat(TheVeterancyNames[v]);
- return tmp;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void UpgradeTemplate::friend_makeVeterancyUpgrade(VeterancyLevel v)
- {
- m_type = UPGRADE_TYPE_OBJECT; // veterancy "upgrades" are always per-object, not per-player
- m_name = getVetUpgradeName(v);
- m_nameKey = TheNameKeyGenerator->nameToKey( m_name );
- m_displayNameLabel.clear(); // should never be displayed
- m_buildTime = 0.0f;
- m_cost = 0.0f;
- // leave this alone.
- //m_upgradeMask = ???;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void UpgradeTemplate::cacheButtonImage()
- {
- if( m_buttonImageName.isNotEmpty() )
- {
- m_buttonImage = TheMappedImageCollection->findImageByName( m_buttonImageName );
- DEBUG_ASSERTCRASH( m_buttonImage, ("UpgradeTemplate: %s is looking for button image %s but can't find it. Skipping...", m_name.str(), m_buttonImageName.str() ) );
- m_buttonImageName.clear(); // we're done with this, so nuke it
- }
- }
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // UPGRADE CENTER /////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- UpgradeCenter::UpgradeCenter( void )
- {
- m_upgradeList = NULL;
- m_nextTemplateMaskBit = 0;
- buttonImagesCached = FALSE;
- } // end UpgradeCenter
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- UpgradeCenter::~UpgradeCenter( void )
- {
-
- // delete all the upgrades loaded from the INI database
- UpgradeTemplate *next;
- while( m_upgradeList )
- {
- // get next
- next = m_upgradeList->friend_getNext();
- // delete head of list
- m_upgradeList->deleteInstance();
- // set head to next element
- m_upgradeList = next;
- } // end while
- } // end ~UpgradeCenter
- //-------------------------------------------------------------------------------------------------
- /** Upgrade center initialization */
- //-------------------------------------------------------------------------------------------------
- void UpgradeCenter::init( void )
- {
- UpgradeTemplate* up;
-
- // name will be overridden by friend_makeVeterancyUpgrade
- // no, there ISN'T an upgrade for this one...
- //up = newUpgrade("");
- //up->friend_makeVeterancyUpgrade(LEVEL_REGULAR);
- up = newUpgrade("");
- up->friend_makeVeterancyUpgrade(LEVEL_VETERAN);
- up = newUpgrade("");
- up->friend_makeVeterancyUpgrade(LEVEL_ELITE);
- up = newUpgrade("");
- up->friend_makeVeterancyUpgrade(LEVEL_HEROIC);
- }
- //-------------------------------------------------------------------------------------------------
- /** Upgrade center system reset */
- //-------------------------------------------------------------------------------------------------
- void UpgradeCenter::reset( void )
- {
- if( TheMappedImageCollection && !buttonImagesCached )
- {
- UpgradeTemplate *upgrade;
- for( upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
- {
- upgrade->cacheButtonImage();
- }
- buttonImagesCached = TRUE;
- }
- }
- //-------------------------------------------------------------------------------------------------
- /** Find upgrade matching name key */
- //-------------------------------------------------------------------------------------------------
- const UpgradeTemplate *UpgradeCenter::findVeterancyUpgrade( VeterancyLevel level ) const
- {
- AsciiString tmp = getVetUpgradeName(level);
- return findUpgrade(tmp);
- }
- //-------------------------------------------------------------------------------------------------
- /** Find upgrade matching name key */
- //-------------------------------------------------------------------------------------------------
- UpgradeTemplate *UpgradeCenter::findNonConstUpgradeByKey( NameKeyType key )
- {
- UpgradeTemplate *upgrade;
- // search list
- for( upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
- if( upgrade->getUpgradeNameKey() == key )
- return upgrade;
- // item not found
- return NULL;
- }
- // ------------------------------------------------------------------------------------------------
- /** Return the first upgrade template */
- // ------------------------------------------------------------------------------------------------
- UpgradeTemplate *UpgradeCenter::firstUpgradeTemplate( void )
- {
-
- return m_upgradeList;
- } // end firstUpgradeTemplate
- //-------------------------------------------------------------------------------------------------
- /** Find upgrade matching name key */
- //-------------------------------------------------------------------------------------------------
- const UpgradeTemplate *UpgradeCenter::findUpgradeByKey( NameKeyType key ) const
- {
- const UpgradeTemplate *upgrade;
- // search list
- for( upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
- if( upgrade->getUpgradeNameKey() == key )
- return upgrade;
- // item not found
- return NULL;
- }
- //-------------------------------------------------------------------------------------------------
- /** Find upgrade matching name */
- //-------------------------------------------------------------------------------------------------
- const UpgradeTemplate *UpgradeCenter::findUpgrade( const AsciiString& name ) const
- {
- return findUpgradeByKey( TheNameKeyGenerator->nameToKey( name ) );
- } // end findUpgrade
- //-------------------------------------------------------------------------------------------------
- /** Allocate a new upgrade template */
- //-------------------------------------------------------------------------------------------------
- UpgradeTemplate *UpgradeCenter::newUpgrade( const AsciiString& name )
- {
- UpgradeTemplate *newUpgrade = newInstance(UpgradeTemplate);
- // copy data from the default upgrade
- const UpgradeTemplate *defaultUpgrade = findUpgrade( "DefaultUpgrade" );
- if( defaultUpgrade )
- *newUpgrade = *defaultUpgrade;
- // assign name and starting data
- newUpgrade->setUpgradeName( name );
- newUpgrade->setUpgradeNameKey( TheNameKeyGenerator->nameToKey( name ) );
- // Make a unique bitmask for this new template by keeping track of what bits have been assigned
- // damn MSFT! proper ANSI syntax for a proper 64-bit constant is "1LL", but MSVC doesn't recognize it
- UpgradeMaskType newMask;
- newMask.set( m_nextTemplateMaskBit );
- //Int64 newMask = 1i64 << m_nextTemplateMaskBit;
- m_nextTemplateMaskBit++;
- DEBUG_ASSERTCRASH( m_nextTemplateMaskBit < UPGRADE_MAX_COUNT, ("Can't have over %d types of Upgrades and have a Bitfield function.", UPGRADE_MAX_COUNT) );
- newUpgrade->friend_setUpgradeMask( newMask );
- // link upgrade
- linkUpgrade( newUpgrade );
- // return new upgrade
- return newUpgrade;
- } // end newUnlinkedUpgrade
- //-------------------------------------------------------------------------------------------------
- /** Link an upgrade to our list */
- //-------------------------------------------------------------------------------------------------
- void UpgradeCenter::linkUpgrade( UpgradeTemplate *upgrade )
- {
- // sanity
- if( upgrade == NULL )
- return;
- // link
- upgrade->friend_setPrev( NULL );
- upgrade->friend_setNext( m_upgradeList );
- if( m_upgradeList )
- m_upgradeList->friend_setPrev( upgrade );
- m_upgradeList = upgrade;
- } // end linkUpgrade
- //-------------------------------------------------------------------------------------------------
- /** Unlink an upgrade from our list */
- //-------------------------------------------------------------------------------------------------
- void UpgradeCenter::unlinkUpgrade( UpgradeTemplate *upgrade )
- {
- // sanity
- if( upgrade == NULL )
- return;
- if( upgrade->friend_getNext() )
- upgrade->friend_getNext()->friend_setPrev( upgrade->friend_getPrev() );
- if( upgrade->friend_getPrev() )
- upgrade->friend_getPrev()->friend_setNext( upgrade->friend_getNext() );
- else
- m_upgradeList = upgrade->friend_getNext();
- } // end unlinkUpgrade
- //-------------------------------------------------------------------------------------------------
- /** does this player have all the necessary things to make this upgrade */
- //-------------------------------------------------------------------------------------------------
- Bool UpgradeCenter::canAffordUpgrade( Player *player, const UpgradeTemplate *upgradeTemplate, Bool displayReason ) const
- {
-
- // sanity
- if( player == NULL || upgradeTemplate == NULL )
- return FALSE;
- // money check
- Money *money = player->getMoney();
- if( money->countMoney() < upgradeTemplate->calcCostToBuild( player ) )
- {
- //Post reason why we can't make upgrade!
- if( displayReason )
- {
- TheInGameUI->message( "GUI:NotEnoughMoneyToUpgrade" );
- }
- return FALSE;
- }
- /// @todo maybe have prereq checks for upgrades???
- return TRUE; // all is well
- } // end canAffordUpgrade
- //-------------------------------------------------------------------------------------------------
- /** generate a list of upgrade names for WorldBuilder */
- //-------------------------------------------------------------------------------------------------
- std::vector<AsciiString> UpgradeCenter::getUpgradeNames( void ) const
- {
- std::vector<AsciiString> upgradeNames;
- for( UpgradeTemplate *upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
- upgradeNames.push_back(upgrade->getUpgradeName());
- return upgradeNames;
- } // end getUpgradeNames
- //-------------------------------------------------------------------------------------------------
- /** Parse an upgrade definition */
- //-------------------------------------------------------------------------------------------------
- void UpgradeCenter::parseUpgradeDefinition( INI *ini )
- {
- // read the name
- const char* c = ini->getNextToken();
- AsciiString name = c;
- // find existing item if present
- UpgradeTemplate* upgrade = TheUpgradeCenter->findNonConstUpgradeByKey( NAMEKEY(name) );
- if( upgrade == NULL )
- {
- // allocate a new item
- upgrade = TheUpgradeCenter->newUpgrade( name );
- } // end if
- // sanity
- DEBUG_ASSERTCRASH( upgrade, ("parseUpgradeDefinition: Unable to allocate upgrade '%s'\n", name.str()) );
- // parse the ini definition
- ini->initFromINI( upgrade, upgrade->getFieldParse() );
- }
|