OCLSpecialPower.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  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: OCLSpecialPower.cpp //////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, April 2002
  25. // Desc: Special powers that are driven by object creation lists
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/Player.h"
  30. #include "Common/RandomValue.h"
  31. #include "Common/ThingFactory.h"
  32. #include "Common/Xfer.h"
  33. #include "GameLogic/Object.h"
  34. #include "GameLogic/ObjectCreationList.h"
  35. #include "GameLogic/PartitionManager.h"
  36. #include "GameLogic/TerrainLogic.h"
  37. #include "GameLogic/Module/OCLSpecialPower.h"
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////
  39. // MODULE DATA ////////////////////////////////////////////////////////////////////////////////////
  40. ///////////////////////////////////////////////////////////////////////////////////////////////////
  41. #ifdef _INTERNAL
  42. // for occasional debugging...
  43. //#pragma optimize("", off)
  44. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  45. #endif
  46. enum
  47. {
  48. CREATE_ABOVE_LOCATION_HEIGHT = 300,
  49. MAX_ADJUST_RADIUS = 500
  50. };
  51. static const char* TheOCLCreateLocTypeNames[] =
  52. {
  53. "CREATE_AT_EDGE_NEAR_SOURCE",
  54. "CREATE_AT_EDGE_NEAR_TARGET",
  55. "CREATE_AT_LOCATION",
  56. "USE_OWNER_OBJECT",
  57. "CREATE_ABOVE_LOCATION",
  58. "CREATE_AT_EDGE_FARTHEST_FROM_TARGET",
  59. NULL
  60. };
  61. //-------------------------------------------------------------------------------------------------
  62. //-------------------------------------------------------------------------------------------------
  63. OCLSpecialPowerModuleData::OCLSpecialPowerModuleData( void )
  64. {
  65. m_defaultOCL = NULL;
  66. m_upgradeOCL.clear();
  67. m_createLoc = CREATE_AT_EDGE_NEAR_SOURCE;
  68. m_isOCLAdjustPositionToPassable = FALSE;
  69. }
  70. //-------------------------------------------------------------------------------------------------
  71. //-------------------------------------------------------------------------------------------------
  72. static void parseOCLUpgradePair( INI* ini, void * /*instance*/, void *store, const void* /*userData*/ )
  73. {
  74. OCLSpecialPowerModuleData::Upgrades up;
  75. INI::parseScience(ini, NULL, &up.m_science, NULL);
  76. INI::parseObjectCreationList(ini, NULL, &up.m_ocl, NULL);
  77. std::vector<OCLSpecialPowerModuleData::Upgrades>* s = (std::vector<OCLSpecialPowerModuleData::Upgrades>*)store;
  78. s->push_back(up);
  79. }
  80. //-------------------------------------------------------------------------------------------------
  81. //-------------------------------------------------------------------------------------------------
  82. /* static */ void OCLSpecialPowerModuleData::buildFieldParse(MultiIniFieldParse& p)
  83. {
  84. SpecialPowerModuleData::buildFieldParse( p );
  85. static const FieldParse dataFieldParse[] =
  86. {
  87. { "UpgradeOCL", parseOCLUpgradePair, NULL, offsetof( OCLSpecialPowerModuleData, m_upgradeOCL ) },
  88. { "OCL", INI::parseObjectCreationList, NULL, offsetof( OCLSpecialPowerModuleData, m_defaultOCL ) },
  89. { "CreateLocation", INI::parseIndexList, TheOCLCreateLocTypeNames, offsetof( OCLSpecialPowerModuleData, m_createLoc ) },
  90. { "ReferenceObject", INI::parseAsciiString, NULL, offsetof( OCLSpecialPowerModuleData, m_referenceThingName ) },
  91. { "OCLAdjustPositionToPassable", INI::parseBool, NULL, offsetof( OCLSpecialPowerModuleData, m_isOCLAdjustPositionToPassable ) },
  92. { 0, 0, 0, 0 }
  93. };
  94. p.add(dataFieldParse);
  95. }
  96. ///////////////////////////////////////////////////////////////////////////////////////////////////
  97. // MODULE /////////////////////////////////////////////////////////////////////////////////////////
  98. ///////////////////////////////////////////////////////////////////////////////////////////////////
  99. //-------------------------------------------------------------------------------------------------
  100. //-------------------------------------------------------------------------------------------------
  101. OCLSpecialPower::OCLSpecialPower( Thing *thing, const ModuleData *moduleData )
  102. : SpecialPowerModule( thing, moduleData )
  103. {
  104. }
  105. //-------------------------------------------------------------------------------------------------
  106. //-------------------------------------------------------------------------------------------------
  107. const ObjectCreationList* OCLSpecialPower::findOCL() const
  108. {
  109. const OCLSpecialPowerModuleData* d = getOCLSpecialPowerModuleData();
  110. const Player* controller = getObject()->getControllingPlayer();
  111. if (controller != NULL)
  112. {
  113. for (std::vector<OCLSpecialPowerModuleData::Upgrades>::const_iterator it = d->m_upgradeOCL.begin();
  114. it != d->m_upgradeOCL.end();
  115. ++it)
  116. {
  117. if (controller->hasScience(it->m_science))
  118. return it->m_ocl;
  119. }
  120. }
  121. return d->m_defaultOCL;
  122. }
  123. //-------------------------------------------------------------------------------------------------
  124. //-------------------------------------------------------------------------------------------------
  125. OCLSpecialPower::~OCLSpecialPower( void )
  126. {
  127. }
  128. //-------------------------------------------------------------------------------------------------
  129. /** Execute the power */
  130. //-------------------------------------------------------------------------------------------------
  131. void OCLSpecialPower::doSpecialPowerAtLocation( const Coord3D *loc, Real angle, UnsignedInt commandOptions )
  132. {
  133. if (getObject()->isDisabled())
  134. return;
  135. // sanity
  136. if( loc == NULL )
  137. return;
  138. // get the module data
  139. const OCLSpecialPowerModuleData *modData = getOCLSpecialPowerModuleData();
  140. Coord3D targetCoord = *loc;
  141. if( modData->m_isOCLAdjustPositionToPassable )
  142. {
  143. FindPositionOptions fpOptions;
  144. fpOptions.flags = FPF_CLEAR_CELLS_ONLY;
  145. fpOptions.maxRadius = MAX_ADJUST_RADIUS;
  146. if ( ! ThePartitionManager->findPositionAround(&targetCoord, &fpOptions, &targetCoord) )
  147. { // if findPosition() fails, then don't monkey with target Coord!
  148. targetCoord = *loc;
  149. }
  150. }
  151. // call the base class action cause we are *EXTENDING* functionality
  152. SpecialPowerModule::doSpecialPowerAtLocation( &targetCoord, angle, commandOptions );
  153. const ObjectCreationList* ocl = findOCL();
  154. // at what point will the "deliverer" come in
  155. Coord3D creationCoord;
  156. switch (modData->m_createLoc)
  157. {
  158. case CREATE_AT_EDGE_NEAR_SOURCE:
  159. creationCoord = TheTerrainLogic->findClosestEdgePoint( getObject()->getPosition() );
  160. ObjectCreationList::create( ocl, getObject(), &creationCoord, &targetCoord, angle );
  161. break;
  162. case CREATE_AT_EDGE_NEAR_TARGET:
  163. creationCoord = TheTerrainLogic->findClosestEdgePoint(&targetCoord);
  164. ObjectCreationList::create( ocl, getObject(), &creationCoord, &targetCoord, angle );
  165. break;
  166. case CREATE_AT_EDGE_FARTHEST_FROM_TARGET:
  167. creationCoord = TheTerrainLogic->findFarthestEdgePoint(&targetCoord);
  168. creationCoord.z += CREATE_ABOVE_LOCATION_HEIGHT;
  169. ObjectCreationList::create( ocl, getObject(), &creationCoord, &targetCoord, angle );
  170. break;
  171. case CREATE_AT_LOCATION:
  172. // this is the case where the special power stuff originates at the location of the mouse click
  173. creationCoord = targetCoord;
  174. ObjectCreationList::create( ocl, getObject(), &creationCoord, &targetCoord, angle );
  175. break;
  176. case USE_OWNER_OBJECT:
  177. creationCoord.set( &targetCoord );
  178. ObjectCreationList::create( ocl, getObject(), &creationCoord, &targetCoord, angle, false );
  179. break;
  180. case CREATE_ABOVE_LOCATION:
  181. // this is the case where the special power stuff originates above the location of the mouse click
  182. creationCoord = targetCoord;
  183. creationCoord.z += CREATE_ABOVE_LOCATION_HEIGHT;
  184. ObjectCreationList::create( ocl, getObject(), &creationCoord, &targetCoord, angle );
  185. break;
  186. }
  187. }
  188. // ------------------------------------------------------------------------------------------------
  189. // ------------------------------------------------------------------------------------------------
  190. void OCLSpecialPower::doSpecialPowerAtObject( Object *obj, UnsignedInt commandOptions )
  191. {
  192. if (getObject()->isDisabled())
  193. return;
  194. // convert to a location
  195. if( !obj )
  196. return;
  197. doSpecialPowerAtLocation( obj->getPosition(), INVALID_ANGLE, commandOptions );
  198. }
  199. // ------------------------------------------------------------------------------------------------
  200. void OCLSpecialPower::doSpecialPower( UnsignedInt commandOptions )
  201. {
  202. if (getObject()->isDisabled())
  203. return;
  204. Coord3D creationCoord;
  205. creationCoord.set( getObject()->getPosition() );
  206. // call the base class action cause we are *EXTENDING* functionality
  207. SpecialPowerModule::doSpecialPowerAtLocation( &creationCoord, INVALID_ANGLE, commandOptions );
  208. const ObjectCreationList* ocl = findOCL();
  209. ObjectCreationList::create( ocl, getObject(), &creationCoord, &creationCoord, false );
  210. }
  211. // ------------------------------------------------------------------------------------------------
  212. const ThingTemplate* OCLSpecialPower::getReferenceThingTemplate() const
  213. {
  214. return TheThingFactory->findTemplate( getOCLSpecialPowerModuleData()->m_referenceThingName );
  215. }
  216. // ------------------------------------------------------------------------------------------------
  217. /** CRC */
  218. // ------------------------------------------------------------------------------------------------
  219. void OCLSpecialPower::crc( Xfer *xfer )
  220. {
  221. // extend base class
  222. SpecialPowerModule::crc( xfer );
  223. } // end crc
  224. // ------------------------------------------------------------------------------------------------
  225. /** Xfer method
  226. * Version Info:
  227. * 1: Initial version */
  228. // ------------------------------------------------------------------------------------------------
  229. void OCLSpecialPower::xfer( Xfer *xfer )
  230. {
  231. // version
  232. XferVersion currentVersion = 1;
  233. XferVersion version = currentVersion;
  234. xfer->xferVersion( &version, currentVersion );
  235. // extend base class
  236. SpecialPowerModule::xfer( xfer );
  237. } // end xfer
  238. // ------------------------------------------------------------------------------------------------
  239. /** Load post process */
  240. // ------------------------------------------------------------------------------------------------
  241. void OCLSpecialPower::loadPostProcess( void )
  242. {
  243. // extend base class
  244. SpecialPowerModule::loadPostProcess();
  245. } // end loadPostProcess