DockUpdate.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  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: DockUpdate.cpp /////////////////////////////////////////////////////////////////////////////
  24. // Author: Graham Smallwood Feb 2002
  25. // Desc: Behavior common to all DockUpdates is here. Everything but action()
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  28. #include "Common/Debug.h"
  29. #include "Common/Xfer.h"
  30. #include "GameClient/Drawable.h"
  31. #include "GameLogic/GameLogic.h"
  32. #include "GameLogic/Object.h"
  33. #include "GameLogic/PartitionManager.h"
  34. #include "GameLogic/Module/DockUpdate.h"
  35. // ------------------------------------------------------------------------------------------------
  36. // ------------------------------------------------------------------------------------------------
  37. // ------------------------------------------------------------------------------------------------
  38. // ------------------------------------------------------------------------------------------------
  39. DockUpdateModuleData::DockUpdateModuleData( void )
  40. {
  41. m_numberApproachPositionsData = 0;
  42. m_isAllowPassthrough = TRUE;
  43. }
  44. /*static*/ void DockUpdateModuleData::buildFieldParse(MultiIniFieldParse& p)
  45. {
  46. UpdateModuleData::buildFieldParse( p );
  47. static const FieldParse dataFieldParse[] =
  48. {
  49. { "NumberApproachPositions" ,INI::parseInt, NULL, offsetof( DockUpdateModuleData, m_numberApproachPositionsData ) },
  50. { "AllowsPassthrough" ,INI::parseBool, NULL, offsetof( DockUpdateModuleData, m_isAllowPassthrough ) },
  51. { 0, 0, 0, 0 }
  52. };
  53. p.add(dataFieldParse);
  54. } // end buildFieldParse
  55. DockUpdate::DockUpdate( Thing *thing, const ModuleData* moduleData ) : UpdateModule( thing, moduleData )
  56. {
  57. m_dockOpen = TRUE;
  58. m_positionsLoaded = FALSE;
  59. m_numberApproachPositionBones = -1;
  60. m_activeDocker = INVALID_ID;
  61. m_dockerInside = FALSE;
  62. m_dockCrippled = FALSE;
  63. const DockUpdateModuleData *md = (const DockUpdateModuleData *)moduleData;
  64. m_exitPosition.zero();
  65. m_dockPosition.zero();
  66. m_enterPosition.zero();
  67. m_numberApproachPositions = md->m_numberApproachPositionsData;
  68. if( m_numberApproachPositions != DYNAMIC_APPROACH_VECTOR_FLAG )
  69. {
  70. // Not dynamic, so make this the size
  71. m_approachPositions.resize(m_numberApproachPositions);
  72. m_approachPositionOwners.resize(m_numberApproachPositions);
  73. m_approachPositionReached.resize(m_numberApproachPositions);
  74. }
  75. else
  76. {
  77. //Otherwise, make a default size, and plan on growing it later
  78. m_approachPositions.resize(DEFAULT_APPROACH_VECTOR_SIZE);
  79. m_approachPositionOwners.resize(DEFAULT_APPROACH_VECTOR_SIZE);
  80. m_approachPositionReached.resize(DEFAULT_APPROACH_VECTOR_SIZE);
  81. }
  82. for( Int vectorIndex = 0; vectorIndex < m_approachPositions.size(); ++vectorIndex )
  83. {
  84. // Whatever size we are, init everything.
  85. m_approachPositions[vectorIndex].zero();
  86. m_approachPositionOwners[vectorIndex] = INVALID_ID;
  87. m_approachPositionReached[vectorIndex] = FALSE;
  88. }
  89. }
  90. DockUpdate::~DockUpdate()
  91. {
  92. }
  93. Bool DockUpdate::isClearToApproach( Object const* docker ) const
  94. {
  95. // If we allow infinite approaches, we don't even need to look up. Just say yes.
  96. // The reserve code will handle appending a free spot to the end.
  97. if( m_numberApproachPositions == DYNAMIC_APPROACH_VECTOR_FLAG )
  98. return TRUE;
  99. ObjectID dockerID = docker->getID();
  100. for( Int positionIndex = 0; positionIndex < m_approachPositionOwners.size(); ++positionIndex )
  101. {
  102. if( m_approachPositionOwners[positionIndex] == INVALID_ID )
  103. {
  104. return TRUE;
  105. }
  106. if( m_approachPositionOwners[positionIndex] == dockerID )
  107. {
  108. return TRUE;
  109. }
  110. }
  111. return FALSE;
  112. }
  113. Bool DockUpdate::reserveApproachPosition( Object* docker, Coord3D *position, Int *index )
  114. {
  115. // load dock positions if not loaded yet
  116. if( m_positionsLoaded == FALSE )
  117. loadDockPositions();
  118. // sanity
  119. if( position == NULL )
  120. return FALSE;
  121. ObjectID dockerID = docker->getID();
  122. for( Int positionIndex = 0; positionIndex < m_approachPositionOwners.size(); ++positionIndex )
  123. {
  124. if( m_approachPositionOwners[positionIndex] == dockerID )
  125. {
  126. *position = computeApproachPosition( positionIndex, docker );
  127. *index = positionIndex;
  128. return TRUE;
  129. }
  130. if( m_approachPositionOwners[positionIndex] == INVALID_ID )
  131. {
  132. m_approachPositionOwners[positionIndex] = dockerID;
  133. *position = computeApproachPosition( positionIndex, docker );
  134. *index = positionIndex;
  135. return TRUE;
  136. }
  137. }
  138. // If I make it out of the loop, I am full, so dynamic approach buildings should make a new entry instead of saying no
  139. if( m_numberApproachPositions == DYNAMIC_APPROACH_VECTOR_FLAG )
  140. {
  141. Coord3D zero;
  142. zero.zero();
  143. m_approachPositions.push_back( zero );
  144. m_approachPositionOwners.push_back( INVALID_ID );
  145. m_approachPositionReached.push_back( FALSE );
  146. loadDockPositions();// refresh this new one
  147. positionIndex = m_approachPositionOwners.size() - 1;// The new last spot
  148. m_approachPositionOwners[positionIndex] = dockerID;
  149. *position = computeApproachPosition( positionIndex, docker );
  150. *index = positionIndex;
  151. return TRUE;
  152. }
  153. return FALSE;
  154. }
  155. Bool DockUpdate::advanceApproachPosition( Object* docker, Coord3D *position, Int *index )
  156. {
  157. // load dock positions if not loaded yet
  158. if( m_positionsLoaded == FALSE )
  159. loadDockPositions();
  160. // sanity
  161. if( position == NULL )
  162. return FALSE;
  163. if( *index <= 0 )
  164. return FALSE;
  165. if( m_approachPositionOwners[(*index) - 1] != INVALID_ID )
  166. return FALSE;
  167. Int hisIndex = *index;
  168. Int previousIndex = hisIndex - 1;
  169. m_approachPositionOwners[previousIndex] = docker->getID();
  170. m_approachPositionReached[previousIndex] = FALSE;
  171. m_approachPositionOwners[hisIndex] = INVALID_ID;
  172. m_approachPositionReached[hisIndex] = FALSE;
  173. *position = computeApproachPosition( previousIndex, docker );
  174. *index = previousIndex;
  175. return TRUE;
  176. }
  177. Bool DockUpdate::isClearToEnter( Object const* docker ) const
  178. {
  179. ObjectID dockerID = docker->getID();
  180. return dockerID == m_activeDocker;
  181. }
  182. Bool DockUpdate::isClearToAdvance( Object const* docker, Int dockerIndex ) const
  183. {
  184. if( dockerIndex < 0 )
  185. return FALSE;
  186. ObjectID dockerID = docker->getID();
  187. Bool correctRequest = dockerID == m_approachPositionOwners[dockerIndex];
  188. Bool approachReached = m_approachPositionReached[dockerIndex];
  189. Bool nextSpotFree = (dockerIndex > 0) && (m_approachPositionOwners[dockerIndex - 1] == INVALID_ID);
  190. return correctRequest && approachReached && nextSpotFree;
  191. }
  192. void DockUpdate::getEnterPosition( Object* docker, Coord3D *position )
  193. {
  194. // load dock positions if not loaded yet
  195. if( m_positionsLoaded == FALSE )
  196. loadDockPositions();
  197. // sanity
  198. if( position == NULL )
  199. return;
  200. // If I don't have a bone, you are fine where you are, unless you fly, in which case I should recenter you
  201. Coord3D zero;
  202. zero.zero();
  203. if( m_enterPosition == zero )
  204. {
  205. if( docker->isUsingAirborneLocomotor() )
  206. {
  207. *position = *getObject()->getPosition();
  208. return;
  209. }
  210. *position = *docker->getPosition();
  211. return;
  212. }
  213. // take local space position and convert to world space
  214. getObject()->convertBonePosToWorldPos( &m_enterPosition, NULL, position, NULL );
  215. }
  216. void DockUpdate::getDockPosition( Object* docker, Coord3D *position )
  217. {
  218. // load dock positions if not loaded yet
  219. if( m_positionsLoaded == FALSE )
  220. loadDockPositions();
  221. // sanity
  222. if( position == NULL )
  223. return;
  224. // If I don't have a bone, you are fine where you are.
  225. Coord3D zero;
  226. zero.zero();
  227. if( m_enterPosition == zero )
  228. {
  229. *position = *docker->getPosition();
  230. return;
  231. }
  232. // take local space position and convert to world space
  233. getObject()->convertBonePosToWorldPos( &m_dockPosition, NULL, position, NULL );
  234. }
  235. void DockUpdate::getExitPosition( Object* docker, Coord3D *position )
  236. {
  237. // load dock positions if not loaded yet
  238. if( m_positionsLoaded == FALSE )
  239. loadDockPositions();
  240. // sanity
  241. if( position == NULL )
  242. return;
  243. // If I don't have a bone, you are fine where you are.
  244. Coord3D zero;
  245. zero.zero();
  246. if( m_enterPosition == zero )
  247. {
  248. *position = *docker->getPosition();
  249. return;
  250. }
  251. // take local space position and convert to world space
  252. getObject()->convertBonePosToWorldPos( &m_exitPosition, NULL, position, NULL );
  253. }
  254. void DockUpdate::onApproachReached( Object* docker )
  255. {
  256. ObjectID dockerID = docker->getID();
  257. for( Int positionIndex = 0; positionIndex < m_approachPositionOwners.size(); ++positionIndex )
  258. {
  259. if( m_approachPositionOwners[positionIndex] == dockerID )
  260. {
  261. m_approachPositionReached[positionIndex] = TRUE;
  262. return;
  263. }
  264. }
  265. }
  266. void DockUpdate::onEnterReached( Object* docker )
  267. {
  268. Object *me = getObject();
  269. me->clearAndSetModelConditionFlags( MAKE_MODELCONDITION_MASK(MODELCONDITION_DOCKING_ENDING),
  270. MAKE_MODELCONDITION_MASK2(MODELCONDITION_DOCKING_BEGINNING, MODELCONDITION_DOCKING) );
  271. docker->clearAndSetModelConditionFlags( MAKE_MODELCONDITION_MASK(MODELCONDITION_DOCKING_ENDING),
  272. MAKE_MODELCONDITION_MASK2(MODELCONDITION_DOCKING_BEGINNING, MODELCONDITION_DOCKING) );
  273. m_dockerInside = TRUE;
  274. ObjectID dockerID = docker->getID();
  275. for( Int positionIndex = 0; positionIndex < m_approachPositionOwners.size(); ++positionIndex )
  276. {
  277. if( m_approachPositionOwners[positionIndex] == dockerID )
  278. {
  279. m_approachPositionOwners[positionIndex] = INVALID_ID;
  280. m_approachPositionReached[positionIndex] = FALSE;
  281. return;
  282. }
  283. }
  284. }
  285. void DockUpdate::onDockReached( Object* docker )
  286. {
  287. Object *me = getObject();
  288. me->clearAndSetModelConditionState( MODELCONDITION_DOCKING_BEGINNING, MODELCONDITION_DOCKING_ACTIVE );
  289. docker->clearAndSetModelConditionState( MODELCONDITION_DOCKING_BEGINNING, MODELCONDITION_DOCKING_ACTIVE );
  290. }
  291. void DockUpdate::onExitReached( Object* docker )
  292. {
  293. Object *me = getObject();
  294. me->clearAndSetModelConditionFlags( MAKE_MODELCONDITION_MASK2(MODELCONDITION_DOCKING_ACTIVE, MODELCONDITION_DOCKING),
  295. MAKE_MODELCONDITION_MASK(MODELCONDITION_DOCKING_ENDING) );
  296. docker->clearAndSetModelConditionFlags( MAKE_MODELCONDITION_MASK2(MODELCONDITION_DOCKING_ACTIVE, MODELCONDITION_DOCKING),
  297. MAKE_MODELCONDITION_MASK(MODELCONDITION_DOCKING_ENDING) );
  298. m_dockerInside = FALSE;
  299. ObjectID dockerID = docker->getID();
  300. if( dockerID == m_activeDocker )
  301. m_activeDocker = INVALID_ID;
  302. else
  303. {
  304. //
  305. // we only assert here if the dock is open, for closed docks it's OK to allow somebody
  306. // to continue moving to the exit position cause they are leaving after all
  307. //
  308. if( isDockOpen() )
  309. DEBUG_ASSERTCRASH( FALSE, ("Fiddle. Someone said goodbye to a dock when the dock didn't think it was talking to that someone."));
  310. }
  311. }
  312. void DockUpdate::cancelDock( Object* docker )
  313. {
  314. ObjectID dockerID = docker->getID();
  315. for( Int positionIndex = 0; positionIndex < m_approachPositionOwners.size(); ++positionIndex )
  316. {
  317. if( m_approachPositionOwners[positionIndex] == dockerID )
  318. {
  319. m_approachPositionOwners[positionIndex] = INVALID_ID;
  320. m_approachPositionReached[positionIndex] = FALSE;
  321. }
  322. }
  323. if( m_activeDocker == dockerID )
  324. {
  325. Object *dockingObject = TheGameLogic->findObjectByID(m_activeDocker);
  326. m_activeDocker = INVALID_ID;
  327. m_dockerInside = FALSE;
  328. // clear any model conditions related to docking that may be set on us and them.
  329. // (Normal clear is part of each stage, but we won't get there.)
  330. ModelConditionFlags clear;
  331. clear.set( MODELCONDITION_DOCKING_ENDING );
  332. clear.set( MODELCONDITION_DOCKING_BEGINNING );
  333. clear.set( MODELCONDITION_DOCKING_ACTIVE );
  334. clear.set( MODELCONDITION_DOCKING );
  335. getObject()->clearModelConditionFlags( clear );
  336. if( dockingObject )
  337. dockingObject->clearModelConditionFlags( clear );
  338. }
  339. }
  340. void DockUpdate::setDockCrippled( Bool setting )
  341. {
  342. // At this level, Crippling means I will accept Approach requests, but I will never grant Enter clearence.
  343. m_dockCrippled = setting;
  344. }
  345. UpdateSleepTime DockUpdate::update()
  346. {
  347. if( m_activeDocker == INVALID_ID && !m_dockCrippled )
  348. {
  349. // if setDockCrippled has been called, I will never give enterance permission.
  350. for( Int positionIndex = 0; positionIndex < m_approachPositionReached.size(); ++positionIndex )
  351. {
  352. if( m_approachPositionReached[positionIndex] )
  353. {
  354. m_activeDocker = m_approachPositionOwners[positionIndex];
  355. return UPDATE_SLEEP_NONE;
  356. }
  357. }
  358. }
  359. else if ( getObject()->isKindOf( KINDOF_SUPPLY_SOURCE ) )
  360. {
  361. Object *docker = TheGameLogic->findObjectByID( m_activeDocker );
  362. if ( docker && docker->isKindOf( KINDOF_DOZER ) && docker->isKindOf( KINDOF_HARVESTER ))// a worker
  363. {
  364. ModelConditionFlags test;
  365. test.set( MODELCONDITION_DOCKING_BEGINNING );
  366. Drawable *dockerDraw = docker->getDrawable();
  367. if ( dockerDraw && dockerDraw->getModelConditionFlags().anyIntersectionWith( test ) )
  368. dockerDraw->clearModelConditionFlags( MAKE_MODELCONDITION_MASK(MODELCONDITION_MOVING) );
  369. }
  370. }
  371. return UPDATE_SLEEP_NONE;
  372. }
  373. Coord3D DockUpdate::computeApproachPosition( Int positionIndex, Object *forWhom )
  374. {
  375. // load dock positions if not loaded yet
  376. if( m_positionsLoaded == FALSE )
  377. loadDockPositions();
  378. Coord3D bestPosition;// This answer is the best, as it includes findPositionAround
  379. Coord3D workingPosition;// But if findPositionAround fails, we need to say something.
  380. FindPositionOptions fpOptions;
  381. // Start with the pristine bone, then convert it to the world, then find a clean spot around it.
  382. Object *us = getObject();
  383. us->convertBonePosToWorldPos( &m_approachPositions[positionIndex], NULL, &workingPosition, NULL );
  384. if( m_numberApproachPositionBones == 0 )
  385. {
  386. Coord3D ourPosition = *us->getPosition();
  387. Coord3D theirPosition = *forWhom->getPosition();
  388. // A Boneless building wants to bias towards the caller for the arbitrary position
  389. Vector3 offset( theirPosition.x - ourPosition.x, theirPosition.y - ourPosition.y, theirPosition.z - ourPosition.z );
  390. offset.Normalize();
  391. offset = offset * (us->getGeometryInfo().getMajorRadius() / 2);
  392. workingPosition.x += offset.X;
  393. workingPosition.y += offset.Y;
  394. workingPosition.z += offset.Z;
  395. }
  396. fpOptions.minRadius = 0.0f;
  397. fpOptions.maxRadius = 100.0f;
  398. fpOptions.sourceToPathToDest = forWhom;// This makes it find a place forWhom can get to.
  399. if( forWhom->isUsingAirborneLocomotor() )
  400. fpOptions.ignoreObject = getObject();// Flyers can ignore us, so they can approach right over us if they want.
  401. Bool spotFound = ThePartitionManager->findPositionAround( &workingPosition, &fpOptions, &bestPosition );
  402. if( spotFound)
  403. return bestPosition;
  404. return workingPosition;
  405. }
  406. // ------------------------------------------------------------------------------------------------
  407. // ------------------------------------------------------------------------------------------------
  408. void DockUpdate::loadDockPositions()
  409. {
  410. Drawable *myDrawable = getObject()->getDrawable();
  411. if (myDrawable)
  412. {
  413. myDrawable->getPristineBonePositions( "DockStart", 0, &m_enterPosition, NULL, 1);
  414. myDrawable->getPristineBonePositions( "DockAction", 0, &m_dockPosition, NULL, 1);
  415. myDrawable->getPristineBonePositions( "DockEnd", 0, &m_exitPosition, NULL, 1);
  416. if( m_numberApproachPositions != DYNAMIC_APPROACH_VECTOR_FLAG )
  417. {
  418. // Dynamic means no bones
  419. Coord3D approachBones[DEFAULT_APPROACH_VECTOR_SIZE];
  420. m_numberApproachPositionBones = myDrawable->getPristineBonePositions( "DockWaiting", 1, approachBones, NULL, m_numberApproachPositions);
  421. if( m_numberApproachPositions == m_approachPositions.size() )//safeguard: will always be true
  422. {
  423. for( Int copyIndex = 0; copyIndex < m_numberApproachPositions; ++copyIndex )
  424. {
  425. m_approachPositions[copyIndex] = approachBones[copyIndex];
  426. }
  427. }
  428. }
  429. else
  430. m_numberApproachPositionBones = 0;
  431. m_positionsLoaded = TRUE;
  432. }
  433. }
  434. // ------------------------------------------------------------------------------------------------
  435. // ------------------------------------------------------------------------------------------------
  436. Bool DockUpdate::isAllowPassthroughType()
  437. {
  438. return getDockUpdateModuleData()->m_isAllowPassthrough;
  439. }
  440. // ------------------------------------------------------------------------------------------------
  441. /** CRC */
  442. // ------------------------------------------------------------------------------------------------
  443. void DockUpdate::crc( Xfer *xfer )
  444. {
  445. // extend base class
  446. UpdateModule::crc( xfer );
  447. } // end crc
  448. // ------------------------------------------------------------------------------------------------
  449. /** Xfer Method */
  450. // ------------------------------------------------------------------------------------------------
  451. void DockUpdate::xfer( Xfer *xfer )
  452. {
  453. // version
  454. XferVersion currentVersion = 1;
  455. XferVersion version = currentVersion;
  456. xfer->xferVersion( &version, currentVersion );
  457. // call base class
  458. UpdateModule::xfer( xfer );
  459. // enter position
  460. xfer->xferCoord3D( &m_enterPosition );
  461. // dock position
  462. xfer->xferCoord3D( &m_dockPosition );
  463. // exit position
  464. xfer->xferCoord3D( &m_exitPosition );
  465. // # approach positions
  466. xfer->xferInt( &m_numberApproachPositions );
  467. // positions loaded
  468. xfer->xferBool( &m_positionsLoaded );
  469. // approach positions
  470. Int vectorSize = m_approachPositions.size();
  471. xfer->xferInt( &vectorSize );
  472. m_approachPositions.resize(vectorSize);
  473. for( Int vectorIndex = 0; vectorIndex < vectorSize; ++vectorIndex )
  474. {
  475. // Okay, this is cool. On save, the size and a bunch of coords will be written.
  476. // on load, vectorSize will be at 0 from the .size, but will then get set
  477. // by the xfer, and properly control the number of Coords.
  478. xfer->xferCoord3D( &m_approachPositions[vectorIndex] );
  479. }
  480. // approach position owners
  481. vectorSize = m_approachPositionOwners.size();
  482. xfer->xferInt( &vectorSize );
  483. m_approachPositionOwners.resize(vectorSize);
  484. for( vectorIndex = 0; vectorIndex < vectorSize; ++vectorIndex )
  485. {
  486. xfer->xferObjectID( &m_approachPositionOwners[vectorIndex] );
  487. }
  488. // approach positions reached
  489. vectorSize = m_approachPositionReached.size();
  490. xfer->xferInt( &vectorSize );
  491. m_approachPositionReached.resize(vectorSize);
  492. for( vectorIndex = 0; vectorIndex < vectorSize; ++vectorIndex )
  493. {
  494. // Vector of Bool gets packed as bitfield internally
  495. Bool unpack = m_approachPositionReached[vectorIndex];
  496. xfer->xferBool( &unpack );
  497. }
  498. // active docker
  499. xfer->xferObjectID( &m_activeDocker );
  500. // docker inside
  501. xfer->xferBool( &m_dockerInside );
  502. // docker crippled
  503. xfer->xferBool( &m_dockCrippled );
  504. // dock open
  505. xfer->xferBool( &m_dockOpen );
  506. } // end xfer
  507. // ------------------------------------------------------------------------------------------------
  508. /** Load post process */
  509. // ------------------------------------------------------------------------------------------------
  510. void DockUpdate::loadPostProcess( void )
  511. {
  512. // call base class
  513. UpdateModule::loadPostProcess();
  514. } // end loadPostProcess