BridgeTowerBehavior.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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: BridgeTowerBehavior.cpp //////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, July 2002
  25. // Desc: Behavior module for the towers attached to bridges that can be targeted
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/ThingTemplate.h"
  30. #include "Common/Xfer.h"
  31. #include "GameClient/InGameUI.h"
  32. #include "GameLogic/GameLogic.h"
  33. #include "GameLogic/Object.h"
  34. #include "GameLogic/Module/BodyModule.h"
  35. #include "GameLogic/Module/BridgeBehavior.h"
  36. #include "GameLogic/Module/BridgeTowerBehavior.h"
  37. #include "GameLogic/TerrainLogic.h"
  38. // ------------------------------------------------------------------------------------------------
  39. // ------------------------------------------------------------------------------------------------
  40. BridgeTowerBehavior::BridgeTowerBehavior( Thing *thing, const ModuleData *moduleData )
  41. : BehaviorModule( thing, moduleData )
  42. {
  43. m_bridgeID = INVALID_ID;
  44. } // end BridgeTowerBehavior
  45. // ------------------------------------------------------------------------------------------------
  46. // ------------------------------------------------------------------------------------------------
  47. BridgeTowerBehavior::~BridgeTowerBehavior( void )
  48. {
  49. } // end ~BridgeTowerBehavior
  50. // ------------------------------------------------------------------------------------------------
  51. // ------------------------------------------------------------------------------------------------
  52. void BridgeTowerBehavior::setBridge( Object *bridge )
  53. {
  54. if( bridge == NULL )
  55. m_bridgeID = INVALID_ID;
  56. else
  57. m_bridgeID = bridge->getID();
  58. } // end setBridge
  59. // ------------------------------------------------------------------------------------------------
  60. // ------------------------------------------------------------------------------------------------
  61. ObjectID BridgeTowerBehavior::getBridgeID( void )
  62. {
  63. return m_bridgeID;
  64. } // end getBridge
  65. // ------------------------------------------------------------------------------------------------
  66. // ------------------------------------------------------------------------------------------------
  67. void BridgeTowerBehavior::setTowerType( BridgeTowerType type )
  68. {
  69. m_type = type;
  70. } // end setTowerType
  71. // ------------------------------------------------------------------------------------------------
  72. // ------------------------------------------------------------------------------------------------
  73. void BridgeTowerBehavior::onDamage( DamageInfo *damageInfo )
  74. {
  75. Object *bridge = TheGameLogic->findObjectByID( getBridgeID() );
  76. // sanity
  77. if( bridge == NULL )
  78. return;
  79. //
  80. // get our body info so we now how much damage percent is being done to us ... we need this
  81. // so that we can propagate the same damage percentage amont the towers and the bridge
  82. //
  83. BodyModuleInterface *body = getObject()->getBodyModule();
  84. Real damagePercentage = damageInfo->in.m_amount / body->getMaxHealth();
  85. // get the bridge behavior module for our bridge
  86. BehaviorModule **bmi;
  87. BridgeBehaviorInterface *bridgeInterface = NULL;
  88. for( bmi = bridge->getBehaviorModules(); *bmi; ++bmi )
  89. {
  90. bridgeInterface = (*bmi)->getBridgeBehaviorInterface();
  91. if( bridgeInterface )
  92. break;
  93. } // end for bmi
  94. DEBUG_ASSERTCRASH( bridgeInterface != NULL, ("BridgeTowerBehavior::onDamage - no 'BridgeBehaviorInterface' found\n") );
  95. if( bridgeInterface )
  96. {
  97. //
  98. // damage each of the other towers if the source of this damage isn't from the bridge
  99. // or other towers
  100. //
  101. Object *source = TheGameLogic->findObjectByID( damageInfo->in.m_sourceID );
  102. if( source == NULL ||
  103. (source->isKindOf( KINDOF_BRIDGE ) == FALSE &&
  104. source->isKindOf( KINDOF_BRIDGE_TOWER ) == FALSE) )
  105. {
  106. for( Int i = 0; i < BRIDGE_MAX_TOWERS; ++i )
  107. {
  108. Object *tower;
  109. tower = TheGameLogic->findObjectByID( bridgeInterface->getTowerID( (BridgeTowerType)i ) );
  110. if( tower && tower != getObject() )
  111. {
  112. BodyModuleInterface *towerBody = tower->getBodyModule();
  113. DamageInfo towerDamage;
  114. towerDamage.in.m_amount = damagePercentage * towerBody->getMaxHealth();
  115. towerDamage.in.m_sourceID = getObject()->getID(); // we're now the source
  116. towerDamage.in.m_damageType = damageInfo->in.m_damageType;
  117. towerDamage.in.m_deathType = damageInfo->in.m_deathType;
  118. tower->attemptDamage( &towerDamage );
  119. } // end if
  120. } // end for i
  121. //
  122. // damage bridge object, but make sure it's done through the bridge interface
  123. // so that it doesn't automatically propagate that damage to the towers
  124. //
  125. BodyModuleInterface *bridgeBody = bridge->getBodyModule();
  126. DamageInfo bridgeDamage;
  127. bridgeDamage.in.m_amount = damagePercentage * bridgeBody->getMaxHealth();
  128. bridgeDamage.in.m_sourceID = getObject()->getID(); // we're now the source
  129. bridgeDamage.in.m_damageType = damageInfo->in.m_damageType;
  130. bridgeDamage.in.m_deathType = damageInfo->in.m_deathType;
  131. bridge->attemptDamage( &bridgeDamage );
  132. } // end if
  133. } // end if
  134. } // end onDamage
  135. // ------------------------------------------------------------------------------------------------
  136. // ------------------------------------------------------------------------------------------------
  137. void BridgeTowerBehavior::onHealing( DamageInfo *damageInfo )
  138. {
  139. Object *bridge = TheGameLogic->findObjectByID( getBridgeID() );
  140. // sanity
  141. if( bridge == NULL )
  142. return;
  143. //
  144. // get our body info so we now how much healing percent is being done to us ... we need this
  145. // so that we can propagate the same healing percentage amont the towers and the bridge
  146. //
  147. BodyModuleInterface *body = getObject()->getBodyModule();
  148. Real healingPercentage = damageInfo->in.m_amount / body->getMaxHealth();
  149. // get the bridge behavior module for our bridge
  150. BehaviorModule **bmi;
  151. BridgeBehaviorInterface *bridgeInterface = NULL;
  152. for( bmi = bridge->getBehaviorModules(); *bmi; ++bmi )
  153. {
  154. bridgeInterface = (*bmi)->getBridgeBehaviorInterface();
  155. if( bridgeInterface )
  156. break;
  157. } // end for bmi
  158. DEBUG_ASSERTCRASH( bridgeInterface != NULL, ("BridgeTowerBehavior::onHealing - no 'BridgeBehaviorInterface' found\n") );
  159. if( bridgeInterface )
  160. {
  161. //
  162. // heal each of the other towers if the source of this healing isn't from the bridge
  163. // or other towers
  164. //
  165. Object *source = TheGameLogic->findObjectByID( damageInfo->in.m_sourceID );
  166. if( source == NULL ||
  167. (source->isKindOf( KINDOF_BRIDGE ) == FALSE &&
  168. source->isKindOf( KINDOF_BRIDGE_TOWER ) == FALSE) )
  169. {
  170. for( Int i = 0; i < BRIDGE_MAX_TOWERS; ++i )
  171. {
  172. Object *tower;
  173. tower = TheGameLogic->findObjectByID( bridgeInterface->getTowerID( (BridgeTowerType)i ) );
  174. if( tower && tower != getObject() )
  175. {
  176. BodyModuleInterface *towerBody = tower->getBodyModule();
  177. tower->attemptHealing(healingPercentage * towerBody->getMaxHealth(), getObject());
  178. } // end if
  179. } // end for i
  180. //
  181. // heal bridge object, but make sure it's done through the bridge interface
  182. // so that it doesn't automatically propagate that healing to the towers.
  183. //
  184. BodyModuleInterface *bridgeBody = bridge->getBodyModule();
  185. bridge->attemptHealing(healingPercentage * bridgeBody->getMaxHealth(), getObject());
  186. } // end if
  187. } // end if
  188. } // end onHealing
  189. // ------------------------------------------------------------------------------------------------
  190. // ------------------------------------------------------------------------------------------------
  191. void BridgeTowerBehavior::onBodyDamageStateChange( const DamageInfo* damageInfo,
  192. BodyDamageType oldState,
  193. BodyDamageType newState )
  194. {
  195. } // end onBodyDamageStateChange
  196. // ------------------------------------------------------------------------------------------------
  197. // ------------------------------------------------------------------------------------------------
  198. void BridgeTowerBehavior::onDie( const DamageInfo *damageInfo )
  199. {
  200. // kill the bridge object, this will kill all the towers
  201. Object *bridge = TheGameLogic->findObjectByID( getBridgeID() );
  202. if( bridge )
  203. bridge->kill();
  204. } // end onDie
  205. ///////////////////////////////////////////////////////////////////////////////////////////////////
  206. ///////////////////////////////////////////////////////////////////////////////////////////////////
  207. ///////////////////////////////////////////////////////////////////////////////////////////////////
  208. // ------------------------------------------------------------------------------------------------
  209. /** Given an object, return a bridge tower interface if that object has one */
  210. // ------------------------------------------------------------------------------------------------
  211. BridgeTowerBehaviorInterface *BridgeTowerBehavior::getBridgeTowerBehaviorInterfaceFromObject( Object *obj )
  212. {
  213. // sanity
  214. if( obj == NULL || obj->isKindOf( KINDOF_BRIDGE_TOWER ) == FALSE )
  215. return NULL;
  216. BehaviorModule **bmi;
  217. BridgeTowerBehaviorInterface *bridgeTowerInterface = NULL;
  218. for( bmi = obj->getBehaviorModules(); *bmi; ++bmi )
  219. {
  220. bridgeTowerInterface = (*bmi)->getBridgeTowerBehaviorInterface();
  221. if( bridgeTowerInterface )
  222. return bridgeTowerInterface;
  223. } // end for bmi
  224. // interface not found
  225. return NULL;
  226. } // getBridgeTowerBehaviorInterfaceFromObject
  227. // ------------------------------------------------------------------------------------------------
  228. /** CRC */
  229. // ------------------------------------------------------------------------------------------------
  230. void BridgeTowerBehavior::crc( Xfer *xfer )
  231. {
  232. // extend base class
  233. BehaviorModule::crc( xfer );
  234. } // end crc
  235. // ------------------------------------------------------------------------------------------------
  236. /** Xfer method
  237. * Version Info:
  238. * 1: Initial version */
  239. // ------------------------------------------------------------------------------------------------
  240. void BridgeTowerBehavior::xfer( Xfer *xfer )
  241. {
  242. // version
  243. XferVersion currentVersion = 1;
  244. XferVersion version = currentVersion;
  245. xfer->xferVersion( &version, currentVersion );
  246. // extend base class
  247. BehaviorModule::xfer( xfer );
  248. // xfer bridge object ID
  249. xfer->xferObjectID( &m_bridgeID );
  250. // xfer tower type
  251. xfer->xferUser( &m_type, sizeof( BridgeTowerType ) );
  252. } // end xfer
  253. // ------------------------------------------------------------------------------------------------
  254. /** Load post process */
  255. // ------------------------------------------------------------------------------------------------
  256. void BridgeTowerBehavior::loadPostProcess( void )
  257. {
  258. // extend base class
  259. BehaviorModule::loadPostProcess();
  260. } // end loadPostProcess