Explosion.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <target/TargetDamageCalc.h>
00022 #include <common/OptionsScorched.h>
00023 #include <common/Defines.h>
00024 #include <common/Logger.h>
00025 #include <weapons/AccessoryStore.h>
00026 #include <weapons/WeaponExplosion.h>
00027 #include <actions/Explosion.h>
00028 #include <actions/CameraPositionAction.h>
00029 #include <engine/ScorchedContext.h>
00030 #include <engine/ActionController.h>
00031 #ifndef S3D_SERVER
00032         #include <graph/OptionsDisplay.h>
00033         #include <graph/ParticleEmitter.h>
00034         #include <graph/MainCamera.h>
00035         #include <client/ScorchedClient.h>
00036         #include <sound/SoundUtils.h>
00037         #include <land/VisibilityPatchGrid.h>
00038 #endif
00039 #include <landscapemap/DeformLandscape.h>
00040 #include <landscapemap/LandscapeMaps.h>
00041 #ifndef S3D_SERVER
00042         #include <landscape/DeformTextures.h>
00043         #include <landscape/Landscape.h>
00044         #include <water/Water.h>
00045         #include <landscape/Smoke.h>
00046         #include <sprites/ExplosionNukeRenderer.h>
00047         #include <sprites/ExplosionTextures.h>
00048 #endif
00049 #include <math.h>
00050 
00051 Explosion::Explosion(FixedVector &position,
00052         ExplosionParams *params,
00053         Weapon *weapon, WeaponFireContext &weaponContext) :
00054         ActionReferenced("Explosion"),
00055         params_(params),
00056         firstTime_(true), totalTime_(0),
00057         weapon_(weapon), weaponContext_(weaponContext), 
00058         position_(position)
00059 {
00060 }
00061 
00062 Explosion::~Explosion()
00063 {
00064         delete params_;
00065 }
00066 
00067 void Explosion::init()
00068 {
00069         fixed ShowTime = 4;
00070         CameraPositionAction *pos = new CameraPositionAction(
00071                 position_, ShowTime, 10);
00072         context_->getActionController().addAction(pos);
00073 
00074         fixed multiplier = fixed(((int) context_->getOptionsGame().getWeapScale()) - 
00075                                                          OptionsGame::ScaleMedium);
00076         multiplier *= fixed(true, 5000);
00077         multiplier += 1;
00078         fixed explosionSize = params_->getSize() * multiplier;  
00079 
00080 #ifndef S3D_SERVER
00081         if (!context_->getServerMode()) 
00082         {
00083                 float height = context_->getLandscapeMaps().getGroundMaps().getInterpHeight(
00084                         position_[0], position_[1]).asFloat();
00085                 float aboveGround = position_[2].asFloat() - height;
00086 
00087                 // If there is a weapon play a splash sound when in water
00088                 bool waterSplash = false;
00089                 if (params_->getCreateSplash())
00090                 {
00091                         waterSplash = 
00092                                 Landscape::instance()->getWater().explosion(
00093                                         position_.asVector(), params_->getSize().asFloat());
00094                 }
00095 
00096                 // Create particles from the center of the explosion
00097                 // These particles will render smoke trails or bits of debris
00098                 if (params_->getCreateDebris())
00099                 {
00100                         // If we are below the ground create the spray of dirt (or water)
00101                         if (aboveGround < 1.0f && !waterSplash)
00102                         {
00103                                 ParticleEmitter sprayemitter;
00104                                 sprayemitter.setAttributes(
00105                                         3.0f, 4.0f, // Life
00106                                         0.5f, 1.0f, // Mass
00107                                         0.01f, 0.02f, // Friction
00108                                         Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, 0.0f), // Velocity
00109                                         Vector(0.9f, 0.9f, 0.9f), 0.5f, // StartColor1
00110                                         Vector(1.0f, 1.0f, 1.0f), 0.7f, // StartColor2
00111                                         Vector(0.9f, 0.9f, 0.9f), 0.0f, // EndColor1
00112                                         Vector(1.0f, 1.0f, 1.0f), 0.1f, // EndColor2
00113                                         3.0f, 3.0f, 4.0f, 4.0f, // Start Size
00114                                         3.0f, 3.0f, 4.0f, 4.0f, // EndSize
00115                                         Vector(0.0f, 0.0f, -800.0f), // Gravity
00116                                         false,
00117                                         true);
00118 
00119                                 sprayemitter.emitSpray(position_.asVector(), 
00120                                         ScorchedClient::instance()->getParticleEngine(),
00121                                         params_->getSize().asFloat() - 2.0f,
00122                                         &Landscape::instance()->getLandscapeTexture1());
00123                         }
00124 
00125                         ParticleEmitter emitter;
00126                         emitter.setAttributes(
00127                                 2.5f, 4.0f, // Life
00128                                 0.2f, 0.5f, // Mass
00129                                 0.01f, 0.02f, // Friction
00130                                 Vector(-0.05f, -0.1f, 0.3f), Vector(0.05f, 0.1f, 0.9f), // Velocity
00131                                 Vector(0.7f, 0.7f, 0.7f), 0.3f, // StartColor1
00132                                 Vector(0.7f, 0.7f, 0.7f), 0.3f, // StartColor2
00133                                 Vector(0.7f, 0.7f, 0.7f), 0.0f, // EndColor1
00134                                 Vector(0.8f, 0.8f, 0.8f), 0.1f, // EndColor2
00135                                 0.2f, 0.2f, 0.5f, 0.5f, // Start Size
00136                                 2.2f, 2.2f, 4.0f, 4.0f, // EndSize
00137                                 Vector(0.0f, 0.0f, -800.0f), // Gravity
00138                                 false,
00139                                 true);
00140 
00141                         // Create debris
00142                         float mult = float(
00143                                 OptionsDisplay::instance()->getExplosionParticlesMult()) / 40.0f;
00144                         int debris = 5 + int(params_->getSize().asFloat() * mult);
00145                         emitter.emitDebris(debris,
00146                                 position_.asVector(), 
00147                                 ScorchedClient::instance()->getParticleEngine());
00148                 }
00149 
00150                 if (0 == strcmp(weapon_->getAccessoryTypeName(), "WeaponMuzzle"))
00151                 {
00152                         // Add initial smoke clouds
00153                         for (int a=0; a<OptionsDisplay::instance()->getNumberExplosionSubParts() * 2; a++)
00154                         {
00155                                 float posXY = (RAND * 4.0f) - 2.0f;
00156                                 float posYZ = (RAND * 4.0f) - 2.0f;
00157 
00158                                 Landscape::instance()->getSmoke().addSmoke(
00159                                         position_[0].asFloat() + posXY, 
00160                                         position_[1].asFloat() + posYZ, 
00161                                         position_[2].asFloat() + 2.0f);
00162                         }
00163                 }
00164                 else
00165                 {
00166                         context_->getViewPoints().explosion(weaponContext_.getPlayerId());
00167                 }
00168 
00169                 {
00170                         GLTextureSet *texture = 0;
00171                         if (0 != strcmp(params_->getExplosionTexture(), "none"))
00172                         {
00173                                 texture = ExplosionTextures::instance()->getTextureSetByName(
00174                                         params_->getExplosionTexture());
00175                         }
00176 
00177                         if (texture)
00178                         {
00179                                 Vector expColor = params_->getExplosionColor().asVector();
00180 
00181                                 ParticleEmitter exploemitter;
00182                                 exploemitter.setAttributes(
00183                                         params_->getMinLife().asFloat(), params_->getMaxLife().asFloat(), // Life
00184                                         0.2f, 0.5f, // Mass
00185                                         0.01f, 0.02f, // Friction
00186                                         Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, 0.0f), // Velocity
00187                                         expColor, 0.8f, // StartColor1
00188                                         expColor, 0.9f, // StartColor2
00189                                         expColor, 0.0f, // EndColor1
00190                                         expColor, 0.1f, // EndColor2
00191                                         0.2f, 0.2f, 0.5f, 0.5f, // Start Size
00192                                         2.2f, 2.2f, 4.0f, 4.0f, // EndSize
00193                                         Vector(0.0f, 0.0f, 0.0f), // Gravity
00194                                         params_->getLuminance(),
00195                                         params_->getWindAffected());
00196                                 exploemitter.emitExplosion(position_.asVector(),
00197                                         ScorchedClient::instance()->getParticleEngine(),
00198                                         explosionSize.asFloat(),
00199                                         texture,
00200                                         params_->getAnimate());
00201                         }
00202                 }
00203 
00204                 if (params_->getCreateMushroomAmount() > 0)
00205                 {
00206                         if (RAND <= params_->getCreateMushroomAmount().asFloat())
00207                         {
00208                                 context_->getActionController().addAction(
00209                                         new SpriteAction(
00210                                         new ExplosionNukeRenderer(position_.asVector(), params_->getSize().asFloat() - 2.0f))); 
00211                         }
00212                 }
00213 
00214                 // Make the camera shake
00215                 MainCamera::instance()->getCamera().addShake(params_->getShake().asFloat());
00216         }
00217 #endif // #ifndef S3D_SERVER
00218 }
00219 
00220 std::string Explosion::getActionDetails()
00221 {
00222         return S3D::formatStringBuffer("%i,%i,%i %s", 
00223                 position_[0].getInternal(), position_[1].getInternal(), position_[2].getInternal(), 
00224                 weapon_->getParent()->getName());
00225 }
00226 
00227 void Explosion::simulate(fixed frameTime, bool &remove)
00228 {
00229         totalTime_ += frameTime;
00230         if (firstTime_)
00231         {
00232                 firstTime_ = false;
00233 #ifndef S3D_SERVER
00234                 if (!context_->getServerMode()) 
00235                 {
00236                         if (params_->getExplosionSound() &&
00237                                 0 != strcmp("none", params_->getExplosionSound()))
00238                         {
00239                                 SoundBuffer *expSound = 
00240                                         Sound::instance()->fetchOrCreateBuffer(
00241                                                 S3D::getDataFile(S3D::formatStringBuffer("data/wav/%s", params_->getExplosionSound())));
00242                                 SoundUtils::playAbsoluteSound(VirtualSoundPriority::eAction,
00243                                         expSound, position_.asVector());
00244                         }
00245                 }
00246 #endif // #ifndef S3D_SERVER
00247 
00248                 // Get the land height at the explosion
00249                 fixed landHeight = context_->getLandscapeMaps().getGroundMaps().
00250                                 getInterpHeight(position_[0], position_[1]);
00251 
00252                 // Dirt should only form along the ground
00253                 FixedVector newPosition = position_;
00254                 if (params_->getDeformType() == ExplosionParams::DeformUp)
00255                 {
00256                         newPosition[2] = landHeight;
00257                 }
00258 
00259                 if (params_->getDeformType() != ExplosionParams::DeformNone)
00260                 {
00261                         // Get the actual explosion size
00262                         fixed multiplier = 
00263                                 fixed(((int) context_->getOptionsGame().getWeapScale()) - 
00264                                         OptionsGame::ScaleMedium);
00265                         multiplier *= fixed(true, 5000);
00266                         multiplier += 1;
00267                         fixed explosionSize = params_->getSize() * multiplier;  
00268 
00269                         // Check if we are allowed to explode underground
00270                         if (!params_->getExplodeUnderGround())
00271                         {
00272                                 if (position_[2] - landHeight < -1)
00273                                 {
00274                                         explosionSize = 0;
00275                                 }
00276                         }
00277 
00278                         // Remove areas from the height map
00279                         if (explosionSize > 0)
00280                         {
00281                                 static DeformLandscape::DeformPoints map;
00282 
00283                                 if (DeformLandscape::deformLandscape(
00284                                         *context_,
00285                                         newPosition, explosionSize, 
00286                                         (params_->getDeformType() == ExplosionParams::DeformDown), map))
00287                                 {
00288 #ifndef S3D_SERVER
00289                                         if (!context_->getServerMode()) 
00290                                         {
00291                                                 Landscape::instance()->recalculate();
00292                                                 VisibilityPatchGrid::instance()->recalculateErrors(newPosition, explosionSize);
00293 
00294                                                 DeformTextures::deformLandscape(
00295                                                         newPosition.asVector(), 
00296                                                         explosionSize.asFloat(),  
00297                                                         ExplosionTextures::instance()->getScorchBitmap(params_->getDeformTexture()),
00298                                                         map);
00299                                         }
00300 #endif // #ifndef S3D_SERVER
00301                                 }
00302                         }
00303                 }
00304 
00305                 if (params_->getHurtAmount() != 0 ||
00306                         params_->getDeformType() != ExplosionParams::DeformNone)
00307                 {
00308                         // Check the tanks for damage
00309                         TargetDamageCalc::explosion(
00310                                 *context_,
00311                                 weapon_, weaponContext_, 
00312                                 newPosition, 
00313                                 params_->getSize() , 
00314                                 params_->getHurtAmount(),
00315                                 (params_->getDeformType() != ExplosionParams::DeformNone),
00316                                 params_->getOnlyHurtShield());
00317                 }
00318         }
00319 
00320         remove = true;
00321         Action::simulate(frameTime, remove);
00322 }

Generated on Mon Feb 16 15:14:48 2009 for Scorched3D by  doxygen 1.5.3