OverlordContain.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  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: OverlordContain.cpp ////////////////////////////////////////////////////////////////////////
  24. // Author: Graham Smallwood, September, 2002
  25. // Desc: Contain module that acts as transport normally, but when full it redirects queries to the first passenger
  26. // All of this redirection stuff makes it so that while I am normally a transport
  27. // for Overlord subObjects, once I have a passenger, _I_ become a transport of their type.
  28. // So, the answer to this question depends on if it is my passenger asking, or theirs.
  29. // As always, I can't use convience functions that get redirected on a ? like this.
  30. ///////////////////////////////////////////////////////////////////////////////////////////////////
  31. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  32. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  33. #include "Common/Player.h"
  34. #include "Common/Xfer.h"
  35. #include "GameClient/ControlBar.h"
  36. #include "GameClient/Drawable.h"
  37. #include "GameLogic/Module/BodyModule.h"
  38. #include "GameLogic/Module/OverlordContain.h"
  39. #include "GameLogic/Object.h"
  40. #include "GameLogic/PartitionManager.h"
  41. // ------------------------------------------------------------------------------------------------
  42. // ------------------------------------------------------------------------------------------------
  43. OverlordContainModuleData::OverlordContainModuleData()
  44. {
  45. }
  46. // ------------------------------------------------------------------------------------------------
  47. // ------------------------------------------------------------------------------------------------
  48. void OverlordContainModuleData::buildFieldParse(MultiIniFieldParse& p)
  49. {
  50. TransportContainModuleData::buildFieldParse(p);
  51. static const FieldParse dataFieldParse[] =
  52. {
  53. { 0, 0, 0, 0 }
  54. };
  55. p.add(dataFieldParse);
  56. }
  57. // ------------------------------------------------------------------------------------------------
  58. // ------------------------------------------------------------------------------------------------
  59. OverlordContain::OverlordContain( Thing *thing, const ModuleData *moduleData ) :
  60. TransportContain( thing, moduleData )
  61. {
  62. m_redirectionActivated = FALSE;
  63. }
  64. //-------------------------------------------------------------------------------------------------
  65. //-------------------------------------------------------------------------------------------------
  66. OverlordContain::~OverlordContain( void )
  67. {
  68. }
  69. //-------------------------------------------------------------------------------------------------
  70. //-------------------------------------------------------------------------------------------------
  71. void OverlordContain::onBodyDamageStateChange( const DamageInfo* damageInfo,
  72. BodyDamageType oldState,
  73. BodyDamageType newState) ///< state change callback
  74. {
  75. // I can't use any convienience functions, as they will all get routed to the bunker I may carry.
  76. // I want just me.
  77. // Oh, and I don't want this function trying to do death. That is more complicated and will be handled
  78. // on my death.
  79. if( newState != BODY_RUBBLE && m_containListSize == 1 )
  80. {
  81. Object *myGuy = m_containList.front();
  82. myGuy->getBodyModule()->setDamageState( newState );
  83. }
  84. }
  85. //-------------------------------------------------------------------------------------------------
  86. //-------------------------------------------------------------------------------------------------
  87. ContainModuleInterface *OverlordContain::getRedirectedContain() const
  88. {
  89. // Naturally, I can not use a redirectible convienience function
  90. // to answer if I am redirecting yet.
  91. // If I am empty, say no.
  92. if( m_containListSize < 1 )
  93. return NULL;
  94. if( !m_redirectionActivated )
  95. return NULL;// Shut off early to allow death to happen without my bunker having
  96. // trouble finding me to say goodbye as messages get sucked up the pipe to him.
  97. Object *myGuy = m_containList.front();
  98. if( myGuy )
  99. return myGuy->getContain();
  100. return NULL;// Or say no if they have no contain.
  101. }
  102. //-------------------------------------------------------------------------------------------------
  103. //-------------------------------------------------------------------------------------------------
  104. //-------------------------------------------------------------------------------------------------
  105. //-------------------------------------------------------------------------------------------------
  106. void OverlordContain::onDie( const DamageInfo *damageInfo )
  107. {
  108. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  109. if( getRedirectedContain() == NULL )
  110. {
  111. TransportContain::onDie( damageInfo );
  112. return;
  113. }
  114. //Everything is fine if I am empty or carrying a regular guy. If I have a redirected contain
  115. // set up, then I need to handle the order of death explicitly, or things will become confused
  116. // when I stop redirecting in the middle of the process. Or I will get confused as my commands
  117. // get sucked up the pipe.
  118. // So this is an extend that lets me control the order of death.
  119. deactivateRedirectedContain();
  120. Object *myGuy = m_containList.front();
  121. myGuy->kill();
  122. TransportContain::onDie( damageInfo );
  123. }
  124. //-------------------------------------------------------------------------------------------------
  125. void OverlordContain::onDelete( void )
  126. {
  127. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  128. if( getRedirectedContain() == NULL )
  129. {
  130. TransportContain::onDelete( );
  131. return;
  132. }
  133. // Without my throwing the redirect switch, teardown deletion will get confused and fire off a bunch of asserts
  134. getRedirectedContain()->removeAllContained();
  135. deactivateRedirectedContain();
  136. removeAllContained();
  137. TransportContain::onDelete( );
  138. }
  139. // ------------------------------------------------------------------------------------------------
  140. void OverlordContain::onCapture( Player *oldOwner, Player *newOwner )
  141. {
  142. if( m_containListSize < 1 )
  143. return;
  144. // Need to capture our specific rider. He will then kick passengers out if he is a Transport
  145. Object *myGuy = m_containList.front();
  146. myGuy->setTeam( newOwner->getDefaultTeam() );
  147. }
  148. //-------------------------------------------------------------------------------------------------
  149. Bool OverlordContain::isGarrisonable() const
  150. {
  151. if( getRedirectedContain() == NULL )
  152. return FALSE;
  153. return getRedirectedContain()->isGarrisonable();
  154. }
  155. //-------------------------------------------------------------------------------------------------
  156. Bool OverlordContain::isKickOutOnCapture()
  157. {
  158. if( getRedirectedContain() == NULL )
  159. return FALSE;// Me the Overlord doesn't want to
  160. return getRedirectedContain()->isKickOutOnCapture();
  161. }
  162. //-------------------------------------------------------------------------------------------------
  163. void OverlordContain::addToContainList( Object *obj )
  164. {
  165. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  166. if( getRedirectedContain() == NULL )
  167. {
  168. TransportContain::addToContainList( obj );
  169. return;
  170. }
  171. getRedirectedContain()->addToContainList( obj );
  172. }
  173. //-------------------------------------------------------------------------------------------------
  174. void OverlordContain::addToContain( Object *obj )
  175. {
  176. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  177. if( getRedirectedContain() == NULL )
  178. {
  179. TransportContain::addToContain( obj );
  180. return;
  181. }
  182. getRedirectedContain()->addToContain( obj );
  183. }
  184. //-------------------------------------------------------------------------------------------------
  185. /** Remove 'obj' from the m_containList of objects in this module.
  186. * This will trigger an onRemoving event for the object that this module
  187. * is a part of and an onRemovedFrom event for the object being removed */
  188. //-------------------------------------------------------------------------------------------------
  189. void OverlordContain::removeFromContain( Object *obj, Bool exposeStealthUnits )
  190. {
  191. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  192. if( getRedirectedContain() == NULL )
  193. {
  194. TransportContain::removeFromContain( obj, exposeStealthUnits );
  195. return;
  196. }
  197. getRedirectedContain()->removeFromContain( obj, exposeStealthUnits );
  198. }
  199. //-------------------------------------------------------------------------------------------------
  200. /** Remove all contained objects from the contained list */
  201. //-------------------------------------------------------------------------------------------------
  202. void OverlordContain::removeAllContained( Bool exposeStealthUnits )
  203. {
  204. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  205. if( getRedirectedContain() == NULL )
  206. {
  207. TransportContain::removeAllContained( exposeStealthUnits );
  208. return;
  209. }
  210. const ContainedItemsList *fullList = getRedirectedContain()->getContainedItemsList();
  211. Object *obj;
  212. ContainedItemsList::const_iterator it;
  213. it = (*fullList).begin();
  214. while( it != (*fullList).end() )
  215. {
  216. obj = *it;
  217. it++;
  218. removeFromContain( obj, exposeStealthUnits );
  219. }
  220. }
  221. //-------------------------------------------------------------------------------------------------
  222. /** Iterate the contained list and call the callback on each of the objects */
  223. //-------------------------------------------------------------------------------------------------
  224. void OverlordContain::iterateContained( ContainIterateFunc func, void *userData, Bool reverse )
  225. {
  226. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  227. if( getRedirectedContain() == NULL )
  228. {
  229. TransportContain::iterateContained( func, userData, reverse );
  230. return;
  231. }
  232. getRedirectedContain()->iterateContained( func, userData, reverse );
  233. }
  234. //-------------------------------------------------------------------------------------------------
  235. void OverlordContain::onContaining( Object *obj )
  236. {
  237. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  238. if( getRedirectedContain() == NULL )
  239. {
  240. TransportContain::onContaining( obj );
  241. activateRedirectedContain();//Am now carrying something
  242. return;
  243. }
  244. OpenContain::onContaining(obj);
  245. getRedirectedContain()->onContaining( obj );
  246. }
  247. //-------------------------------------------------------------------------------------------------
  248. void OverlordContain::onRemoving( Object *obj )
  249. {
  250. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  251. if( getRedirectedContain() == NULL )
  252. {
  253. TransportContain::onRemoving( obj );
  254. return;
  255. }
  256. OpenContain::onRemoving(obj);
  257. getRedirectedContain()->onRemoving( obj );
  258. }
  259. //-------------------------------------------------------------------------------------------------
  260. Bool OverlordContain::isValidContainerFor(const Object* obj, Bool checkCapacity) const
  261. {
  262. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  263. if( getRedirectedContain() == NULL )
  264. return TransportContain::isValidContainerFor( obj, checkCapacity );
  265. return getRedirectedContain()->isValidContainerFor( obj, checkCapacity );
  266. }
  267. //-------------------------------------------------------------------------------------------------
  268. UnsignedInt OverlordContain::getContainCount() const
  269. {
  270. ContainModuleInterface* redir = getRedirectedContain();
  271. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  272. if( redir == NULL )
  273. return TransportContain::getContainCount( );
  274. return redir->getContainCount();
  275. }
  276. //-------------------------------------------------------------------------------------------------
  277. Bool OverlordContain::getContainerPipsToShow(Int& numTotal, Int& numFull)
  278. {
  279. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  280. if( getRedirectedContain() == NULL )
  281. {
  282. numTotal = 0;
  283. numFull = 0;
  284. return false;
  285. }
  286. else
  287. {
  288. return getRedirectedContain()->getContainerPipsToShow(numTotal, numFull);
  289. }
  290. }
  291. //-------------------------------------------------------------------------------------------------
  292. Int OverlordContain::getContainMax( ) const
  293. {
  294. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  295. if( getRedirectedContain() == NULL )
  296. return TransportContain::getContainMax( );
  297. return getRedirectedContain()->getContainMax();
  298. }
  299. //-------------------------------------------------------------------------------------------------
  300. const ContainedItemsList* OverlordContain::getContainedItemsList() const
  301. {
  302. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  303. if( getRedirectedContain() == NULL )
  304. return TransportContain::getContainedItemsList( );
  305. return getRedirectedContain()->getContainedItemsList();
  306. }
  307. //-------------------------------------------------------------------------------------------------
  308. Bool OverlordContain::isEnclosingContainerFor( const Object *obj ) const
  309. {
  310. // All of this redirection stuff makes it so that while I am normally a transport
  311. // for Overlord subObjects, once I have a passenger, _I_ become a transport of their type.
  312. // So, the answer to this question depends on if it is my passenger asking, or theirs.
  313. // As always, I can't use convience functions that get redirected on a ? like this.
  314. if( m_containListSize > 0 && obj == m_containList.front() )
  315. return FALSE;
  316. return TRUE;
  317. }
  318. //-------------------------------------------------------------------------------------------------
  319. Bool OverlordContain::isDisplayedOnControlBar() const
  320. {
  321. // Do you mean me the Overlord, or my behavior of passing stuff on to my passengers?
  322. if( getRedirectedContain() == NULL )
  323. return FALSE;//No need to call up inheritance, this is a module based question, and I say no.
  324. return getRedirectedContain()->isDisplayedOnControlBar();
  325. }
  326. //-------------------------------------------------------------------------------------------------
  327. const Object *OverlordContain::friend_getRider() const
  328. {
  329. // The draw order dependency bug for riders means that our draw module needs to cheat to get
  330. //around it. So this is another function that knows it is getting around redirection to ask
  331. // an Overlord specific function.
  332. if( m_containListSize > 0 )
  333. return m_containList.front();
  334. return NULL;
  335. }
  336. //-------------------------------------------------------------------------------------------------
  337. void OverlordContain::activateRedirectedContain()
  338. {
  339. m_redirectionActivated = TRUE;
  340. }
  341. //-------------------------------------------------------------------------------------------------
  342. void OverlordContain::deactivateRedirectedContain()
  343. {
  344. m_redirectionActivated = FALSE;
  345. }
  346. //-------------------------------------------------------------------------------------------------
  347. //-------------------------------------------------------------------------------------------------
  348. // if my object gets selected, then my visible passengers should, too
  349. // this gets called from
  350. void OverlordContain::clientVisibleContainedFlashAsSelected()
  351. {
  352. // THIS OVERRIDES GRAHAMS NASTY OVERRIDE THING
  353. // SO WE CAN FLASH THE PORTABLE BUNKER INSTEAD OF ITS OCCUPANTS
  354. const ContainedItemsList* items = TransportContain::getContainedItemsList();
  355. if( items )
  356. {
  357. ContainedItemsList::const_iterator it;
  358. it = items->begin();
  359. while( *it )
  360. {
  361. Object *object = *it;
  362. if ( object && object->isKindOf( KINDOF_PORTABLE_STRUCTURE ) )
  363. {
  364. Drawable *draw = object->getDrawable();
  365. if ( draw )
  366. {
  367. draw->flashAsSelected(); //WOW!
  368. }
  369. }
  370. ++it;
  371. }
  372. }
  373. }
  374. // ------------------------------------------------------------------------------------------------
  375. /** CRC */
  376. // ------------------------------------------------------------------------------------------------
  377. void OverlordContain::crc( Xfer *xfer )
  378. {
  379. // extend base class
  380. TransportContain::crc( xfer );
  381. } // end crc
  382. // ------------------------------------------------------------------------------------------------
  383. /** Xfer method
  384. * Version Info:
  385. * 1: Initial version */
  386. // ------------------------------------------------------------------------------------------------
  387. void OverlordContain::xfer( Xfer *xfer )
  388. {
  389. // version
  390. XferVersion currentVersion = 1;
  391. XferVersion version = currentVersion;
  392. xfer->xferVersion( &version, currentVersion );
  393. // extend base class
  394. TransportContain::xfer( xfer );
  395. // redirection activated
  396. xfer->xferBool( &m_redirectionActivated );
  397. } // end xfer
  398. // ------------------------------------------------------------------------------------------------
  399. /** Load post process */
  400. // ------------------------------------------------------------------------------------------------
  401. void OverlordContain::loadPostProcess( void )
  402. {
  403. // extend base class
  404. TransportContain::loadPostProcess();
  405. } // end loadPostProcess