ResourceGatheringManager.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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: ResourceGatheringManager.cpp ///////////////////////////////////////////////////////////
  24. // The part of a Player's brain that keeps track of all Resource type Objects and makes
  25. // gathering type decisions based on them.
  26. // Author: Graham Smallwood, January, 2002
  27. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  28. #include "Common/ResourceGatheringManager.h"
  29. #include "Common/ActionManager.h"
  30. #include "Common/Xfer.h"
  31. #include "GameLogic/GameLogic.h"
  32. #include "GameLogic/Object.h"
  33. #include "GameLogic/PartitionManager.h"
  34. #include "GameLogic/Module/SupplyTruckAIUpdate.h"
  35. #include "GameLogic/Module/SupplyCenterDockUpdate.h"
  36. #include "GameLogic/Module/SupplyWarehouseDockUpdate.h"
  37. #include "GameLogic/Module/UpdateModule.h"
  38. ResourceGatheringManager::ResourceGatheringManager()
  39. {
  40. }
  41. ResourceGatheringManager::~ResourceGatheringManager()
  42. {
  43. m_supplyWarehouses.erase( m_supplyWarehouses.begin(), m_supplyWarehouses.end() );
  44. m_supplyCenters.erase( m_supplyCenters.begin(), m_supplyCenters.end() );
  45. }
  46. void ResourceGatheringManager::addSupplyCenter( Object *newCenter )
  47. {
  48. if( newCenter == NULL )
  49. return;
  50. m_supplyCenters.push_back( newCenter->getID() );
  51. }
  52. void ResourceGatheringManager::removeSupplyCenter( Object *oldCenter )
  53. {
  54. if( oldCenter == NULL )
  55. return;
  56. ObjectID targetID = oldCenter->getID();
  57. objectIDListIterator iterator = m_supplyCenters.begin();
  58. while( iterator != m_supplyCenters.end() )
  59. {
  60. if( targetID == *iterator )
  61. {
  62. iterator = m_supplyCenters.erase( iterator );
  63. }
  64. else
  65. iterator++;
  66. }
  67. }
  68. void ResourceGatheringManager::addSupplyWarehouse( Object *newWarehouse )
  69. {
  70. if( newWarehouse == NULL )
  71. return;
  72. m_supplyWarehouses.push_back( newWarehouse->getID() );
  73. }
  74. void ResourceGatheringManager::removeSupplyWarehouse( Object *oldWarehouse )
  75. {
  76. if( oldWarehouse == NULL )
  77. return;
  78. ObjectID targetID = oldWarehouse->getID();
  79. objectIDListIterator iterator = m_supplyWarehouses.begin();
  80. while( iterator != m_supplyWarehouses.end() )
  81. {
  82. if( targetID == *iterator )
  83. {
  84. iterator = m_supplyWarehouses.erase( iterator );
  85. }
  86. else
  87. iterator++;
  88. }
  89. }
  90. static Real computeRelativeCost( Object *queryObject, Object *destObject, Real *pureDistanceSquared )
  91. {
  92. /** @todo This gets filled with Pathfinding computations, analysis of Boxes remaining,
  93. Threat calculations, paths of other trucks, and other fancy stuff.
  94. */
  95. //A good score is a very small number.
  96. if( queryObject == NULL || destObject == NULL )
  97. return FLT_MAX;
  98. if( !TheActionManager->canTransferSuppliesAt(queryObject, destObject) )
  99. return FLT_MAX;// Handles emptyness and alliances
  100. DockUpdateInterface *dockInterface = destObject->getDockUpdateInterface();
  101. if( !dockInterface->isClearToApproach( queryObject ) )
  102. return FLT_MAX;
  103. // since we don't care about the distance as a distance per se, but rather as
  104. // a goodness-factor, save some time by getting the dist-sqr (srj)
  105. Real distSquared = ThePartitionManager->getDistanceSquared(queryObject, destObject, FROM_CENTER_3D);
  106. // I need the distance, but I don't want to count on the coincidence that
  107. // the abstract 'cost' this function returns happens to be just the distance, since it could
  108. // become more complicated
  109. if( pureDistanceSquared )
  110. *pureDistanceSquared = distSquared;
  111. return distSquared;
  112. }
  113. Object *ResourceGatheringManager::findBestSupplyWarehouse( Object *queryObject )
  114. {
  115. Object *bestWarehouse = NULL;
  116. Real maxDistanceSquared = 100000;
  117. if( ( queryObject == NULL ) || ( queryObject->getAI() == NULL ) )
  118. return NULL;
  119. SupplyTruckAIInterface *supplyTruckAI = queryObject->getAI()->getSupplyTruckAIInterface();
  120. if( supplyTruckAI )
  121. {
  122. // Check for a dock override being set.
  123. ObjectID dockID = supplyTruckAI->getPreferredDockID();
  124. Object *dock = TheGameLogic->findObjectByID(dockID);
  125. if( dock )
  126. {
  127. static const NameKeyType key_warehouseUpdate = NAMEKEY("SupplyWarehouseDockUpdate");
  128. SupplyWarehouseDockUpdate *warehouseModule = (SupplyWarehouseDockUpdate*)dock->findUpdateModule( key_warehouseUpdate );
  129. //If remotely okay, let User win.
  130. if( warehouseModule && computeRelativeCost( queryObject, dock, NULL ) != FLT_MAX )
  131. return dock;
  132. }
  133. // Please note, there is not a separate Warehouse and Center memory by Design. Because
  134. // we lack a UI way to click Warehouse and drag to center to set up a specific path, the
  135. // practical realization has been made that you do not want separate memory.
  136. // Design wants a harvester to give up and return to base if it is "too far" to the warehouse.
  137. // Note, the "PreferedDock" will override this, and there is no distance max on Centers.
  138. maxDistanceSquared = supplyTruckAI->getWarehouseScanDistance() * supplyTruckAI->getWarehouseScanDistance();
  139. }
  140. //Otherwise, search for a good one.
  141. Real bestCost = FLT_MAX;
  142. objectIDListIterator iterator = m_supplyWarehouses.begin();
  143. while( iterator != m_supplyWarehouses.end() )
  144. {
  145. ObjectID currentID = *iterator;
  146. Object *currentWarehouse =TheGameLogic->findObjectByID(currentID);
  147. if( currentWarehouse == NULL )
  148. {
  149. iterator = m_supplyWarehouses.erase( iterator );
  150. }
  151. else
  152. {
  153. Real distanceSquared;
  154. Real currentCost = computeRelativeCost( queryObject, currentWarehouse, &distanceSquared );
  155. if( (currentCost < bestCost) && (distanceSquared < maxDistanceSquared) )
  156. {
  157. bestWarehouse = currentWarehouse;
  158. bestCost = currentCost;
  159. }
  160. iterator++;
  161. }
  162. }
  163. return bestWarehouse;
  164. }
  165. Object *ResourceGatheringManager::findBestSupplyCenter( Object *queryObject )
  166. {
  167. Object *bestCenter = NULL;
  168. if( ( queryObject == NULL ) || ( queryObject->getAI() == NULL ) )
  169. return NULL;
  170. SupplyTruckAIInterface *supplyTruckAI = queryObject->getAI()->getSupplyTruckAIInterface();
  171. if( supplyTruckAI )
  172. {
  173. // Check for a dock override being set.
  174. ObjectID dockID = supplyTruckAI->getPreferredDockID();
  175. Object *dock = TheGameLogic->findObjectByID(dockID);
  176. if( dock )
  177. {
  178. static const NameKeyType key_centerUpdate = NAMEKEY("SupplyCenterDockUpdate");
  179. SupplyWarehouseDockUpdate *centerModule = (SupplyWarehouseDockUpdate*)dock->findUpdateModule( key_centerUpdate );
  180. //If remotely okay, let User win.
  181. if( centerModule && computeRelativeCost( queryObject, dock, NULL ) != FLT_MAX )
  182. return dock;
  183. }
  184. // Please note, there is not a separate Warehouse and Center memory by Design. Because
  185. // we lack a UI way to click Warehouse and drag to center to set up a specific path, the
  186. // practical realization has been made that you do not want separate memory.
  187. }
  188. //Otherwise, search for a good one.
  189. Real bestCost = FLT_MAX;
  190. objectIDListIterator iterator = m_supplyCenters.begin();
  191. while( iterator != m_supplyCenters.end() )
  192. {
  193. ObjectID currentID = *iterator;
  194. Object *currentCenter =TheGameLogic->findObjectByID(currentID);
  195. if( currentCenter == NULL )
  196. {
  197. iterator = m_supplyWarehouses.erase( iterator );
  198. }
  199. else
  200. {
  201. Real currentCost = computeRelativeCost( queryObject, currentCenter, NULL );
  202. if( currentCost < bestCost )
  203. {
  204. bestCenter = currentCenter;
  205. bestCost = currentCost;
  206. }
  207. iterator++;
  208. }
  209. }
  210. return bestCenter;
  211. }
  212. // ------------------------------------------------------------------------------------------------
  213. /** CRC */
  214. // ------------------------------------------------------------------------------------------------
  215. void ResourceGatheringManager::crc( Xfer *xfer )
  216. {
  217. } // end crc
  218. // ------------------------------------------------------------------------------------------------
  219. /** Xfer method
  220. * Version Info:
  221. * 1: Initial version */
  222. // ------------------------------------------------------------------------------------------------
  223. void ResourceGatheringManager::xfer( Xfer *xfer )
  224. {
  225. // version
  226. XferVersion currentVersion = 1;
  227. XferVersion version = currentVersion;
  228. xfer->xferVersion( &version, currentVersion );
  229. // supply warehouses
  230. xfer->xferSTLObjectIDList( &m_supplyWarehouses );
  231. // supply centers
  232. xfer->xferSTLObjectIDList( &m_supplyCenters );
  233. } // end xfer
  234. // ------------------------------------------------------------------------------------------------
  235. /** Load post process */
  236. // ------------------------------------------------------------------------------------------------
  237. void ResourceGatheringManager::loadPostProcess( void )
  238. {
  239. } // end loadPostProcess