splash.cpp
Engine/source/T3D/fx/splash.cpp
Public Functions
ConsoleDocClass(Splash , "@brief Manages the ring used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> a <a href="/coding/class/classsplash/">Splash</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effect.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" )
ConsoleDocClass(SplashData , "@brief Acts as the physical point in space in white a <a href="/coding/class/classsplash/">Splash</a> is created <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" )
Detailed Description
Public Functions
ConsoleDocClass(Splash , "@brief Manages the ring used <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> a <a href="/coding/class/classsplash/">Splash</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effect.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" )
ConsoleDocClass(SplashData , "@brief Acts as the physical point in space in white a <a href="/coding/class/classsplash/">Splash</a> is created <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" )
IMPLEMENT_CO_DATABLOCK_V1(SplashData )
IMPLEMENT_CO_NETOBJECT_V1(Splash )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "T3D/fx/splash.h" 25 26#include "console/consoleTypes.h" 27#include "gfx/primBuilder.h" 28#include "gfx/gfxDrawUtil.h" 29#include "sfx/sfxSystem.h" 30#include "sfx/sfxProfile.h" 31#include "scene/sceneManager.h" 32#include "scene/sceneRenderState.h" 33#include "core/stream/bitStream.h" 34#include "math/mathIO.h" 35#include "T3D/fx/explosion.h" 36#include "T3D/fx/particle.h" 37#include "T3D/fx/particleEmitter.h" 38#include "T3D/fx/particleEmitterNode.h" 39#include "T3D/gameBase/gameProcess.h" 40#include "sim/netConnection.h" 41#include "renderInstance/renderPassManager.h" 42#include "console/engineAPI.h" 43 44namespace 45{ 46 47MRandomLCG sgRandom(0xdeadbeef); 48 49} // namespace {} 50 51//---------------------------------------------------------------------------- 52 53IMPLEMENT_CO_DATABLOCK_V1(SplashData); 54IMPLEMENT_CO_NETOBJECT_V1(Splash); 55 56ConsoleDocClass( SplashData, 57 "@brief Acts as the physical point in space in white a Splash is created from.\n" 58 "@ingroup FX\n" 59); 60 61ConsoleDocClass( Splash, 62 "@brief Manages the ring used for a Splash effect.\n" 63 "@ingroup FX\n" 64); 65 66//-------------------------------------------------------------------------- 67// Splash Data 68//-------------------------------------------------------------------------- 69SplashData::SplashData() 70{ 71 soundProfile = NULL; 72 soundProfileId = 0; 73 74 scale.set(1, 1, 1); 75 76 dMemset( emitterList, 0, sizeof( emitterList ) ); 77 dMemset( emitterIDList, 0, sizeof( emitterIDList ) ); 78 79 delayMS = 0; 80 delayVariance = 0; 81 lifetimeMS = 1000; 82 lifetimeVariance = 0; 83 width = 4.0; 84 numSegments = 10; 85 velocity = 5.0; 86 height = 0.0; 87 acceleration = 0.0; 88 texWrap = 1.0; 89 texFactor = 3.0; 90 ejectionFreq = 5; 91 ejectionAngle = 45.0; 92 ringLifetime = 1.0; 93 startRadius = 0.5; 94 explosion = NULL; 95 explosionId = 0; 96 97 dMemset( textureName, 0, sizeof( textureName ) ); 98 99 U32 i; 100 for( i=0; i<NUM_TIME_KEYS; i++ ) 101 times[i] = 1.0; 102 103 times[0] = 0.0; 104 105 for( i=0; i<NUM_TIME_KEYS; i++ ) 106 colors[i].set( 1.0, 1.0, 1.0, 1.0 ); 107 108} 109 110//-------------------------------------------------------------------------- 111// Init fields 112//-------------------------------------------------------------------------- 113 void SplashData::initPersistFields() 114{ 115 addField("soundProfile", TYPEID< SFXProfile >(), Offset(soundProfile, SplashData), "SFXProfile effect to play.\n"); 116 addField("scale", TypePoint3F, Offset(scale, SplashData), "The scale of this splashing effect, defined as the F32 points X, Y, Z.\n"); 117 addField("emitter", TYPEID< ParticleEmitterData >(), Offset(emitterList, SplashData), NUM_EMITTERS, "List of particle emitters to create at the point of this Splash effect.\n"); 118 addField("delayMS", TypeS32, Offset(delayMS, SplashData), "Time to delay, in milliseconds, before actually starting this effect.\n"); 119 addField("delayVariance", TypeS32, Offset(delayVariance, SplashData), "Time variance for delayMS.\n"); 120 addField("lifetimeMS", TypeS32, Offset(lifetimeMS, SplashData), "Lifetime for this effect, in milliseconds.\n"); 121 addField("lifetimeVariance", TypeS32, Offset(lifetimeVariance, SplashData), "Time variance for lifetimeMS.\n"); 122 addField("width", TypeF32, Offset(width, SplashData), "Width for the X and Y coordinates to create this effect within."); 123 addField("numSegments", TypeS32, Offset(numSegments, SplashData), "Number of ejection points in the splash ring.\n"); 124 addField("velocity", TypeF32, Offset(velocity, SplashData), "Velocity for the splash effect to travel.\n"); 125 addField("height", TypeF32, Offset(height, SplashData), "Height for the splash to reach.\n"); 126 addField("acceleration", TypeF32, Offset(acceleration, SplashData), "Constant acceleration value to place upon the splash effect.\n"); 127 addField("times", TypeF32, Offset(times, SplashData), NUM_TIME_KEYS, "Times to transition through the splash effect. Up to 4 allowed. Values are 0.0 - 1.0, and corrispond to the life of the particle where 0 is first created and 1 is end of lifespace.\n" ); 128 addField("colors", TypeColorF, Offset(colors, SplashData), NUM_TIME_KEYS, "Color values to set the splash effect, rgba. Up to 4 allowed. Will transition through colors based on values set in the times value. Example: colors[0] = \"0.6 1.0 1.0 0.5\".\n" ); 129 addField("texture", TypeFilename, Offset(textureName, SplashData), NUM_TEX, "Imagemap file to use as the texture for the splash effect.\n"); 130 addField("texWrap", TypeF32, Offset(texWrap, SplashData), "Amount to wrap the texture around the splash ring, 0.0f - 1.0f.\n"); 131 addField("texFactor", TypeF32, Offset(texFactor, SplashData), "Factor in which to apply the texture to the splash ring, 0.0f - 1.0f.\n"); 132 addField("ejectionFreq", TypeF32, Offset(ejectionFreq, SplashData), "Frequency in which to emit splash rings.\n"); 133 addField("ejectionAngle", TypeF32, Offset(ejectionAngle, SplashData), "Rotational angle to create a splash ring.\n"); 134 addField("ringLifetime", TypeF32, Offset(ringLifetime, SplashData), "Lifetime, in milliseconds, for a splash ring.\n"); 135 addField("startRadius", TypeF32, Offset(startRadius, SplashData), "Starting radius size of a splash ring.\n"); 136 addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, SplashData), "ExplosionData object to create at the creation position of this splash effect.\n"); 137 138 Parent::initPersistFields(); 139} 140 141//-------------------------------------------------------------------------- 142// On add - verify data settings 143//-------------------------------------------------------------------------- 144bool SplashData::onAdd() 145{ 146 if (Parent::onAdd() == false) 147 return false; 148 149 return true; 150} 151 152//-------------------------------------------------------------------------- 153// Pack data 154//-------------------------------------------------------------------------- 155void SplashData::packData(BitStream* stream) 156{ 157 Parent::packData(stream); 158 159 mathWrite(*stream, scale); 160 stream->write(delayMS); 161 stream->write(delayVariance); 162 stream->write(lifetimeMS); 163 stream->write(lifetimeVariance); 164 stream->write(width); 165 stream->write(numSegments); 166 stream->write(velocity); 167 stream->write(height); 168 stream->write(acceleration); 169 stream->write(texWrap); 170 stream->write(texFactor); 171 stream->write(ejectionFreq); 172 stream->write(ejectionAngle); 173 stream->write(ringLifetime); 174 stream->write(startRadius); 175 176 if( stream->writeFlag( explosion ) ) 177 { 178 stream->writeRangedU32(explosion->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast); 179 } 180 181 S32 i; 182 for( i=0; i<NUM_EMITTERS; i++ ) 183 { 184 if( stream->writeFlag( emitterList[i] != NULL ) ) 185 { 186 stream->writeRangedU32( emitterList[i]->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast ); 187 } 188 } 189 190 for( i=0; i<NUM_TIME_KEYS; i++ ) 191 { 192 stream->write( colors[i] ); 193 } 194 195 for( i=0; i<NUM_TIME_KEYS; i++ ) 196 { 197 stream->write( times[i] ); 198 } 199 200 for( i=0; i<NUM_TEX; i++ ) 201 { 202 stream->writeString(textureName[i]); 203 } 204} 205 206//-------------------------------------------------------------------------- 207// Unpack data 208//-------------------------------------------------------------------------- 209void SplashData::unpackData(BitStream* stream) 210{ 211 Parent::unpackData(stream); 212 213 mathRead(*stream, &scale); 214 stream->read(&delayMS); 215 stream->read(&delayVariance); 216 stream->read(&lifetimeMS); 217 stream->read(&lifetimeVariance); 218 stream->read(&width); 219 stream->read(&numSegments); 220 stream->read(&velocity); 221 stream->read(&height); 222 stream->read(&acceleration); 223 stream->read(&texWrap); 224 stream->read(&texFactor); 225 stream->read(&ejectionFreq); 226 stream->read(&ejectionAngle); 227 stream->read(&ringLifetime); 228 stream->read(&startRadius); 229 230 if( stream->readFlag() ) 231 { 232 explosionId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); 233 } 234 235 U32 i; 236 for( i=0; i<NUM_EMITTERS; i++ ) 237 { 238 if( stream->readFlag() ) 239 { 240 emitterIDList[i] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); 241 } 242 } 243 244 for( i=0; i<NUM_TIME_KEYS; i++ ) 245 { 246 stream->read( &colors[i] ); 247 } 248 249 for( i=0; i<NUM_TIME_KEYS; i++ ) 250 { 251 stream->read( ×[i] ); 252 } 253 254 for( i=0; i<NUM_TEX; i++ ) 255 { 256 textureName[i] = stream->readSTString(); 257 } 258} 259 260//-------------------------------------------------------------------------- 261// Preload data - load resources 262//-------------------------------------------------------------------------- 263bool SplashData::preload(bool server, String &errorStr) 264{ 265 if (Parent::preload(server, errorStr) == false) 266 return false; 267 268 if (!server) 269 { 270 S32 i; 271 for( i=0; i<NUM_EMITTERS; i++ ) 272 { 273 if( !emitterList[i] && emitterIDList[i] != 0 ) 274 { 275 if( Sim::findObject( emitterIDList[i], emitterList[i] ) == false) 276 { 277 Con::errorf( ConsoleLogEntry::General, "SplashData::onAdd: Invalid packet, bad datablockId(particle emitter): 0x%x", emitterIDList[i] ); 278 } 279 } 280 } 281 282 for( i=0; i<NUM_TEX; i++ ) 283 { 284 if (textureName[i] && textureName[i][0]) 285 { 286 textureHandle[i] = GFXTexHandle(textureName[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - textureHandle[%d] (line %d)", __FUNCTION__, i, __LINE__) ); 287 } 288 } 289 } 290 291 if( !explosion && explosionId != 0 ) 292 { 293 if( !Sim::findObject(explosionId, explosion) ) 294 { 295 Con::errorf(ConsoleLogEntry::General, "SplashData::preload: Invalid packet, bad datablockId(explosion): %d", explosionId); 296 } 297 } 298 299 return true; 300} 301 302 303//-------------------------------------------------------------------------- 304// Splash 305//-------------------------------------------------------------------------- 306Splash::Splash() 307 : mDataBlock( NULL ) 308{ 309 dMemset( mEmitterList, 0, sizeof( mEmitterList ) ); 310 311 mDelayMS = 0; 312 mCurrMS = 0; 313 mEndingMS = 1000; 314 mActive = false; 315 mRadius = 0.0; 316 mVelocity = 1.0; 317 mHeight = 0.0; 318 mTimeSinceLastRing = 0.0; 319 mDead = false; 320 mElapsedTime = 0.0; 321 322 mInitialNormal.set( 0.0, 0.0, 1.0 ); 323 324 // Only allocated client side. 325 mNetFlags.set( IsGhost ); 326} 327 328//-------------------------------------------------------------------------- 329// Destructor 330//-------------------------------------------------------------------------- 331Splash::~Splash() 332{ 333} 334 335//-------------------------------------------------------------------------- 336// Set initial state 337//-------------------------------------------------------------------------- 338void Splash::setInitialState(const Point3F& point, const Point3F& normal, const F32 fade) 339{ 340 mInitialPosition = point; 341 mInitialNormal = normal; 342 mFade = fade; 343 mFog = 0.0f; 344} 345 346 347//-------------------------------------------------------------------------- 348// OnAdd 349//-------------------------------------------------------------------------- 350bool Splash::onAdd() 351{ 352 // first check if we have a server connection, if we dont then this is on the server 353 // and we should exit, then check if the parent fails to add the object 354 NetConnection* conn = NetConnection::getConnectionToServer(); 355 if(!conn || !Parent::onAdd()) 356 return false; 357 358 if( !mDataBlock ) 359 { 360 Con::errorf("Splash::onAdd - Fail - No datablock"); 361 return false; 362 } 363 364 mDelayMS = mDataBlock->delayMS + sgRandom.randI( -mDataBlock->delayVariance, mDataBlock->delayVariance ); 365 mEndingMS = mDataBlock->lifetimeMS + sgRandom.randI( -mDataBlock->lifetimeVariance, mDataBlock->lifetimeVariance ); 366 367 mVelocity = mDataBlock->velocity; 368 mHeight = mDataBlock->height; 369 mTimeSinceLastRing = 1.0 / mDataBlock->ejectionFreq; 370 371 for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ ) 372 { 373 if( mDataBlock->emitterList[i] != NULL ) 374 { 375 ParticleEmitter * pEmitter = new ParticleEmitter; 376 pEmitter->onNewDataBlock( mDataBlock->emitterList[i], false ); 377 if( !pEmitter->registerObject() ) 378 { 379 Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() ); 380 delete pEmitter; 381 pEmitter = NULL; 382 } 383 mEmitterList[i] = pEmitter; 384 } 385 } 386 387 spawnExplosion(); 388 389 mObjBox.minExtents = Point3F( -1, -1, -1 ); 390 mObjBox.maxExtents = Point3F( 1, 1, 1 ); 391 resetWorldBox(); 392 393 gClientSceneGraph->addObjectToScene(this); 394 395 removeFromProcessList(); 396 ClientProcessList::get()->addObject(this); 397 398 conn->addObject(this); 399 400 return true; 401} 402 403//-------------------------------------------------------------------------- 404// OnRemove 405//-------------------------------------------------------------------------- 406void Splash::onRemove() 407{ 408 for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ ) 409 { 410 if( mEmitterList[i] ) 411 { 412 mEmitterList[i]->deleteWhenEmpty(); 413 mEmitterList[i] = NULL; 414 } 415 } 416 417 ringList.clear(); 418 419 removeFromScene(); 420 421 Parent::onRemove(); 422} 423 424 425//-------------------------------------------------------------------------- 426// On New Data Block 427//-------------------------------------------------------------------------- 428bool Splash::onNewDataBlock( GameBaseData *dptr, bool reload ) 429{ 430 mDataBlock = dynamic_cast<SplashData*>(dptr); 431 if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload)) 432 return false; 433 434 scriptOnNewDataBlock(); 435 return true; 436} 437 438 439//-------------------------------------------------------------------------- 440// Process tick 441//-------------------------------------------------------------------------- 442void Splash::processTick(const Move*) 443{ 444 mCurrMS += TickMs; 445 446 if( isServerObject() ) 447 { 448 if( mCurrMS >= mEndingMS ) 449 { 450 mDead = true; 451 if( mCurrMS >= (mEndingMS + mDataBlock->ringLifetime * 1000) ) 452 { 453 deleteObject(); 454 } 455 } 456 } 457 else 458 { 459 if( mCurrMS >= mEndingMS ) 460 { 461 mDead = true; 462 } 463 } 464} 465 466//-------------------------------------------------------------------------- 467// Advance time 468//-------------------------------------------------------------------------- 469void Splash::advanceTime(F32 dt) 470{ 471 if (dt == 0.0) 472 return; 473 474 mElapsedTime += dt; 475 476 updateColor(); 477 updateWave( dt ); 478 updateEmitters( dt ); 479 updateRings( dt ); 480 481 if( !mDead ) 482 { 483 emitRings( dt ); 484 } 485} 486 487//---------------------------------------------------------------------------- 488// Update emitters 489//---------------------------------------------------------------------------- 490void Splash::updateEmitters( F32 dt ) 491{ 492 Point3F pos = getPosition(); 493 494 for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ ) 495 { 496 if( mEmitterList[i] ) 497 { 498 mEmitterList[i]->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0, 0.0, 0.0 ), (S32) (dt * 1000) ); 499 } 500 } 501 502} 503 504//---------------------------------------------------------------------------- 505// Update wave 506//---------------------------------------------------------------------------- 507void Splash::updateWave( F32 dt ) 508{ 509 mVelocity += mDataBlock->acceleration * dt; 510 mRadius += mVelocity * dt; 511 512} 513 514//---------------------------------------------------------------------------- 515// Update color 516//---------------------------------------------------------------------------- 517void Splash::updateColor() 518{ 519 for(SplashRingList::Iterator ring = ringList.begin(); ring != ringList.end(); ++ring) 520 { 521 F32 t = F32(ring->elapsedTime) / F32(ring->lifetime); 522 523 for( U32 i = 1; i < SplashData::NUM_TIME_KEYS; i++ ) 524 { 525 if( mDataBlock->times[i] >= t ) 526 { 527 F32 firstPart = t - mDataBlock->times[i-1]; 528 F32 total = (mDataBlock->times[i] - 529 mDataBlock->times[i-1]); 530 531 firstPart /= total; 532 533 ring->color.interpolate( mDataBlock->colors[i-1], 534 mDataBlock->colors[i], 535 firstPart); 536 break; 537 } 538 } 539 } 540} 541 542//---------------------------------------------------------------------------- 543// Create ring 544//---------------------------------------------------------------------------- 545SplashRing Splash::createRing() 546{ 547 SplashRing ring; 548 U32 numPoints = mDataBlock->numSegments + 1; 549 550 Point3F ejectionAxis( 0.0, 0.0, 1.0 ); 551 552 Point3F axisx; 553 if (mFabs(ejectionAxis.z) < 0.999f) 554 mCross(ejectionAxis, Point3F(0, 0, 1), &axisx); 555 else 556 mCross(ejectionAxis, Point3F(0, 1, 0), &axisx); 557 axisx.normalize(); 558 559 for( U32 i=0; i<numPoints; i++ ) 560 { 561 F32 t = F32(i) / F32(numPoints); 562 563 AngAxisF thetaRot( axisx, mDataBlock->ejectionAngle * (M_PI / 180.0)); 564 AngAxisF phiRot( ejectionAxis, t * (M_PI * 2.0)); 565 566 Point3F pointAxis = ejectionAxis; 567 568 MatrixF temp; 569 thetaRot.setMatrix(&temp); 570 temp.mulP(pointAxis); 571 phiRot.setMatrix(&temp); 572 temp.mulP(pointAxis); 573 574 Point3F startOffset = axisx; 575 temp.mulV( startOffset ); 576 startOffset *= mDataBlock->startRadius; 577 578 SplashRingPoint point; 579 point.position = getPosition() + startOffset; 580 point.velocity = pointAxis * mDataBlock->velocity; 581 582 ring.points.push_back( point ); 583 } 584 585 ring.color = mDataBlock->colors[0]; 586 ring.lifetime = mDataBlock->ringLifetime; 587 ring.elapsedTime = 0.0; 588 ring.v = mDataBlock->texFactor * mFmod( mElapsedTime, 1.0 ); 589 590 return ring; 591} 592 593//---------------------------------------------------------------------------- 594// Emit rings 595//---------------------------------------------------------------------------- 596void Splash::emitRings( F32 dt ) 597{ 598 mTimeSinceLastRing += dt; 599 600 S32 numNewRings = (S32) (mTimeSinceLastRing * F32(mDataBlock->ejectionFreq)); 601 602 mTimeSinceLastRing -= numNewRings / mDataBlock->ejectionFreq; 603 604 for( S32 i=numNewRings-1; i>=0; i-- ) 605 { 606 F32 t = F32(i) / F32(numNewRings); 607 t *= dt; 608 t += mTimeSinceLastRing; 609 610 SplashRing ring = createRing(); 611 updateRing( ring, t ); 612 613 ringList.pushBack( ring ); 614 } 615} 616 617//---------------------------------------------------------------------------- 618// Update rings 619//---------------------------------------------------------------------------- 620void Splash::updateRings( F32 dt ) 621{ 622 SplashRingList::Iterator ring; 623 for(SplashRingList::Iterator i = ringList.begin(); i != ringList.end(); /*Trickiness*/) 624 { 625 ring = i++; 626 ring->elapsedTime += dt; 627 628 if( !ring->isActive() ) 629 { 630 ringList.erase( ring ); 631 } 632 else 633 { 634 updateRing( *ring, dt ); 635 } 636 } 637} 638 639//---------------------------------------------------------------------------- 640// Update ring 641//---------------------------------------------------------------------------- 642void Splash::updateRing( SplashRing& ring, F32 dt ) 643{ 644 for( U32 i=0; i<ring.points.size(); i++ ) 645 { 646 if( mDead ) 647 { 648 Point3F vel = ring.points[i].velocity; 649 vel.normalize(); 650 vel *= mDataBlock->acceleration; 651 ring.points[i].velocity += vel * dt; 652 } 653 654 ring.points[i].velocity += Point3F( 0.0f, 0.0f, -9.8f ) * dt; 655 ring.points[i].position += ring.points[i].velocity * dt; 656 } 657} 658 659//---------------------------------------------------------------------------- 660// Explode 661//---------------------------------------------------------------------------- 662void Splash::spawnExplosion() 663{ 664 if( !mDataBlock->explosion ) return; 665 666 Explosion* pExplosion = new Explosion; 667 pExplosion->onNewDataBlock(mDataBlock->explosion, false); 668 669 MatrixF trans = getTransform(); 670 trans.setPosition( getPosition() ); 671 672 pExplosion->setTransform( trans ); 673 pExplosion->setInitialState( trans.getPosition(), VectorF(0,0,1), 1); 674 if (!pExplosion->registerObject()) 675 delete pExplosion; 676} 677 678//-------------------------------------------------------------------------- 679// packUpdate 680//-------------------------------------------------------------------------- 681U32 Splash::packUpdate(NetConnection* con, U32 mask, BitStream* stream) 682{ 683 U32 retMask = Parent::packUpdate(con, mask, stream); 684 685 if( stream->writeFlag(mask & GameBase::InitialUpdateMask) ) 686 { 687 mathWrite(*stream, mInitialPosition); 688 } 689 690 return retMask; 691} 692 693//-------------------------------------------------------------------------- 694// unpackUpdate 695//-------------------------------------------------------------------------- 696void Splash::unpackUpdate(NetConnection* con, BitStream* stream) 697{ 698 Parent::unpackUpdate(con, stream); 699 700 if( stream->readFlag() ) 701 { 702 mathRead(*stream, &mInitialPosition); 703 setPosition( mInitialPosition ); 704 } 705} 706
