CrateSystem.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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: CrateSystem.cpp /////////////////////////////////////////////////////////////////////////////////
  24. // Author: Graham Smallwood Feb 2002
  25. // Desc: System responsible for Crates as code objects - ini, new/delete etc
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  28. #define DEFINE_VETERANCY_NAMES // for TheVeterancyNames[]
  29. #include "GameLogic/CrateSystem.h"
  30. #include "Common/BitFlagsIO.h"
  31. CrateSystem *TheCrateSystem = NULL;
  32. CrateSystem::CrateSystem()
  33. {
  34. m_crateTemplateVector.clear();
  35. }
  36. CrateSystem::~CrateSystem()
  37. {
  38. Int count = m_crateTemplateVector.size();
  39. for( Int templateIndex = 0; templateIndex < count; templateIndex ++ )
  40. {
  41. CrateTemplate *currentTemplate = m_crateTemplateVector[templateIndex];
  42. if( currentTemplate )
  43. {
  44. currentTemplate->deleteInstance();
  45. }
  46. }
  47. m_crateTemplateVector.clear();
  48. }
  49. void CrateSystem::init( void )
  50. {
  51. reset();
  52. }
  53. void CrateSystem::reset( void )
  54. {
  55. // clean up overrides
  56. std::vector<CrateTemplate *>::iterator it;
  57. for( it = m_crateTemplateVector.begin(); it != m_crateTemplateVector.end(); )
  58. {
  59. CrateTemplate *currentTemplate = *it;
  60. if( currentTemplate )
  61. {
  62. Overridable *tempCrateTemplate = currentTemplate->deleteOverrides();
  63. if (!tempCrateTemplate)
  64. {
  65. // base dude was an override - kill it from the vector
  66. it = m_crateTemplateVector.erase(it);
  67. }
  68. else
  69. {
  70. ++it;
  71. }
  72. }
  73. else
  74. {
  75. it = m_crateTemplateVector.erase(it);
  76. }
  77. }
  78. }
  79. void CrateSystem::parseCrateTemplateDefinition(INI* ini)
  80. {
  81. AsciiString name;
  82. // read the crateTemplate name
  83. const char* c = ini->getNextToken();
  84. name.set(c);
  85. CrateTemplate *crateTemplate = TheCrateSystem->friend_findCrateTemplate(name);
  86. if (crateTemplate == NULL) {
  87. crateTemplate = TheCrateSystem->newCrateTemplate(name);
  88. if (ini->getLoadType() == INI_LOAD_CREATE_OVERRIDES) {
  89. crateTemplate->markAsOverride();
  90. }
  91. } else if( ini->getLoadType() != INI_LOAD_CREATE_OVERRIDES ) {
  92. DEBUG_CRASH(( "[LINE: %d in '%s'] Duplicate crate %s found!", ini->getLineNum(), ini->getFilename().str(), name.str() ));
  93. } else {
  94. crateTemplate = TheCrateSystem->newCrateTemplateOverride(crateTemplate);
  95. }
  96. // parse the ini weapon definition
  97. ini->initFromINI(crateTemplate, crateTemplate->getFieldParse());
  98. }
  99. CrateTemplate *CrateSystem::newCrateTemplate( AsciiString name )
  100. {
  101. // sanity
  102. if(name.isEmpty())
  103. return NULL;
  104. // allocate a new weapon
  105. CrateTemplate *ct = newInstance(CrateTemplate);
  106. // if the default template is present, get it and copy over any data to the new template
  107. const CrateTemplate *defaultCT = findCrateTemplate(AsciiString("DefaultCrate"));
  108. if(defaultCT)
  109. {
  110. *ct = *defaultCT;
  111. }
  112. ct->setName( name );
  113. m_crateTemplateVector.push_back(ct);
  114. return ct;
  115. }
  116. CrateTemplate *CrateSystem::newCrateTemplateOverride( CrateTemplate *crateToOverride )
  117. {
  118. if (!crateToOverride) {
  119. return NULL;
  120. }
  121. CrateTemplate *newOverride = newInstance(CrateTemplate);
  122. *newOverride = *crateToOverride;
  123. newOverride->markAsOverride();
  124. crateToOverride->setNextOverride(newOverride);
  125. return newOverride;
  126. }
  127. const CrateTemplate *CrateSystem::findCrateTemplate(AsciiString name) const
  128. {
  129. // search weapon list for name
  130. for (Int i = 0; i < m_crateTemplateVector.size(); i++)
  131. if(m_crateTemplateVector[i]->getName() == name) {
  132. CrateTemplateOverride overridable(m_crateTemplateVector[i]);
  133. return overridable;
  134. }
  135. return NULL;
  136. }
  137. CrateTemplate *CrateSystem::friend_findCrateTemplate(AsciiString name)
  138. {
  139. // search weapon list for name
  140. for (Int i = 0; i < m_crateTemplateVector.size(); i++)
  141. if(m_crateTemplateVector[i]->getName() == name) {
  142. CrateTemplateOverride overridable(m_crateTemplateVector[i]);
  143. return const_cast<CrateTemplate*>((const CrateTemplate *)overridable);
  144. }
  145. return NULL;
  146. }
  147. //--------------------------------------------------------------------------------
  148. //--------------------------------------------------------------------------------
  149. //--------------------------------------------------------------------------------
  150. //--------------------------------------------------------------------------------
  151. //--------------------------------------------------------------------------------
  152. const FieldParse CrateTemplate::TheCrateTemplateFieldParseTable[] =
  153. {
  154. { "CreationChance", INI::parseReal, NULL, offsetof( CrateTemplate, m_creationChance ) },
  155. { "VeterancyLevel", INI::parseIndexList, TheVeterancyNames, offsetof( CrateTemplate, m_veterancyLevel ) },
  156. { "KilledByType", KindOfMaskType::parseFromINI, NULL, offsetof( CrateTemplate, m_killedByTypeKindof) },
  157. { "CrateObject", CrateTemplate::parseCrateCreationEntry, NULL, NULL },
  158. { "KillerScience", INI::parseScience, NULL, offsetof( CrateTemplate, m_killerScience) },
  159. { "OwnedByMaker", INI::parseBool, NULL, offsetof( CrateTemplate, m_isOwnedByMaker) },
  160. { NULL, NULL, NULL, NULL }, // keep this last!
  161. };
  162. CrateTemplate::CrateTemplate()
  163. {
  164. m_name = "";
  165. m_creationChance = 0;
  166. CLEAR_KINDOFMASK(m_killedByTypeKindof);
  167. m_veterancyLevel = LEVEL_INVALID;
  168. m_killerScience = SCIENCE_INVALID;
  169. m_possibleCrates.clear();
  170. m_isOwnedByMaker = FALSE;
  171. }
  172. CrateTemplate::~CrateTemplate()
  173. {
  174. m_possibleCrates.clear();
  175. }
  176. void CrateTemplate::parseCrateCreationEntry( INI* ini, void *instance, void *, const void* )
  177. {
  178. CrateTemplate *self = (CrateTemplate *)instance;
  179. const char *token = ini->getNextToken();
  180. AsciiString crateName = token;
  181. token = ini->getNextToken();
  182. Real crateValue;
  183. if (sscanf( token, "%f", &crateValue ) != 1)
  184. throw INI_INVALID_DATA;
  185. crateCreationEntry newEntry;
  186. newEntry.crateName = crateName;
  187. newEntry.crateChance = crateValue;
  188. self->m_possibleCrates.push_back( newEntry );
  189. }