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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">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 href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</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], &GFXStaticTextureSRGBProfile, 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 mRandAngle = 0; 314 mEndingMS = 1000; 315 mActive = false; 316 mRadius = 0.0; 317 mVelocity = 1.0; 318 mHeight = 0.0; 319 mTimeSinceLastRing = 0.0; 320 mDead = false; 321 mElapsedTime = 0.0; 322 323 mInitialNormal.set( 0.0, 0.0, 1.0 ); 324 mFade = 0; 325 mFog = 0; 326 // Only allocated client side. 327 mNetFlags.set( IsGhost ); 328} 329 330//-------------------------------------------------------------------------- 331// Destructor 332//-------------------------------------------------------------------------- 333Splash::~Splash() 334{ 335} 336 337//-------------------------------------------------------------------------- 338// Set initial state 339//-------------------------------------------------------------------------- 340void Splash::setInitialState(const Point3F& point, const Point3F& normal, const F32 fade) 341{ 342 mInitialPosition = point; 343 mInitialNormal = normal; 344 mFade = fade; 345 mFog = 0.0f; 346} 347 348 349//-------------------------------------------------------------------------- 350// OnAdd 351//-------------------------------------------------------------------------- 352bool Splash::onAdd() 353{ 354 // first check if we have a server connection, if we dont then this is on the server 355 // and we should exit, then check if the parent fails to add the object 356 NetConnection* conn = NetConnection::getConnectionToServer(); 357 if(!conn || !Parent::onAdd()) 358 return false; 359 360 if( !mDataBlock ) 361 { 362 Con::errorf("Splash::onAdd - Fail - No datablock"); 363 return false; 364 } 365 366 mDelayMS = mDataBlock->delayMS + sgRandom.randI( -mDataBlock->delayVariance, mDataBlock->delayVariance ); 367 mEndingMS = mDataBlock->lifetimeMS + sgRandom.randI( -mDataBlock->lifetimeVariance, mDataBlock->lifetimeVariance ); 368 369 mVelocity = mDataBlock->velocity; 370 mHeight = mDataBlock->height; 371 mTimeSinceLastRing = 1.0 / mDataBlock->ejectionFreq; 372 373 for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ ) 374 { 375 if( mDataBlock->emitterList[i] != NULL ) 376 { 377 ParticleEmitter * pEmitter = new ParticleEmitter; 378 pEmitter->onNewDataBlock( mDataBlock->emitterList[i], false ); 379 if( !pEmitter->registerObject() ) 380 { 381 Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() ); 382 delete pEmitter; 383 pEmitter = NULL; 384 } 385 mEmitterList[i] = pEmitter; 386 } 387 } 388 389 spawnExplosion(); 390 391 mObjBox.minExtents = Point3F( -1, -1, -1 ); 392 mObjBox.maxExtents = Point3F( 1, 1, 1 ); 393 resetWorldBox(); 394 395 gClientSceneGraph->addObjectToScene(this); 396 397 removeFromProcessList(); 398 ClientProcessList::get()->addObject(this); 399 400 conn->addObject(this); 401 402 return true; 403} 404 405//-------------------------------------------------------------------------- 406// OnRemove 407//-------------------------------------------------------------------------- 408void Splash::onRemove() 409{ 410 for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ ) 411 { 412 if( mEmitterList[i] ) 413 { 414 mEmitterList[i]->deleteWhenEmpty(); 415 mEmitterList[i] = NULL; 416 } 417 } 418 419 ringList.clear(); 420 421 removeFromScene(); 422 423 Parent::onRemove(); 424} 425 426 427//-------------------------------------------------------------------------- 428// On New Data Block 429//-------------------------------------------------------------------------- 430bool Splash::onNewDataBlock( GameBaseData *dptr, bool reload ) 431{ 432 mDataBlock = dynamic_cast<SplashData*>(dptr); 433 if (!mDataBlock || !Parent::onNewDataBlock(dptr, reload)) 434 return false; 435 436 scriptOnNewDataBlock(); 437 return true; 438} 439 440 441//-------------------------------------------------------------------------- 442// Process tick 443//-------------------------------------------------------------------------- 444void Splash::processTick(const Move*) 445{ 446 mCurrMS += TickMs; 447 448 if( isServerObject() ) 449 { 450 if( mCurrMS >= mEndingMS ) 451 { 452 mDead = true; 453 if( mCurrMS >= (mEndingMS + mDataBlock->ringLifetime * 1000) ) 454 { 455 deleteObject(); 456 } 457 } 458 } 459 else 460 { 461 if( mCurrMS >= mEndingMS ) 462 { 463 mDead = true; 464 } 465 } 466} 467 468//-------------------------------------------------------------------------- 469// Advance time 470//-------------------------------------------------------------------------- 471void Splash::advanceTime(F32 dt) 472{ 473 if (dt == 0.0) 474 return; 475 476 mElapsedTime += dt; 477 478 updateColor(); 479 updateWave( dt ); 480 updateEmitters( dt ); 481 updateRings( dt ); 482 483 if( !mDead ) 484 { 485 emitRings( dt ); 486 } 487} 488 489//---------------------------------------------------------------------------- 490// Update emitters 491//---------------------------------------------------------------------------- 492void Splash::updateEmitters( F32 dt ) 493{ 494 Point3F pos = getPosition(); 495 496 for( U32 i=0; i<SplashData::NUM_EMITTERS; i++ ) 497 { 498 if( mEmitterList[i] ) 499 { 500 mEmitterList[i]->emitParticles( pos, pos, mInitialNormal, Point3F( 0.0, 0.0, 0.0 ), (S32) (dt * 1000) ); 501 } 502 } 503 504} 505 506//---------------------------------------------------------------------------- 507// Update wave 508//---------------------------------------------------------------------------- 509void Splash::updateWave( F32 dt ) 510{ 511 mVelocity += mDataBlock->acceleration * dt; 512 mRadius += mVelocity * dt; 513 514} 515 516//---------------------------------------------------------------------------- 517// Update color 518//---------------------------------------------------------------------------- 519void Splash::updateColor() 520{ 521 for(SplashRingList::Iterator ring = ringList.begin(); ring != ringList.end(); ++ring) 522 { 523 F32 t = F32(ring->elapsedTime) / F32(ring->lifetime); 524 525 for( U32 i = 1; i < SplashData::NUM_TIME_KEYS; i++ ) 526 { 527 if( mDataBlock->times[i] >= t ) 528 { 529 F32 firstPart = t - mDataBlock->times[i-1]; 530 F32 total = (mDataBlock->times[i] - 531 mDataBlock->times[i-1]); 532 533 firstPart /= total; 534 535 ring->color.interpolate( mDataBlock->colors[i-1], 536 mDataBlock->colors[i], 537 firstPart); 538 break; 539 } 540 } 541 } 542} 543 544//---------------------------------------------------------------------------- 545// Create ring 546//---------------------------------------------------------------------------- 547SplashRing Splash::createRing() 548{ 549 SplashRing ring; 550 U32 numPoints = mDataBlock->numSegments + 1; 551 552 Point3F ejectionAxis( 0.0, 0.0, 1.0 ); 553 554 Point3F axisx; 555 if (mFabs(ejectionAxis.z) < 0.999f) 556 mCross(ejectionAxis, Point3F(0, 0, 1), &axisx); 557 else 558 mCross(ejectionAxis, Point3F(0, 1, 0), &axisx); 559 axisx.normalize(); 560 561 for( U32 i=0; i<numPoints; i++ ) 562 { 563 F32 t = F32(i) / F32(numPoints); 564 565 AngAxisF thetaRot( axisx, mDataBlock->ejectionAngle * (M_PI / 180.0)); 566 AngAxisF phiRot( ejectionAxis, t * (M_PI * 2.0)); 567 568 Point3F pointAxis = ejectionAxis; 569 570 MatrixF temp; 571 thetaRot.setMatrix(&temp); 572 temp.mulP(pointAxis); 573 phiRot.setMatrix(&temp); 574 temp.mulP(pointAxis); 575 576 Point3F startOffset = axisx; 577 temp.mulV( startOffset ); 578 startOffset *= mDataBlock->startRadius; 579 580 SplashRingPoint point; 581 point.position = getPosition() + startOffset; 582 point.velocity = pointAxis * mDataBlock->velocity; 583 584 ring.points.push_back( point ); 585 } 586 587 ring.color = mDataBlock->colors[0]; 588 ring.lifetime = mDataBlock->ringLifetime; 589 ring.elapsedTime = 0.0; 590 ring.v = mDataBlock->texFactor * mFmod( mElapsedTime, 1.0 ); 591 592 return ring; 593} 594 595//---------------------------------------------------------------------------- 596// Emit rings 597//---------------------------------------------------------------------------- 598void Splash::emitRings( F32 dt ) 599{ 600 mTimeSinceLastRing += dt; 601 602 S32 numNewRings = (S32) (mTimeSinceLastRing * F32(mDataBlock->ejectionFreq)); 603 604 mTimeSinceLastRing -= numNewRings / mDataBlock->ejectionFreq; 605 606 for( S32 i=numNewRings-1; i>=0; i-- ) 607 { 608 F32 t = F32(i) / F32(numNewRings); 609 t *= dt; 610 t += mTimeSinceLastRing; 611 612 SplashRing ring = createRing(); 613 updateRing( ring, t ); 614 615 ringList.pushBack( ring ); 616 } 617} 618 619//---------------------------------------------------------------------------- 620// Update rings 621//---------------------------------------------------------------------------- 622void Splash::updateRings( F32 dt ) 623{ 624 SplashRingList::Iterator ring; 625 for(SplashRingList::Iterator i = ringList.begin(); i != ringList.end(); /*Trickiness*/) 626 { 627 ring = i++; 628 ring->elapsedTime += dt; 629 630 if( !ring->isActive() ) 631 { 632 ringList.erase( ring ); 633 } 634 else 635 { 636 updateRing( *ring, dt ); 637 } 638 } 639} 640 641//---------------------------------------------------------------------------- 642// Update ring 643//---------------------------------------------------------------------------- 644void Splash::updateRing( SplashRing& ring, F32 dt ) 645{ 646 for( U32 i=0; i<ring.points.size(); i++ ) 647 { 648 if( mDead ) 649 { 650 Point3F vel = ring.points[i].velocity; 651 vel.normalize(); 652 vel *= mDataBlock->acceleration; 653 ring.points[i].velocity += vel * dt; 654 } 655 656 ring.points[i].velocity += Point3F( 0.0f, 0.0f, -9.8f ) * dt; 657 ring.points[i].position += ring.points[i].velocity * dt; 658 } 659} 660 661//---------------------------------------------------------------------------- 662// Explode 663//---------------------------------------------------------------------------- 664void Splash::spawnExplosion() 665{ 666 if( !mDataBlock->explosion ) return; 667 668 Explosion* pExplosion = new Explosion; 669 pExplosion->onNewDataBlock(mDataBlock->explosion, false); 670 671 MatrixF trans = getTransform(); 672 trans.setPosition( getPosition() ); 673 674 pExplosion->setTransform( trans ); 675 pExplosion->setInitialState( trans.getPosition(), VectorF(0,0,1), 1); 676 if (!pExplosion->registerObject()) 677 delete pExplosion; 678} 679 680//-------------------------------------------------------------------------- 681// packUpdate 682//-------------------------------------------------------------------------- 683U32 Splash::packUpdate(NetConnection* con, U32 mask, BitStream* stream) 684{ 685 U32 retMask = Parent::packUpdate(con, mask, stream); 686 687 if( stream->writeFlag(mask & GameBase::InitialUpdateMask) ) 688 { 689 mathWrite(*stream, mInitialPosition); 690 } 691 692 return retMask; 693} 694 695//-------------------------------------------------------------------------- 696// unpackUpdate 697//-------------------------------------------------------------------------- 698void Splash::unpackUpdate(NetConnection* con, BitStream* stream) 699{ 700 Parent::unpackUpdate(con, stream); 701 702 if( stream->readFlag() ) 703 { 704 mathRead(*stream, &mInitialPosition); 705 setPosition( mInitialPosition ); 706 } 707} 708