BridgeScaffoldBehavior.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  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: BridgeScaffoldBehavior.cpp ///////////////////////////////////////////////////////////////
  24. // Author: Colin Day, September 2002
  25. // Desc: Bridge scaffold
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h"
  29. #include "Common/Xfer.h"
  30. #include "GameClient/InGameUI.h"
  31. #include "GameLogic/GameLogic.h"
  32. #include "GameLogic/Object.h"
  33. #include "GameLogic/Module/BridgeScaffoldBehavior.h"
  34. // ------------------------------------------------------------------------------------------------
  35. // ------------------------------------------------------------------------------------------------
  36. BridgeScaffoldBehavior::BridgeScaffoldBehavior( Thing *thing, const ModuleData *moduleData )
  37. : UpdateModule( thing, moduleData )
  38. {
  39. m_targetMotion = STM_STILL;
  40. m_createPos.zero();
  41. m_riseToPos.zero();
  42. m_buildPos.zero();
  43. m_targetPos.zero();
  44. m_lateralSpeed = 1.0f;
  45. m_verticalSpeed = 1.0f;
  46. } // end BridgeScaffoldBehavior
  47. // ------------------------------------------------------------------------------------------------
  48. // ------------------------------------------------------------------------------------------------
  49. BridgeScaffoldBehavior::~BridgeScaffoldBehavior( void )
  50. {
  51. } // end ~BridgeScaffoldBehavior
  52. // ------------------------------------------------------------------------------------------------
  53. /** Set all of the target positions that we're care about as a moving scaffold object */
  54. // ------------------------------------------------------------------------------------------------
  55. void BridgeScaffoldBehavior::setPositions( const Coord3D *createPos,
  56. const Coord3D *riseToPos,
  57. const Coord3D *buildPos )
  58. {
  59. m_createPos = *createPos;
  60. m_riseToPos = *riseToPos;
  61. m_buildPos = *buildPos;
  62. } // end setPositions
  63. // ------------------------------------------------------------------------------------------------
  64. /** Set us moving to the right target position for the requested motion type */
  65. // ------------------------------------------------------------------------------------------------
  66. void BridgeScaffoldBehavior::setMotion( ScaffoldTargetMotion targetMotion )
  67. {
  68. // save the target motion type
  69. m_targetMotion = targetMotion;
  70. // given the target motion, pick a destination target
  71. switch( m_targetMotion )
  72. {
  73. // --------------------------------------------------------------------------------------------
  74. case STM_RISE:
  75. case STM_TEAR_DOWN_ACROSS:
  76. m_targetPos = m_riseToPos;
  77. break;
  78. // --------------------------------------------------------------------------------------------
  79. case STM_BUILD_ACROSS:
  80. m_targetPos = m_buildPos;
  81. break;
  82. // --------------------------------------------------------------------------------------------
  83. case STM_SINK:
  84. m_targetPos = m_createPos;
  85. break;
  86. } // end switch
  87. } // end setMotion
  88. // ------------------------------------------------------------------------------------------------
  89. /** Whatever our current state of motion is, reverse it */
  90. // ------------------------------------------------------------------------------------------------
  91. void BridgeScaffoldBehavior::reverseMotion( void )
  92. {
  93. switch( m_targetMotion )
  94. {
  95. case STM_STILL:
  96. setMotion( STM_TEAR_DOWN_ACROSS );
  97. break;
  98. case STM_RISE:
  99. setMotion( STM_SINK );
  100. break;
  101. case STM_BUILD_ACROSS:
  102. setMotion( STM_TEAR_DOWN_ACROSS );
  103. break;
  104. case STM_TEAR_DOWN_ACROSS:
  105. setMotion( STM_BUILD_ACROSS );
  106. break;
  107. case STM_SINK:
  108. setMotion( STM_RISE );
  109. break;
  110. } // end switch
  111. } // end reverseMotion
  112. // ------------------------------------------------------------------------------------------------
  113. /** The update method */
  114. // ------------------------------------------------------------------------------------------------
  115. UpdateSleepTime BridgeScaffoldBehavior::update( void )
  116. {
  117. // do nothing if we're not in motion
  118. if( m_targetMotion == STM_STILL )
  119. return UPDATE_SLEEP_NONE;
  120. // get our info
  121. Object *us = getObject();
  122. const Coord3D *ourPos = us->getPosition();
  123. // compute direction vector from our position to the target position
  124. Coord3D dirV;
  125. dirV.x = m_targetPos.x - ourPos->x;
  126. dirV.y = m_targetPos.y - ourPos->y;
  127. dirV.z = m_targetPos.z - ourPos->z;
  128. // use normalized direction vector "v" to do the pulling movement
  129. Coord3D v = dirV;
  130. v.normalize();
  131. // depending on our motion type, we move at different speeds
  132. Real topSpeed = 1.0f;
  133. Coord3D *start, *end;
  134. switch( m_targetMotion )
  135. {
  136. case STM_RISE:
  137. topSpeed = m_verticalSpeed;
  138. start = &m_createPos;
  139. end = &m_riseToPos;
  140. break;
  141. case STM_SINK:
  142. topSpeed = m_verticalSpeed;
  143. start = &m_riseToPos;
  144. end = &m_createPos;
  145. break;
  146. case STM_BUILD_ACROSS:
  147. topSpeed = m_lateralSpeed;
  148. start = &m_riseToPos;
  149. end = &m_buildPos;
  150. break;
  151. case STM_TEAR_DOWN_ACROSS:
  152. topSpeed = m_lateralSpeed;
  153. start = &m_buildPos;
  154. end = &m_riseToPos;
  155. break;
  156. } // end switch
  157. // adjust speed so it's slower at the end of motion
  158. Coord3D speedVector;
  159. speedVector.x = end->x - start->x;
  160. speedVector.y = end->y - start->y;
  161. speedVector.z = end->z - start->z;
  162. Real totalDistance = speedVector.length() * 0.25f;
  163. speedVector.x = end->x - ourPos->x;
  164. speedVector.y = end->y - ourPos->y;
  165. speedVector.z = end->z - ourPos->z;
  166. Real ourDistance = speedVector.length();
  167. Real speed = (ourDistance / totalDistance) * topSpeed;
  168. Real minSpeed = topSpeed * 0.08f;
  169. if( speed < minSpeed )
  170. speed = minSpeed;
  171. if( speed > topSpeed )
  172. speed = topSpeed;
  173. //
  174. // make sure that speed can't get so incredibly small that we never finish our
  175. // movement no matter what the speed and distance are
  176. //
  177. if( speed < 0.001f )
  178. speed = 0.001f;
  179. // compute the new position given the speed
  180. Coord3D newPos;
  181. newPos.x = v.x * speed + ourPos->x;
  182. newPos.y = v.y * speed + ourPos->y;
  183. newPos.z = v.z * speed + ourPos->z;
  184. //
  185. // will this new position push us beyond our target destination, we will take the vector
  186. // from the new position to the destination and the vector from our current present position
  187. // tot he destination and dot them togehter ... if the result is < 0 then we have will
  188. // overshoot the distance if we use the new position
  189. //
  190. Coord3D tooFarVector;
  191. tooFarVector.x = m_targetPos.x - newPos.x;
  192. tooFarVector.y = m_targetPos.y - newPos.y;
  193. tooFarVector.z = m_targetPos.z - newPos.z;
  194. if( tooFarVector.x * dirV.x + tooFarVector.y * dirV.y + tooFarVector.z * dirV.z <= 0.0f )
  195. {
  196. // use the destination position
  197. newPos = m_targetPos;
  198. //
  199. // we have reached our target position, switch motion to the next position in
  200. // the chain (which may be stay still and don't move anymore)
  201. //
  202. switch( m_targetMotion )
  203. {
  204. case STM_RISE: setMotion( STM_BUILD_ACROSS ); break;
  205. case STM_BUILD_ACROSS: setMotion( STM_STILL ); break;
  206. case STM_TEAR_DOWN_ACROSS: setMotion( STM_SINK ); break;
  207. case STM_SINK:
  208. {
  209. // we are done with a sinking motion, destroy the scaffold object as our job is done
  210. TheGameLogic->destroyObject( us );
  211. break;
  212. } // end case
  213. } // end switch
  214. } // end if
  215. // set the new position
  216. us->setPosition( &newPos );
  217. // do not sleep
  218. return UPDATE_SLEEP_NONE;
  219. } // end update
  220. // ------------------------------------------------------------------------------------------------
  221. /** STATIC MEMBER:
  222. * Helper function to retrieve a bridge scaffold interface from an object if one is present */
  223. // ------------------------------------------------------------------------------------------------
  224. BridgeScaffoldBehaviorInterface *BridgeScaffoldBehavior::getBridgeScaffoldBehaviorInterfaceFromObject( Object *obj )
  225. {
  226. // santiy
  227. if( obj == NULL )
  228. return NULL;
  229. // get the bridge tower behavior interface
  230. BridgeScaffoldBehaviorInterface *bridgeScaffoldInterface = NULL;
  231. BehaviorModule **bmi;
  232. for( bmi = obj->getBehaviorModules(); *bmi; ++bmi )
  233. {
  234. bridgeScaffoldInterface = (*bmi)->getBridgeScaffoldBehaviorInterface();
  235. if( bridgeScaffoldInterface )
  236. return bridgeScaffoldInterface;
  237. } // end for bmi
  238. // interface not found
  239. return NULL;
  240. } // end getBridgeScaffoldBehaviorInterfaceFromObject
  241. // ------------------------------------------------------------------------------------------------
  242. /** CRC */
  243. // ------------------------------------------------------------------------------------------------
  244. void BridgeScaffoldBehavior::crc( Xfer *xfer )
  245. {
  246. // extend base class
  247. UpdateModule::crc( xfer );
  248. } // end crc
  249. // ------------------------------------------------------------------------------------------------
  250. /** Xfer method
  251. * Version Info:
  252. * 1: Initial version */
  253. // ------------------------------------------------------------------------------------------------
  254. void BridgeScaffoldBehavior::xfer( Xfer *xfer )
  255. {
  256. // version
  257. XferVersion currentVersion = 1;
  258. XferVersion version = currentVersion;
  259. xfer->xferVersion( &version, currentVersion );
  260. // extend base class
  261. UpdateModule::xfer( xfer );
  262. // target motion
  263. xfer->xferUser( &m_targetMotion, sizeof( ScaffoldTargetMotion ) );
  264. // create pos
  265. xfer->xferCoord3D( &m_createPos );
  266. // rise to pos
  267. xfer->xferCoord3D( &m_riseToPos );
  268. // build pos
  269. xfer->xferCoord3D( &m_buildPos );
  270. // lateral speed
  271. xfer->xferReal( &m_lateralSpeed );
  272. // vertical speed
  273. xfer->xferReal( &m_verticalSpeed );
  274. // current target pos
  275. xfer->xferCoord3D( &m_targetPos );
  276. } // end xfer
  277. // ------------------------------------------------------------------------------------------------
  278. /** Load post process */
  279. // ------------------------------------------------------------------------------------------------
  280. void BridgeScaffoldBehavior::loadPostProcess( void )
  281. {
  282. // extend base class
  283. UpdateModule::loadPostProcess();
  284. } // end loadPostProcess