Upgrade.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: Upgrade.cpp //////////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, March 2002
  25. // Desc: Upgrade system for players
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #define DEFINE_UPGRADE_TYPE_NAMES
  30. #define DEFINE_VETERANCY_NAMES
  31. #include "Common/Upgrade.h"
  32. #include "Common/Player.h"
  33. #include "Common/Xfer.h"
  34. #include "GameClient/InGameUI.h"
  35. #include "GameClient/Image.h"
  36. // PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
  37. class UpgradeCenter *TheUpgradeCenter = NULL;
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////
  39. // UPGRADE ////////////////////////////////////////////////////////////////////////////////////////
  40. ///////////////////////////////////////////////////////////////////////////////////////////////////
  41. //-------------------------------------------------------------------------------------------------
  42. //-------------------------------------------------------------------------------------------------
  43. Upgrade::Upgrade( const UpgradeTemplate *upgradeTemplate )
  44. {
  45. m_template = upgradeTemplate;
  46. m_status = UPGRADE_STATUS_INVALID;
  47. m_next = NULL;
  48. m_prev = NULL;
  49. } // end Upgrade
  50. //-------------------------------------------------------------------------------------------------
  51. //-------------------------------------------------------------------------------------------------
  52. Upgrade::~Upgrade( void )
  53. {
  54. } // end ~Upgrade
  55. // ------------------------------------------------------------------------------------------------
  56. /** CRC */
  57. // ------------------------------------------------------------------------------------------------
  58. void Upgrade::crc( Xfer *xfer )
  59. {
  60. } // end crc
  61. // ------------------------------------------------------------------------------------------------
  62. /** Xfer method
  63. * Version Info:
  64. * 1: Initial version */
  65. // ------------------------------------------------------------------------------------------------
  66. void Upgrade::xfer( Xfer *xfer )
  67. {
  68. // version
  69. XferVersion currentVersion = 1;
  70. XferVersion version = currentVersion;
  71. xfer->xferVersion( &version, currentVersion );
  72. // status
  73. xfer->xferUser( &m_status, sizeof( UpgradeStatusType ) );
  74. } // end xfer
  75. // ------------------------------------------------------------------------------------------------
  76. /** Load post process */
  77. // ------------------------------------------------------------------------------------------------
  78. void Upgrade::loadPostProcess( void )
  79. {
  80. } // end loadPostProcess
  81. ///////////////////////////////////////////////////////////////////////////////////////////////////
  82. // UPGRADE TEMPLATE ///////////////////////////////////////////////////////////////////////////////
  83. ///////////////////////////////////////////////////////////////////////////////////////////////////
  84. //-------------------------------------------------------------------------------------------------
  85. //-------------------------------------------------------------------------------------------------
  86. const FieldParse UpgradeTemplate::m_upgradeFieldParseTable[] =
  87. {
  88. { "DisplayName", INI::parseAsciiString, NULL, offsetof( UpgradeTemplate, m_displayNameLabel ) },
  89. { "Type", INI::parseIndexList, UpgradeTypeNames, offsetof( UpgradeTemplate, m_type ) },
  90. { "BuildTime", INI::parseReal, NULL, offsetof( UpgradeTemplate, m_buildTime ) },
  91. { "BuildCost", INI::parseInt, NULL, offsetof( UpgradeTemplate, m_cost ) },
  92. { "ButtonImage", INI::parseAsciiString, NULL, offsetof( UpgradeTemplate, m_buttonImageName ) },
  93. { "ResearchSound", INI::parseAudioEventRTS, NULL, offsetof( UpgradeTemplate, m_researchSound ) },
  94. { "UnitSpecificSound", INI::parseAudioEventRTS, NULL, offsetof( UpgradeTemplate, m_unitSpecificSound ) },
  95. { NULL, NULL, NULL, 0 } // keep this last
  96. };
  97. //-------------------------------------------------------------------------------------------------
  98. //-------------------------------------------------------------------------------------------------
  99. UpgradeTemplate::UpgradeTemplate( void )
  100. {
  101. //Added By Sadullah Nader
  102. //Initialization(s) inserted
  103. m_cost = 0;
  104. //
  105. m_type = UPGRADE_TYPE_PLAYER;
  106. m_nameKey = NAMEKEY_INVALID;
  107. m_buildTime = 0.0f;
  108. m_upgradeMask = 0;
  109. m_next = NULL;
  110. m_prev = NULL;
  111. m_buttonImage = NULL;
  112. } // end UpgradeTemplate
  113. //-------------------------------------------------------------------------------------------------
  114. //-------------------------------------------------------------------------------------------------
  115. UpgradeTemplate::~UpgradeTemplate( void )
  116. {
  117. } // end ~UpgradeTemplate
  118. //-------------------------------------------------------------------------------------------------
  119. /** Calculate the time it takes (in logic frames) for a player to build this UpgradeTemplate */
  120. //-------------------------------------------------------------------------------------------------
  121. Int UpgradeTemplate::calcTimeToBuild( Player *player ) const
  122. {
  123. #if defined(_DEBUG) || defined(_INTERNAL)
  124. if( player->buildsInstantly() )
  125. {
  126. return 1;
  127. }
  128. #endif
  129. ///@todo modify this by power state of player
  130. return m_buildTime * LOGICFRAMES_PER_SECOND;
  131. } // end calcTimeToBuild
  132. //-------------------------------------------------------------------------------------------------
  133. /** Calculate the cost takes this player to build this upgrade */
  134. //-------------------------------------------------------------------------------------------------
  135. Int UpgradeTemplate::calcCostToBuild( Player *player ) const
  136. {
  137. ///@todo modify this by any player handicaps
  138. return m_cost;
  139. } // end calcCostToBuild
  140. //-------------------------------------------------------------------------------------------------
  141. //-------------------------------------------------------------------------------------------------
  142. static AsciiString getVetUpgradeName(VeterancyLevel v)
  143. {
  144. AsciiString tmp;
  145. tmp = "Upgrade_Veterancy_";
  146. tmp.concat(TheVeterancyNames[v]);
  147. return tmp;
  148. }
  149. //-------------------------------------------------------------------------------------------------
  150. //-------------------------------------------------------------------------------------------------
  151. void UpgradeTemplate::friend_makeVeterancyUpgrade(VeterancyLevel v)
  152. {
  153. m_type = UPGRADE_TYPE_OBJECT; // veterancy "upgrades" are always per-object, not per-player
  154. m_name = getVetUpgradeName(v);
  155. m_nameKey = TheNameKeyGenerator->nameToKey( m_name );
  156. m_displayNameLabel.clear(); // should never be displayed
  157. m_buildTime = 0.0f;
  158. m_cost = 0.0f;
  159. // leave this alone.
  160. //m_upgradeMask = ???;
  161. }
  162. //-------------------------------------------------------------------------------------------------
  163. //-------------------------------------------------------------------------------------------------
  164. void UpgradeTemplate::cacheButtonImage()
  165. {
  166. if( m_buttonImageName.isNotEmpty() )
  167. {
  168. m_buttonImage = TheMappedImageCollection->findImageByName( m_buttonImageName );
  169. DEBUG_ASSERTCRASH( m_buttonImage, ("UpgradeTemplate: %s is looking for button image %s but can't find it. Skipping...", m_name.str(), m_buttonImageName.str() ) );
  170. m_buttonImageName.clear(); // we're done with this, so nuke it
  171. }
  172. }
  173. ///////////////////////////////////////////////////////////////////////////////////////////////////
  174. // UPGRADE CENTER /////////////////////////////////////////////////////////////////////////////////
  175. ///////////////////////////////////////////////////////////////////////////////////////////////////
  176. //-------------------------------------------------------------------------------------------------
  177. //-------------------------------------------------------------------------------------------------
  178. UpgradeCenter::UpgradeCenter( void )
  179. {
  180. m_upgradeList = NULL;
  181. m_nextTemplateMaskBit = 0;
  182. buttonImagesCached = FALSE;
  183. } // end UpgradeCenter
  184. //-------------------------------------------------------------------------------------------------
  185. //-------------------------------------------------------------------------------------------------
  186. UpgradeCenter::~UpgradeCenter( void )
  187. {
  188. // delete all the upgrades loaded from the INI database
  189. UpgradeTemplate *next;
  190. while( m_upgradeList )
  191. {
  192. // get next
  193. next = m_upgradeList->friend_getNext();
  194. // delete head of list
  195. m_upgradeList->deleteInstance();
  196. // set head to next element
  197. m_upgradeList = next;
  198. } // end while
  199. } // end ~UpgradeCenter
  200. //-------------------------------------------------------------------------------------------------
  201. /** Upgrade center initialization */
  202. //-------------------------------------------------------------------------------------------------
  203. void UpgradeCenter::init( void )
  204. {
  205. UpgradeTemplate* up;
  206. // name will be overridden by friend_makeVeterancyUpgrade
  207. // no, there ISN'T an upgrade for this one...
  208. //up = newUpgrade("");
  209. //up->friend_makeVeterancyUpgrade(LEVEL_REGULAR);
  210. up = newUpgrade("");
  211. up->friend_makeVeterancyUpgrade(LEVEL_VETERAN);
  212. up = newUpgrade("");
  213. up->friend_makeVeterancyUpgrade(LEVEL_ELITE);
  214. up = newUpgrade("");
  215. up->friend_makeVeterancyUpgrade(LEVEL_HEROIC);
  216. }
  217. //-------------------------------------------------------------------------------------------------
  218. /** Upgrade center system reset */
  219. //-------------------------------------------------------------------------------------------------
  220. void UpgradeCenter::reset( void )
  221. {
  222. if( TheMappedImageCollection && !buttonImagesCached )
  223. {
  224. UpgradeTemplate *upgrade;
  225. for( upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
  226. {
  227. upgrade->cacheButtonImage();
  228. }
  229. buttonImagesCached = TRUE;
  230. }
  231. }
  232. //-------------------------------------------------------------------------------------------------
  233. /** Find upgrade matching name key */
  234. //-------------------------------------------------------------------------------------------------
  235. const UpgradeTemplate *UpgradeCenter::findVeterancyUpgrade( VeterancyLevel level ) const
  236. {
  237. AsciiString tmp = getVetUpgradeName(level);
  238. return findUpgrade(tmp);
  239. }
  240. //-------------------------------------------------------------------------------------------------
  241. /** Find upgrade matching name key */
  242. //-------------------------------------------------------------------------------------------------
  243. UpgradeTemplate *UpgradeCenter::findNonConstUpgradeByKey( NameKeyType key )
  244. {
  245. UpgradeTemplate *upgrade;
  246. // search list
  247. for( upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
  248. if( upgrade->getUpgradeNameKey() == key )
  249. return upgrade;
  250. // item not found
  251. return NULL;
  252. }
  253. // ------------------------------------------------------------------------------------------------
  254. /** Return the first upgrade template */
  255. // ------------------------------------------------------------------------------------------------
  256. UpgradeTemplate *UpgradeCenter::firstUpgradeTemplate( void )
  257. {
  258. return m_upgradeList;
  259. } // end firstUpgradeTemplate
  260. //-------------------------------------------------------------------------------------------------
  261. /** Find upgrade matching name key */
  262. //-------------------------------------------------------------------------------------------------
  263. const UpgradeTemplate *UpgradeCenter::findUpgradeByKey( NameKeyType key ) const
  264. {
  265. const UpgradeTemplate *upgrade;
  266. // search list
  267. for( upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
  268. if( upgrade->getUpgradeNameKey() == key )
  269. return upgrade;
  270. // item not found
  271. return NULL;
  272. }
  273. //-------------------------------------------------------------------------------------------------
  274. /** Find upgrade matching name */
  275. //-------------------------------------------------------------------------------------------------
  276. const UpgradeTemplate *UpgradeCenter::findUpgrade( const AsciiString& name ) const
  277. {
  278. return findUpgradeByKey( TheNameKeyGenerator->nameToKey( name ) );
  279. } // end findUpgrade
  280. //-------------------------------------------------------------------------------------------------
  281. /** Allocate a new upgrade template */
  282. //-------------------------------------------------------------------------------------------------
  283. UpgradeTemplate *UpgradeCenter::newUpgrade( const AsciiString& name )
  284. {
  285. UpgradeTemplate *newUpgrade = newInstance(UpgradeTemplate);
  286. // copy data from the default upgrade
  287. const UpgradeTemplate *defaultUpgrade = findUpgrade( "DefaultUpgrade" );
  288. if( defaultUpgrade )
  289. *newUpgrade = *defaultUpgrade;
  290. // assign name and starting data
  291. newUpgrade->setUpgradeName( name );
  292. newUpgrade->setUpgradeNameKey( TheNameKeyGenerator->nameToKey( name ) );
  293. // Make a unique bitmask for this new template by keeping track of what bits have been assigned
  294. // damn MSFT! proper ANSI syntax for a proper 64-bit constant is "1LL", but MSVC doesn't recognize it
  295. Int64 newMask = 1i64 << m_nextTemplateMaskBit;
  296. m_nextTemplateMaskBit++;
  297. DEBUG_ASSERTCRASH( m_nextTemplateMaskBit < 64, ("Can't have over 64 types of Upgrades and have a Bitfield function.") );
  298. newUpgrade->friend_setUpgradeMask( newMask );
  299. // link upgrade
  300. linkUpgrade( newUpgrade );
  301. // return new upgrade
  302. return newUpgrade;
  303. } // end newUnlinkedUpgrade
  304. //-------------------------------------------------------------------------------------------------
  305. /** Link an upgrade to our list */
  306. //-------------------------------------------------------------------------------------------------
  307. void UpgradeCenter::linkUpgrade( UpgradeTemplate *upgrade )
  308. {
  309. // sanity
  310. if( upgrade == NULL )
  311. return;
  312. // link
  313. upgrade->friend_setPrev( NULL );
  314. upgrade->friend_setNext( m_upgradeList );
  315. if( m_upgradeList )
  316. m_upgradeList->friend_setPrev( upgrade );
  317. m_upgradeList = upgrade;
  318. } // end linkUpgrade
  319. //-------------------------------------------------------------------------------------------------
  320. /** Unlink an upgrade from our list */
  321. //-------------------------------------------------------------------------------------------------
  322. void UpgradeCenter::unlinkUpgrade( UpgradeTemplate *upgrade )
  323. {
  324. // sanity
  325. if( upgrade == NULL )
  326. return;
  327. if( upgrade->friend_getNext() )
  328. upgrade->friend_getNext()->friend_setPrev( upgrade->friend_getPrev() );
  329. if( upgrade->friend_getPrev() )
  330. upgrade->friend_getPrev()->friend_setNext( upgrade->friend_getNext() );
  331. else
  332. m_upgradeList = upgrade->friend_getNext();
  333. } // end unlinkUpgrade
  334. //-------------------------------------------------------------------------------------------------
  335. /** does this player have all the necessary things to make this upgrade */
  336. //-------------------------------------------------------------------------------------------------
  337. Bool UpgradeCenter::canAffordUpgrade( Player *player, const UpgradeTemplate *upgradeTemplate, Bool displayReason ) const
  338. {
  339. // sanity
  340. if( player == NULL || upgradeTemplate == NULL )
  341. return FALSE;
  342. // money check
  343. Money *money = player->getMoney();
  344. if( money->countMoney() < upgradeTemplate->calcCostToBuild( player ) )
  345. {
  346. //Post reason why we can't make upgrade!
  347. if( displayReason )
  348. {
  349. TheInGameUI->message( "GUI:NotEnoughMoneyToUpgrade" );
  350. }
  351. return FALSE;
  352. }
  353. /// @todo maybe have prereq checks for upgrades???
  354. return TRUE; // all is well
  355. } // end canAffordUpgrade
  356. //-------------------------------------------------------------------------------------------------
  357. /** generate a list of upgrade names for WorldBuilder */
  358. //-------------------------------------------------------------------------------------------------
  359. std::vector<AsciiString> UpgradeCenter::getUpgradeNames( void ) const
  360. {
  361. std::vector<AsciiString> upgradeNames;
  362. for( UpgradeTemplate *upgrade = m_upgradeList; upgrade; upgrade = upgrade->friend_getNext() )
  363. upgradeNames.push_back(upgrade->getUpgradeName());
  364. return upgradeNames;
  365. } // end getUpgradeNames
  366. //-------------------------------------------------------------------------------------------------
  367. /** Parse an upgrade definition */
  368. //-------------------------------------------------------------------------------------------------
  369. void UpgradeCenter::parseUpgradeDefinition( INI *ini )
  370. {
  371. // read the name
  372. const char* c = ini->getNextToken();
  373. AsciiString name = c;
  374. // find existing item if present
  375. UpgradeTemplate* upgrade = TheUpgradeCenter->findNonConstUpgradeByKey( NAMEKEY(name) );
  376. if( upgrade == NULL )
  377. {
  378. // allocate a new item
  379. upgrade = TheUpgradeCenter->newUpgrade( name );
  380. } // end if
  381. // sanity
  382. DEBUG_ASSERTCRASH( upgrade, ("parseUpgradeDefinition: Unable to allocate upgrade '%s'\n", name.str()) );
  383. // parse the ini definition
  384. ini->initFromINI( upgrade, upgrade->getFieldParse() );
  385. }