BoneFXUpdate.cpp 23 KB

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