00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00097
00098 if (params_->getCreateDebris())
00099 {
00100
00101 if (aboveGround < 1.0f && !waterSplash)
00102 {
00103 ParticleEmitter sprayemitter;
00104 sprayemitter.setAttributes(
00105 3.0f, 4.0f,
00106 0.5f, 1.0f,
00107 0.01f, 0.02f,
00108 Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, 0.0f),
00109 Vector(0.9f, 0.9f, 0.9f), 0.5f,
00110 Vector(1.0f, 1.0f, 1.0f), 0.7f,
00111 Vector(0.9f, 0.9f, 0.9f), 0.0f,
00112 Vector(1.0f, 1.0f, 1.0f), 0.1f,
00113 3.0f, 3.0f, 4.0f, 4.0f,
00114 3.0f, 3.0f, 4.0f, 4.0f,
00115 Vector(0.0f, 0.0f, -800.0f),
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,
00128 0.2f, 0.5f,
00129 0.01f, 0.02f,
00130 Vector(-0.05f, -0.1f, 0.3f), Vector(0.05f, 0.1f, 0.9f),
00131 Vector(0.7f, 0.7f, 0.7f), 0.3f,
00132 Vector(0.7f, 0.7f, 0.7f), 0.3f,
00133 Vector(0.7f, 0.7f, 0.7f), 0.0f,
00134 Vector(0.8f, 0.8f, 0.8f), 0.1f,
00135 0.2f, 0.2f, 0.5f, 0.5f,
00136 2.2f, 2.2f, 4.0f, 4.0f,
00137 Vector(0.0f, 0.0f, -800.0f),
00138 false,
00139 true);
00140
00141
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
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(),
00184 0.2f, 0.5f,
00185 0.01f, 0.02f,
00186 Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, 0.0f),
00187 expColor, 0.8f,
00188 expColor, 0.9f,
00189 expColor, 0.0f,
00190 expColor, 0.1f,
00191 0.2f, 0.2f, 0.5f, 0.5f,
00192 2.2f, 2.2f, 4.0f, 4.0f,
00193 Vector(0.0f, 0.0f, 0.0f),
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
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
00249 fixed landHeight = context_->getLandscapeMaps().getGroundMaps().
00250 getInterpHeight(position_[0], position_[1]);
00251
00252
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
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
00270 if (!params_->getExplodeUnderGround())
00271 {
00272 if (position_[2] - landHeight < -1)
00273 {
00274 explosionSize = 0;
00275 }
00276 }
00277
00278
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
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 }