BoneFXUpdate.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  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: BoneFXUpdate.cpp ///////////////////////////////////////////////////////////////////////
  24. // Author:
  25. // Desc:
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/GameState.h"
  30. #include "Common/Thing.h"
  31. #include "Common/ThingTemplate.h"
  32. #include "Common/INI.h"
  33. #include "Common/RandomValue.h"
  34. #include "Common/Xfer.h"
  35. #include "GameClient/FXList.h"
  36. #include "GameLogic/GameLogic.h"
  37. #include "GameLogic/Module/AIUpdate.h"
  38. #include "GameLogic/Object.h"
  39. #include "GameLogic/ObjectCreationList.h"
  40. #include "GameClient/Drawable.h"
  41. #include "GameLogic/Module/BoneFXUpdate.h"
  42. #include "GameLogic/Module/BoneFXDamage.h"
  43. const Int MAX_IDX = 32;
  44. //-------------------------------------------------------------------------------------------------
  45. //-------------------------------------------------------------------------------------------------
  46. BoneFXUpdateModuleData::BoneFXUpdateModuleData(void)
  47. {
  48. Int i, j;
  49. for (i = 0; i < BODYDAMAGETYPE_COUNT; ++i) {
  50. for (j = 0; j < BONE_FX_MAX_BONES; ++j) {
  51. m_fxList[i][j].fx = NULL;
  52. m_fxList[i][j].onlyOnce = TRUE;
  53. m_OCL[i][j].ocl = NULL;
  54. m_OCL[i][j].onlyOnce = TRUE;
  55. m_particleSystem[i][j].particleSysTemplate = NULL;
  56. m_particleSystem[i][j].onlyOnce = TRUE;
  57. }
  58. }
  59. m_damageFXTypes = DAMAGE_TYPE_FLAGS_ALL;
  60. m_damageOCLTypes = DAMAGE_TYPE_FLAGS_ALL;
  61. m_damageParticleTypes = DAMAGE_TYPE_FLAGS_ALL;
  62. }
  63. //-------------------------------------------------------------------------------------------------
  64. //-------------------------------------------------------------------------------------------------
  65. BoneFXUpdate::BoneFXUpdate( Thing *thing, const ModuleData* moduleData ) : UpdateModule( thing, moduleData )
  66. {
  67. Int i, j;
  68. for (i = 0; i < BODYDAMAGETYPE_COUNT; ++i) {
  69. for (j = 0; j < BONE_FX_MAX_BONES; ++j) {
  70. m_nextFXFrame[i][j] = -1;
  71. m_nextOCLFrame[i][j] = -1;
  72. m_nextParticleSystemFrame[i][j] = -1;
  73. m_FXBonePositions[i][j].zero();
  74. m_OCLBonePositions[i][j].zero();
  75. m_PSBonePositions[i][j].zero();
  76. }
  77. m_bonesResolved[i] = FALSE;
  78. }
  79. m_particleSystemIDs.clear();
  80. m_active = FALSE;
  81. //Added By Sadullah Nader
  82. m_curBodyState = BODY_PRISTINE;
  83. }
  84. //-------------------------------------------------------------------------------------------------
  85. void BoneFXUpdate::onObjectCreated()
  86. {
  87. static NameKeyType key_BoneFXDamage = NAMEKEY("BoneFXDamage");
  88. BoneFXDamage* bfxd = (BoneFXDamage*)getObject()->findDamageModule(key_BoneFXDamage);
  89. if (bfxd == NULL)
  90. {
  91. DEBUG_CRASH(("BoneFXUpdate requires BoneFXDamage"));
  92. throw INI_INVALID_DATA;
  93. }
  94. }
  95. //-------------------------------------------------------------------------------------------------
  96. //-------------------------------------------------------------------------------------------------
  97. BoneFXUpdate::~BoneFXUpdate( void )
  98. {
  99. killRunningParticleSystems();
  100. }
  101. //-------------------------------------------------------------------------------------------------
  102. /** Parse fx location info ... that is a named bone */
  103. //-------------------------------------------------------------------------------------------------
  104. static void parseFXLocInfo( INI *ini, void *instance, BoneLocInfo *locInfo )
  105. {
  106. const char *token = ini->getNextToken( ini->getSepsColon() );
  107. if( stricmp( token, "bone" ) == 0 )
  108. {
  109. // save bone name and location type
  110. locInfo->boneName = ini->getNextToken();
  111. } // end if
  112. else
  113. {
  114. // error
  115. throw INI_INVALID_DATA;
  116. } // end else
  117. } // end parseFXLocInfo
  118. //-------------------------------------------------------------------------------------------------
  119. /** Parse a random delay. This is a number pair, where the numbers are a min and max time in miliseconds. */
  120. //-------------------------------------------------------------------------------------------------
  121. static void parseGameClientRandomDelay( INI *ini, void *instance, GameClientRandomVariable *delay)
  122. {
  123. Real min, max;
  124. INI::parseDurationReal(ini, instance, &min, NULL);
  125. INI::parseDurationReal(ini, instance, &max, NULL);
  126. delay->setRange(min, max, GameClientRandomVariable::DistributionType::UNIFORM);
  127. }
  128. static void parseGameLogicRandomDelay( INI *ini, void *instance, GameLogicRandomVariable *delay)
  129. {
  130. Real min, max;
  131. INI::parseDurationReal(ini, instance, &min, NULL);
  132. INI::parseDurationReal(ini, instance, &max, NULL);
  133. delay->setRange(min, max, GameLogicRandomVariable::DistributionType::UNIFORM);
  134. }
  135. //-------------------------------------------------------------------------------------------------
  136. /** In the form of:
  137. * <BodyDamageState>FXList<index> = Bone:<BoneName> OnlyOnce:<Yes|No> <Min delay> <Max delay> FXList:<FXListName> */
  138. //-------------------------------------------------------------------------------------------------
  139. void BoneFXUpdateModuleData::parseFXList( INI *ini, void *instance,
  140. void *store, const void *userData )
  141. {
  142. const char *token;
  143. BoneFXListInfo *info = (BoneFXListInfo *)store;
  144. // parse the location bone or location
  145. parseFXLocInfo( ini, instance, &info->locInfo );
  146. // make sure we have an "OnlyOnce:" token
  147. token = ini->getNextToken( ini->getSepsColon() );
  148. if (stricmp( token, "onlyonce" ) != 0)
  149. {
  150. // error
  151. throw INI_INVALID_DATA;
  152. } // end if
  153. ini->parseBool( ini, instance, &info->onlyOnce, NULL);
  154. parseGameLogicRandomDelay( ini, instance, &info->gameLogicDelay);
  155. // make sure we have an "FXList:" token
  156. token = ini->getNextToken( ini->getSepsColon() );
  157. if( stricmp( token, "fxlist" ) != 0 )
  158. {
  159. // error
  160. throw INI_INVALID_DATA;
  161. } // end if
  162. // parse the fx list name
  163. ini->parseFXList( ini, instance, &info->fx, NULL );
  164. } // end parseFXList
  165. //-------------------------------------------------------------------------------------------------
  166. /** In the form of:
  167. * <BodyDamageState>OCL<index> = Bone:<BoneName> OnlyOnce:<Yes|No> <Min delay> <Max delay> OCL:<OCLName> */
  168. //-------------------------------------------------------------------------------------------------
  169. void BoneFXUpdateModuleData::parseObjectCreationList( INI *ini, void *instance,
  170. void *store, const void *userData )
  171. {
  172. const char *token;
  173. BoneOCLInfo *info = (BoneOCLInfo *)store;
  174. // parse the location bone or location
  175. parseFXLocInfo( ini, instance, &info->locInfo );
  176. // make sure we have an "OnlyOnce:" token
  177. token = ini->getNextToken( ini->getSepsColon() );
  178. if (stricmp( token, "onlyonce" ) != 0)
  179. {
  180. // error
  181. throw INI_INVALID_DATA;
  182. } // end if
  183. ini->parseBool( ini, instance, &info->onlyOnce, NULL );
  184. parseGameLogicRandomDelay(ini, instance, &info->gameLogicDelay);
  185. // make sure we have an "OCL:" token
  186. token = ini->getNextToken( ini->getSepsColon() );
  187. if( stricmp( token, "ocl" ) != 0 )
  188. {
  189. // error
  190. throw INI_INVALID_DATA;
  191. } // end if
  192. // parse the ocl name
  193. ini->parseObjectCreationList( ini, instance, &info->ocl, NULL );
  194. } // end parseObjectCreationList
  195. //-------------------------------------------------------------------------------------------------
  196. /** In the form of:
  197. * <BodyDamageState>ParticleSystem<index> = <Bone:BoneName> OnlyOnce:<Yes|No> <Min delay> <Max delay> PSys:<PSysName> */
  198. //-------------------------------------------------------------------------------------------------
  199. void BoneFXUpdateModuleData::parseParticleSystem( INI *ini, void *instance,
  200. void *store, const void *userData )
  201. {
  202. const char *token;
  203. BoneParticleSystemInfo *info = (BoneParticleSystemInfo *)store;
  204. // parse the location bone or location
  205. parseFXLocInfo( ini, instance, &info->locInfo );
  206. // make sure we have an "OnlyOnce:" token
  207. token = ini->getNextToken( ini->getSepsColon() );
  208. if (stricmp( token, "onlyonce" ) != 0)
  209. {
  210. // error
  211. throw INI_INVALID_DATA;
  212. } // end if
  213. ini->parseBool( ini, instance, &info->onlyOnce, NULL );
  214. parseGameClientRandomDelay(ini, instance, &info->gameClientDelay);
  215. // make sure we have an "PSys:" token
  216. token = ini->getNextToken( ini->getSepsColon() );
  217. if( stricmp( token, "psys" ) != 0 )
  218. {
  219. // error
  220. throw INI_INVALID_DATA;
  221. } // end if
  222. // parse the particle system name
  223. ini->parseParticleSystemTemplate( ini, instance, &info->particleSysTemplate, NULL );
  224. } // end parseParticleSystem
  225. //-------------------------------------------------------------------------------------------------
  226. //-------------------------------------------------------------------------------------------------
  227. UpdateSleepTime BoneFXUpdate::update( void )
  228. {
  229. /// @todo srj use SLEEPY_UPDATE here
  230. const BoneFXUpdateModuleData *d = getBoneFXUpdateModuleData();
  231. Int now = TheGameLogic->getFrame();
  232. if (m_active == FALSE) {
  233. initTimes();
  234. m_active = TRUE;
  235. }
  236. for (Int i = 0; i < BONE_FX_MAX_BONES; ++i) {
  237. //Check to see if its time to fire off any cool stuff.
  238. if ((m_nextFXFrame[m_curBodyState][i] != -1) && (m_nextFXFrame[m_curBodyState][i] <= now)) {
  239. doFXListAtBone(d->m_fxList[m_curBodyState][i].fx, &(m_FXBonePositions[m_curBodyState][i]));
  240. computeNextLogicFXTime(&(d->m_fxList[m_curBodyState][i]), m_nextFXFrame[m_curBodyState][i]);
  241. }
  242. if ((m_nextOCLFrame[m_curBodyState][i] != -1) && (m_nextOCLFrame[m_curBodyState][i] <= now)) {
  243. doOCLAtBone(d->m_OCL[m_curBodyState][i].ocl, &(m_OCLBonePositions[m_curBodyState][i]));
  244. computeNextLogicFXTime(&(d->m_OCL[m_curBodyState][i]), m_nextOCLFrame[m_curBodyState][i]);
  245. }
  246. if ((m_nextParticleSystemFrame[m_curBodyState][i] != -1) && (m_nextParticleSystemFrame[m_curBodyState][i] <= now)) {
  247. doParticleSystemAtBone(d->m_particleSystem[m_curBodyState][i].particleSysTemplate, &(m_PSBonePositions[m_curBodyState][i]));
  248. computeNextClientFXTime(&(d->m_particleSystem[m_curBodyState][i]), m_nextParticleSystemFrame[m_curBodyState][i]);
  249. }
  250. }
  251. return UPDATE_SLEEP_NONE;
  252. }
  253. //-------------------------------------------------------------------------------------------------
  254. //-------------------------------------------------------------------------------------------------
  255. void BoneFXUpdate::initTimes() {
  256. Int i;
  257. const BoneFXUpdateModuleData *d = getBoneFXUpdateModuleData();
  258. Int now = TheGameLogic->getFrame();
  259. for (i = 0; i < BONE_FX_MAX_BONES; ++i) {
  260. if (d->m_fxList[m_curBodyState][i].locInfo.boneName.compare(AsciiString::TheEmptyString) != 0) {
  261. m_nextFXFrame[m_curBodyState][i] = now + REAL_TO_INT(d->m_fxList[m_curBodyState][i].gameLogicDelay.getValue());
  262. } else {
  263. m_nextFXFrame[m_curBodyState][i] = -1;
  264. }
  265. if (d->m_OCL[m_curBodyState][i].locInfo.boneName.compare(AsciiString::TheEmptyString) != 0) {
  266. m_nextOCLFrame[m_curBodyState][i] = now + REAL_TO_INT(d->m_OCL[m_curBodyState][i].gameLogicDelay.getValue());
  267. } else {
  268. m_nextOCLFrame[m_curBodyState][i] = -1;
  269. }
  270. if (d->m_particleSystem[m_curBodyState][i].locInfo.boneName.compare(AsciiString::TheEmptyString) != 0) {
  271. m_nextParticleSystemFrame[m_curBodyState][i] = now + REAL_TO_INT(d->m_particleSystem[m_curBodyState][i].gameClientDelay.getValue());
  272. } else {
  273. m_nextParticleSystemFrame[m_curBodyState][i] = -1;
  274. }
  275. }
  276. }
  277. //-------------------------------------------------------------------------------------------------
  278. //-------------------------------------------------------------------------------------------------
  279. inline Bool inList(Int value, Int count, const Int idxList[])
  280. {
  281. for (Int j = 0; j < count; ++j)
  282. {
  283. if (idxList[j] == value)
  284. return true;
  285. }
  286. return false;
  287. }
  288. //-------------------------------------------------------------------------------------------------
  289. //-------------------------------------------------------------------------------------------------
  290. static void buildNonDupRandomIndexList(Int range, Int count, Int idxList[])
  291. {
  292. for (Int i = 0; i < count; ++i)
  293. {
  294. Int idx;
  295. do
  296. {
  297. idx = GameLogicRandomValue(0, range-1);
  298. }
  299. while (inList(idx, i, idxList));
  300. idxList[i] = idx;
  301. }
  302. }
  303. //-------------------------------------------------------------------------------------------------
  304. //-------------------------------------------------------------------------------------------------
  305. void BoneFXUpdate::changeBodyDamageState(BodyDamageType oldState, BodyDamageType newState)
  306. {
  307. m_curBodyState = newState;
  308. killRunningParticleSystems();
  309. initTimes();
  310. }
  311. //-------------------------------------------------------------------------------------------------
  312. //-------------------------------------------------------------------------------------------------
  313. void BoneFXUpdate::doFXListAtBone(const FXList *fxList, const Coord3D *bonePosition)
  314. {
  315. if (m_bonesResolved[m_curBodyState] == FALSE) {
  316. resolveBoneLocations();
  317. }
  318. // if we are restricted by the damage type executing effect, bail out of here
  319. const BoneFXUpdateModuleData *d = getBoneFXUpdateModuleData();
  320. const DamageInfo *lastDamageInfo = getObject()->getBodyModule()->getLastDamageInfo();
  321. if( lastDamageInfo && getDamageTypeFlag( d->m_damageFXTypes, lastDamageInfo->in.m_damageType ) == FALSE )
  322. return;
  323. // the bonePosition variable will have been made right by the call to
  324. // resolveBoneLocations. Either that or it was correct to begin with.
  325. Object *building = getObject();
  326. // Convert the bone's position relative to the origin of the building to the current
  327. // bone position in the world.
  328. Coord3D newPos;
  329. building->convertBonePosToWorldPos(bonePosition, NULL, &newPos, NULL);
  330. // execute the fx list at the calculated bone position.
  331. FXList::doFXPos(fxList, &newPos, NULL);
  332. }
  333. //-------------------------------------------------------------------------------------------------
  334. //-------------------------------------------------------------------------------------------------
  335. void BoneFXUpdate::doOCLAtBone(const ObjectCreationList *ocl, const Coord3D *bonePosition)
  336. {
  337. if (m_bonesResolved[m_curBodyState] == FALSE) {
  338. resolveBoneLocations();
  339. }
  340. // if we are restricted by the damage type executing effect, bail out of here
  341. const BoneFXUpdateModuleData *d = getBoneFXUpdateModuleData();
  342. const DamageInfo *lastDamageInfo = getObject()->getBodyModule()->getLastDamageInfo();
  343. if( lastDamageInfo && getDamageTypeFlag( d->m_damageOCLTypes, lastDamageInfo->in.m_damageType ) == FALSE )
  344. return;
  345. // the bonePosition variable will have been made right by the call to
  346. // resolveBoneLocations. Either that or it was correct to begin with.
  347. Object *building = getObject();
  348. Coord3D newPos;
  349. building->convertBonePosToWorldPos(bonePosition, NULL, &newPos, NULL);
  350. ObjectCreationList::create( ocl, building, &newPos, NULL );
  351. }
  352. //-------------------------------------------------------------------------------------------------
  353. //-------------------------------------------------------------------------------------------------
  354. void BoneFXUpdate::doParticleSystemAtBone(const ParticleSystemTemplate *particleSystemTemplate, const Coord3D *bonePosition)
  355. {
  356. if (m_bonesResolved[m_curBodyState] == FALSE) {
  357. resolveBoneLocations();
  358. }
  359. // if we are restricted by the damage type executing effect, bail out of here
  360. const BoneFXUpdateModuleData *d = getBoneFXUpdateModuleData();
  361. const DamageInfo *lastDamageInfo = getObject()->getBodyModule()->getLastDamageInfo();
  362. if( lastDamageInfo && getDamageTypeFlag( d->m_damageParticleTypes, lastDamageInfo->in.m_damageType ) == FALSE )
  363. return;
  364. Object *building = getObject();
  365. ParticleSystem *psys = TheParticleSystemManager->createParticleSystem(particleSystemTemplate);
  366. if (psys != NULL)
  367. {
  368. m_particleSystemIDs.push_back(psys->getSystemID());
  369. psys->setPosition(bonePosition);
  370. psys->attachToObject(building);
  371. Drawable *drawable = building->getDrawable();
  372. if (drawable && drawable->isDrawableEffectivelyHidden())
  373. {
  374. psys->stop();
  375. }
  376. }
  377. }
  378. //-------------------------------------------------------------------------------------------------
  379. //-------------------------------------------------------------------------------------------------
  380. void BoneFXUpdate::computeNextClientFXTime(const BaseBoneListInfo *info, Int &nextFrame)
  381. {
  382. if (info->onlyOnce) {
  383. nextFrame = -1;
  384. return;
  385. }
  386. nextFrame = TheGameLogic->getFrame() + REAL_TO_INT(info->gameClientDelay.getValue());
  387. }
  388. //-------------------------------------------------------------------------------------------------
  389. //-------------------------------------------------------------------------------------------------
  390. void BoneFXUpdate::computeNextLogicFXTime(const BaseBoneListInfo *info, Int &nextFrame)
  391. {
  392. if (info->onlyOnce) {
  393. nextFrame = -1;
  394. return;
  395. }
  396. nextFrame = TheGameLogic->getFrame() + REAL_TO_INT(info->gameLogicDelay.getValue());
  397. }
  398. //-------------------------------------------------------------------------------------------------
  399. //-------------------------------------------------------------------------------------------------
  400. void BoneFXUpdate::killRunningParticleSystems() {
  401. for (std::vector<ParticleSystemID>::iterator it = m_particleSystemIDs.begin(); it != m_particleSystemIDs.end(); ++it)
  402. {
  403. ParticleSystem *sys = TheParticleSystemManager->findParticleSystem(*it);
  404. if( sys )
  405. sys->destroy();
  406. }
  407. m_particleSystemIDs.clear();
  408. }
  409. //-------------------------------------------------------------------------------------------------
  410. //-------------------------------------------------------------------------------------------------
  411. // This function is going to suck lots of time, should only be called once.
  412. void BoneFXUpdate::resolveBoneLocations() {
  413. Int i;
  414. const BoneFXUpdateModuleData *d = getBoneFXUpdateModuleData();
  415. Object *building = getObject();
  416. if (building == NULL) {
  417. DEBUG_ASSERTCRASH(building != NULL, ("There is no object?"));
  418. return;
  419. }
  420. Drawable *drawable = building->getDrawable();
  421. if (drawable == NULL) {
  422. DEBUG_ASSERTCRASH(drawable != NULL, ("There is no drawable?"));
  423. }
  424. if (d == NULL) {
  425. return;
  426. }
  427. for (i = 0; i < BONE_FX_MAX_BONES; ++i) {
  428. if (d->m_fxList[m_curBodyState][i].locInfo.boneName.compare(AsciiString::TheEmptyString) != 0)
  429. {
  430. const BoneFXListInfo *info = &(d->m_fxList[m_curBodyState][i]);
  431. drawable->getPristineBonePositions(info->locInfo.boneName.str(), 0, &m_FXBonePositions[m_curBodyState][i], NULL, 1);
  432. }
  433. if (d->m_OCL[m_curBodyState][i].locInfo.boneName.compare(AsciiString::TheEmptyString) != 0)
  434. {
  435. const BoneOCLInfo *info = &(d->m_OCL[m_curBodyState][i]);
  436. drawable->getPristineBonePositions(info->locInfo.boneName.str(), 0, &m_OCLBonePositions[m_curBodyState][i], NULL, 1);
  437. }
  438. if (d->m_particleSystem[m_curBodyState][i].locInfo.boneName.compare(AsciiString::TheEmptyString) != 0)
  439. {
  440. const BoneParticleSystemInfo *info = &(d->m_particleSystem[m_curBodyState][i]);
  441. drawable->getPristineBonePositions(info->locInfo.boneName.str(), 0, &m_PSBonePositions[m_curBodyState][i], NULL, 1);
  442. }
  443. }
  444. m_bonesResolved[m_curBodyState] = TRUE;
  445. }
  446. //-------------------------------------------------------------------------------------------------
  447. //-------------------------------------------------------------------------------------------------
  448. void BoneFXUpdate::stopAllBoneFX() {
  449. int i, j;
  450. for (i = 0; i < BODYDAMAGETYPE_COUNT; ++i) {
  451. for (j = 0; j < BONE_FX_MAX_BONES; ++j) {
  452. m_nextFXFrame[i][j] = -1;
  453. m_nextOCLFrame[i][j] = -1;
  454. m_nextParticleSystemFrame[i][j] = -1;
  455. }
  456. }
  457. killRunningParticleSystems();
  458. }
  459. // ------------------------------------------------------------------------------------------------
  460. /** CRC */
  461. // ------------------------------------------------------------------------------------------------
  462. void BoneFXUpdate::crc( Xfer *xfer )
  463. {
  464. // extend base class
  465. UpdateModule::crc( xfer );
  466. } // end crc
  467. // ------------------------------------------------------------------------------------------------
  468. /** Xfer method
  469. * Version Info:
  470. * 1: Initial version */
  471. // ------------------------------------------------------------------------------------------------
  472. void BoneFXUpdate::xfer( Xfer *xfer )
  473. {
  474. // version
  475. XferVersion currentVersion = 1;
  476. XferVersion version = currentVersion;
  477. xfer->xferVersion( &version, currentVersion );
  478. // extend base class
  479. UpdateModule::xfer( xfer );
  480. // particle system vector count and data
  481. UnsignedShort particleSystemCount = m_particleSystemIDs.size();
  482. xfer->xferUnsignedShort( &particleSystemCount );
  483. ParticleSystemID systemID;
  484. if( xfer->getXferMode() == XFER_SAVE )
  485. {
  486. std::vector<ParticleSystemID>::const_iterator it;
  487. for( it = m_particleSystemIDs.begin(); it != m_particleSystemIDs.end(); ++it )
  488. {
  489. systemID = *it;
  490. xfer->xferUser( &systemID, sizeof( ParticleSystemID ) );
  491. } // end for
  492. } // end if, save
  493. else
  494. {
  495. // the list should be emtpy right now
  496. if( m_particleSystemIDs.empty() == FALSE )
  497. {
  498. DEBUG_CRASH(( "BoneFXUpdate::xfer - m_particleSystemIDs should be empty but is not\n" ));
  499. throw SC_INVALID_DATA;
  500. } // end if
  501. // read all data
  502. for( UnsignedShort i = 0; i < particleSystemCount; ++i )
  503. {
  504. // read id
  505. xfer->xferUser( &systemID, sizeof( ParticleSystemID ) );
  506. // put at end of vector
  507. m_particleSystemIDs.push_back( systemID );
  508. } // end for, i
  509. } // end else
  510. // next fx frame
  511. xfer->xferUser( m_nextFXFrame, sizeof( Int ) * BODYDAMAGETYPE_COUNT * BONE_FX_MAX_BONES );
  512. // next OCL farme
  513. xfer->xferUser( m_nextOCLFrame, sizeof( Int ) * BODYDAMAGETYPE_COUNT * BONE_FX_MAX_BONES );
  514. // next particle system frame
  515. xfer->xferUser( m_nextParticleSystemFrame, sizeof( Int ) * BODYDAMAGETYPE_COUNT * BONE_FX_MAX_BONES );
  516. // fx bone positions
  517. xfer->xferUser( m_FXBonePositions, sizeof( Coord3D ) * BODYDAMAGETYPE_COUNT * BONE_FX_MAX_BONES );
  518. // ocl bone positions
  519. xfer->xferUser( m_OCLBonePositions, sizeof( Coord3D ) * BODYDAMAGETYPE_COUNT * BONE_FX_MAX_BONES );
  520. // particle system bone positions
  521. xfer->xferUser( m_PSBonePositions, sizeof( Coord3D ) * BODYDAMAGETYPE_COUNT * BONE_FX_MAX_BONES );
  522. // current body state
  523. xfer->xferUser( &m_curBodyState, sizeof( BodyDamageType ) );
  524. // bones resolved
  525. xfer->xferUser( m_bonesResolved, sizeof( Bool ) * BODYDAMAGETYPE_COUNT );
  526. // active
  527. xfer->xferBool( &m_active );
  528. } // end xfer
  529. // ------------------------------------------------------------------------------------------------
  530. /** Load post process */
  531. // ------------------------------------------------------------------------------------------------
  532. void BoneFXUpdate::loadPostProcess( void )
  533. {
  534. // extend base class
  535. UpdateModule::loadPostProcess();
  536. } // end loadPostProcess