summaryrefslogtreecommitdiffhomepage
path: root/Stars45/Shot.cpp
diff options
context:
space:
mode:
authormilo24x7@gmail.com <milo24x7@gmail.com@076cb2c4-205e-83fd-5cf3-1be9aa105544>2013-07-07 22:08:49 +0000
committermilo24x7@gmail.com <milo24x7@gmail.com@076cb2c4-205e-83fd-5cf3-1be9aa105544>2013-07-07 22:08:49 +0000
commitd17521c8b9085a91d08fecfd0b51bbbf7b1dccac (patch)
tree4673104b47dc68a079cac9f94deefd48dfcb66fa /Stars45/Shot.cpp
parent1de4b2bdbb019be6f1b7262c3eba5568d7682edd (diff)
downloadstarshatter-d17521c8b9085a91d08fecfd0b51bbbf7b1dccac.zip
starshatter-d17521c8b9085a91d08fecfd0b51bbbf7b1dccac.tar.gz
starshatter-d17521c8b9085a91d08fecfd0b51bbbf7b1dccac.tar.bz2
Updated open source license declaration and fixed some formatting issues.
Diffstat (limited to 'Stars45/Shot.cpp')
-rw-r--r--Stars45/Shot.cpp1276
1 files changed, 650 insertions, 626 deletions
diff --git a/Stars45/Shot.cpp b/Stars45/Shot.cpp
index 8311843..09caf98 100644
--- a/Stars45/Shot.cpp
+++ b/Stars45/Shot.cpp
@@ -1,626 +1,650 @@
-/* Project Starshatter 4.5
- Destroyer Studios LLC
- Copyright (C) 1997-2004. All Rights Reserved.
-
- SUBSYSTEM: Stars.exe
- FILE: Shot.cpp
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Laser and Missile class
-*/
-
-#include "MemDebug.h"
-#include "Shot.h"
-#include "Weapon.h"
-#include "DriveSprite.h"
-#include "SeekerAI.h"
-#include "Sim.h"
-#include "Ship.h"
-#include "Trail.h"
-#include "Random.h"
-#include "AudioConfig.h"
-#include "TerrainRegion.h"
-#include "Terrain.h"
-
-#include "Game.h"
-#include "Bolt.h"
-#include "Sprite.h"
-#include "Solid.h"
-#include "Light.h"
-#include "Bitmap.h"
-#include "DataLoader.h"
-#include "Sound.h"
-
-// +--------------------------------------------------------------------+
-
-Shot::Shot(const Point& pos, const Camera& shot_cam, WeaponDesign* dsn, const Ship* ship)
-: first_frame(true), owner(ship), flash(0), flare(0), trail(0), sound(0), eta(0),
-charge(1.0f), design(dsn), offset(1.0e5f), altitude_agl(-1.0e6f), hit_target(false)
-{
- obj_type = SimObject::SIM_SHOT;
- type = design->type;
- primary = design->primary;
- beam = design->beam;
- base_damage = design->damage;
- armed = false;
-
- radius = 10.0f;
-
- if (primary || design->decoy_type || !design->guided) {
- straight = true;
- armed = true;
- }
-
- cam.Clone(shot_cam);
-
- life = design->life;
- velocity = cam.vpn() * (double) design->speed;
-
- MoveTo(pos);
-
- if (beam)
- origin = pos + (shot_cam.vpn() * -design->length);
-
- switch (design->graphic_type) {
- case Graphic::BOLT: {
- Bolt* s = new(__FILE__,__LINE__) Bolt(design->length, design->width, design->shot_img, 1);
- s->SetDirection(cam.vpn());
- rep = s;
- }
- break;
-
- case Graphic::SPRITE: {
- Sprite* s = 0;
-
- if (design->animation)
- s = new(__FILE__,__LINE__) DriveSprite(design->animation, design->anim_length);
- else
- s = new(__FILE__,__LINE__) DriveSprite(design->shot_img);
-
- s->Scale((double) design->scale);
- rep = s;
- }
- break;
-
- case Graphic::SOLID: {
- Solid* s = new(__FILE__,__LINE__) Solid;
- s->UseModel(design->shot_model);
- rep = s;
-
- radius = rep->Radius();
- }
- break;
- }
-
- if (rep)
- rep->MoveTo(pos);
-
- light = 0;
-
- if (design->light > 0) {
- light = new(__FILE__,__LINE__) Light(design->light);
- light->SetColor(design->light_color);
- }
-
- mass = design->mass;
- drag = design->drag;
- thrust = 0.0f;
-
- dr_drg = design->roll_drag;
- dp_drg = design->pitch_drag;
- dy_drg = design->yaw_drag;
-
- SetAngularRates((float) design->roll_rate, (float) design->pitch_rate, (float) design->yaw_rate);
-
- if (design->flash_img != 0) {
- flash = new(__FILE__,__LINE__) Sprite(design->flash_img);
- flash->Scale((double) design->flash_scale);
- flash->MoveTo(pos - cam.vpn() * design->length);
- flash->SetLuminous(true);
- }
-
- if (design->flare_img != 0) {
- flare = new(__FILE__,__LINE__) DriveSprite(design->flare_img);
- flare->Scale((double) design->flare_scale);
- flare->MoveTo(pos);
- }
-
- if (owner) {
- iff_code = (BYTE) owner->GetIFF();
- Observe((SimObject*) owner);
- }
-
- sprintf_s(name, "Shot(%s)", design->name.data());
-}
-
-// +--------------------------------------------------------------------+
-
-Shot::~Shot()
-{
- GRAPHIC_DESTROY(flash);
- GRAPHIC_DESTROY(flare);
- GRAPHIC_DESTROY(trail);
-
- if (sound) {
- sound->Stop();
- sound->Release();
- }
-}
-
-// +--------------------------------------------------------------------+
-
-const char*
-Shot::DesignName() const
-{
- return design->name;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::SetCharge(float c)
-{
- charge = c;
-
- // trim beam life to amount of energy available:
- if (beam)
- life = design->life * charge / design->charge;
-}
-
-void
-Shot::SetFuse(double seconds)
-{
- if (seconds > 0 && !beam)
- life = seconds;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::SeekTarget(SimObject* target, System* sub)
-{
- if (dir && !primary) {
- SeekerAI* seeker = (SeekerAI*) dir;
- SimObject* old_target = seeker->GetTarget();
-
- if (old_target->Type()==SimObject::SIM_SHIP) {
- Ship* tgt_ship = (Ship*) old_target;
- tgt_ship->DropThreat(this);
- }
- }
-
- delete dir;
- dir = 0;
-
- if (target) {
- SeekerAI* seeker = new(__FILE__,__LINE__) SeekerAI(this);
- seeker->SetTarget(target, sub);
- seeker->SetPursuit(design->guided);
- seeker->SetDelay(1);
-
- dir = seeker;
-
- if (!primary && target->Type()==SimObject::SIM_SHIP) {
- Ship* tgt_ship = (Ship*) target;
- tgt_ship->AddThreat(this);
- }
- }
-}
-
-bool
-Shot::IsTracking(Ship* tgt) const
-{
- return tgt && (GetTarget() == tgt);
-}
-
-SimObject*
-Shot::GetTarget() const
-{
- if (dir) {
- SeekerAI* seeker = (SeekerAI*) dir;
-
- if (seeker->GetDelay() <= 0)
- return seeker->GetTarget();
- }
-
- return 0;
-}
-
-bool
-Shot::IsFlak() const
-{
- return design && design->flak;
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-Shot::IsHostileTo(const SimObject* o) const
-{
- if (o) {
- if (o->Type() == SIM_SHIP) {
- Ship* s = (Ship*) o;
-
- if (s->IsRogue())
- return true;
-
- if (s->GetIFF() > 0 && s->GetIFF() != GetIFF())
- return true;
- }
-
- else if (o->Type() == SIM_SHOT || o->Type() == SIM_DRONE) {
- Shot* s = (Shot*) o;
-
- if (s->GetIFF() > 0 && s->GetIFF() != GetIFF())
- return true;
- }
- }
-
- return false;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::ExecFrame(double seconds)
-{
- altitude_agl = -1.0e6f;
-
- // add random flickering effect:
- double flicker = 0.75 + (double) rand() / 8e4;
- if (flicker > 1) flicker = 1;
-
- if (flare) {
- flare->SetShade(flicker);
- }
- else if (beam) {
- Bolt* blob = (Bolt*) rep;
- blob->SetShade(flicker);
- offset -= (float) (seconds * 10);
- }
-
- if (Game::Paused())
- return;
-
- if (beam) {
- if (!first_frame) {
- if (life > 0) {
- life -= seconds;
-
- if (life < 0)
- life = 0;
- }
- }
- }
- else {
- origin = Location();
-
- if (!first_frame)
- Physical::ExecFrame(seconds);
- else
- Physical::ExecFrame(0);
-
- double len = design->length;
- if (len < 50) len = 50;
-
- if (!trail && life > 0 && design->life - life > 0.2) {
- if (design->trail.length()) {
- trail = new(__FILE__,__LINE__) Trail(design->trail_img, design->trail_length);
-
- if (design->trail_width > 0)
- trail->SetWidth(design->trail_width);
-
- if (design->trail_dim > 0)
- trail->SetDim(design->trail_dim);
-
- trail->AddPoint(Location() + Heading() * -100);
-
- Scene* scene = 0;
-
- if (rep)
- scene = rep->GetScene();
-
- if (scene)
- scene->AddGraphic(trail);
- }
- }
-
- if (trail)
- trail->AddPoint(Location());
-
- if (!armed) {
- SeekerAI* seeker = (SeekerAI*) dir;
-
- if (seeker && seeker->GetDelay() <= 0)
- armed = true;
- }
-
- // handle submunitions:
- else if (design->det_range > 0 && design->det_count > 0) {
- if (dir && !primary) {
- SeekerAI* seeker = (SeekerAI*) dir;
- SimObject* target = seeker->GetTarget();
-
- if (target) {
- double range = Point(Location() - target->Location()).length();
-
- if (range < design->det_range) {
- life = 0;
-
- Sim* sim = Sim::GetSim();
- WeaponDesign* child_design = WeaponDesign::Find(design->det_child);
-
- if (sim && child_design) {
- double spread = design->det_spread;
-
- Camera aim_cam;
- aim_cam.Clone(Cam());
- aim_cam.LookAt(target->Location());
-
- for (int i = 0; i < design->det_count; i++) {
- Shot* child = sim->CreateShot(Location(), aim_cam, child_design,
- owner, owner->GetRegion());
-
- child->SetCharge(child_design->charge);
-
- if (child_design->guided)
- child->SeekTarget(target, seeker->GetSubTarget());
-
- if (child_design->beam)
- child->SetBeamPoints(Location(), target->Location());
-
- if (i) aim_cam.LookAt(target->Location());
- aim_cam.Pitch(Random(-spread, spread));
- aim_cam.Yaw(Random(-spread, spread));
- }
- }
- }
- }
- }
- }
-
- if (flash && !first_frame)
- GRAPHIC_DESTROY(flash);
-
- if (thrust < design->thrust)
- thrust += (float) (seconds * 5.0e3);
- else
- thrust = design->thrust;
- }
-
- first_frame = 0;
-
- if (flare)
- flare->MoveTo(Location());
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::Disarm()
-{
- if (armed && !primary) {
- armed = false;
- delete dir;
- dir = 0;
- }
-}
-
-void
-Shot::Destroy()
-{
- life = 0;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::SetBeamPoints(const Point& from, const Point& to)
-{
- if (beam) {
- MoveTo(to);
- origin = from;
-
- if (sound) {
- sound->SetLocation(from);
- }
-
- if (rep) {
- Bolt* s = (Bolt*) rep;
- s->SetEndPoints(from, to);
-
- double len = Point(to - from).length() / 500;
- s->SetTextureOffset(offset, offset + len);
- }
- }
-
- if (flash) {
- flash->MoveTo(origin);
- }
-}
-
-// +--------------------------------------------------------------------+
-
-double
-Shot::AltitudeMSL() const
-{
- return Location().y;
-}
-
-double
-Shot::AltitudeAGL() const
-{
- if (altitude_agl < -1000) {
- Shot* pThis = (Shot*) this; // cast-away const
- Point loc = Location();
- Terrain* terrain = region->GetTerrain();
-
- if (terrain)
- pThis->altitude_agl = (float) (loc.y - terrain->Height(loc.x, loc.z));
-
- else
- pThis->altitude_agl = (float) loc.y;
-
- if (!_finite(altitude_agl)) {
- pThis->altitude_agl = 0.0f;
- }
- }
-
- return altitude_agl;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::Initialize()
-{
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::Close()
-{
-}
-
-// +--------------------------------------------------------------------+
-
-double
-Shot::Damage() const
-{
- double damage = 0;
-
- // beam damage based on length:
- if (beam) {
- double fade = 1;
-
- if (design) {
- // linear fade with distance:
- double len = Point(origin - Location()).length();
-
- if (len > design->min_range)
- fade = (design->length - len) / (design->length - design->min_range);
- }
-
- damage = base_damage * charge * fade * Game::FrameTime();
- }
-
- // energy wep damage based on time:
- else if (primary) {
- damage = base_damage * charge * life;
- }
-
- // missile damage is constant:
- else {
- damage = base_damage * charge;
- }
-
- return damage;
-}
-
-double
-Shot::Length() const
-{
- if (design)
- return design->length;
-
- return 500;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::Activate(Scene& scene)
-{
- SimObject::Activate(scene);
-
- if (trail)
- scene.AddGraphic(trail);
-
- if (flash)
- scene.AddGraphic(flash);
-
- if (flare)
- scene.AddGraphic(flare);
-
- if (first_frame) {
- if (design->sound_resource) {
- sound = design->sound_resource->Duplicate();
-
- if (sound) {
- long max_vol = AudioConfig::EfxVolume();
- long volume = -1000;
-
- if (volume > max_vol)
- volume = max_vol;
-
- if (beam) {
- sound->SetLocation(origin);
- sound->SetVolume(volume);
- sound->Play();
- }
- else {
- sound->SetLocation(Location());
- sound->SetVolume(volume);
- sound->Play();
- sound = 0; // fire and forget:
- }
- }
- }
- }
-}
-
-// +--------------------------------------------------------------------+
-
-void
-Shot::Deactivate(Scene& scene)
-{
- SimObject::Deactivate(scene);
-
- if (trail)
- scene.DelGraphic(trail);
-
- if (flash)
- scene.DelGraphic(flash);
-
- if (flare)
- scene.DelGraphic(flare);
-}
-
-// +--------------------------------------------------------------------+
-
-int
-Shot::GetIFF() const
-{
- return iff_code;
-}
-
-// +--------------------------------------------------------------------+
-
-Color
-Shot::MarkerColor() const
-{
- return Ship::IFFColor(GetIFF());
-}
-
-// +--------------------------------------------------------------------+
-
-const char*
-Shot::GetObserverName() const
-{
- return name;
-}
-
-// +--------------------------------------------------------------------+
-
-bool
-Shot::Update(SimObject* obj)
-{
- if (obj == (SimObject*) owner)
- owner = 0;
-
- return SimObserver::Update(obj);
-}
+/* Starshatter OpenSource Distribution
+ Copyright (c) 1997-2004, Destroyer Studios LLC.
+ All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name "Destroyer Studios" nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+ SUBSYSTEM: Stars.exe
+ FILE: Shot.cpp
+ AUTHOR: John DiCamillo
+
+
+ OVERVIEW
+ ========
+ Laser and Missile class
+*/
+
+#include "MemDebug.h"
+#include "Shot.h"
+#include "Weapon.h"
+#include "DriveSprite.h"
+#include "SeekerAI.h"
+#include "Sim.h"
+#include "Ship.h"
+#include "Trail.h"
+#include "Random.h"
+#include "AudioConfig.h"
+#include "TerrainRegion.h"
+#include "Terrain.h"
+
+#include "Game.h"
+#include "Bolt.h"
+#include "Sprite.h"
+#include "Solid.h"
+#include "Light.h"
+#include "Bitmap.h"
+#include "DataLoader.h"
+#include "Sound.h"
+
+// +--------------------------------------------------------------------+
+
+Shot::Shot(const Point& pos, const Camera& shot_cam, WeaponDesign* dsn, const Ship* ship)
+: first_frame(true), owner(ship), flash(0), flare(0), trail(0), sound(0), eta(0),
+charge(1.0f), design(dsn), offset(1.0e5f), altitude_agl(-1.0e6f), hit_target(false)
+{
+ obj_type = SimObject::SIM_SHOT;
+ type = design->type;
+ primary = design->primary;
+ beam = design->beam;
+ base_damage = design->damage;
+ armed = false;
+
+ radius = 10.0f;
+
+ if (primary || design->decoy_type || !design->guided) {
+ straight = true;
+ armed = true;
+ }
+
+ cam.Clone(shot_cam);
+
+ life = design->life;
+ velocity = cam.vpn() * (double) design->speed;
+
+ MoveTo(pos);
+
+ if (beam)
+ origin = pos + (shot_cam.vpn() * -design->length);
+
+ switch (design->graphic_type) {
+ case Graphic::BOLT: {
+ Bolt* s = new(__FILE__,__LINE__) Bolt(design->length, design->width, design->shot_img, 1);
+ s->SetDirection(cam.vpn());
+ rep = s;
+ }
+ break;
+
+ case Graphic::SPRITE: {
+ Sprite* s = 0;
+
+ if (design->animation)
+ s = new(__FILE__,__LINE__) DriveSprite(design->animation, design->anim_length);
+ else
+ s = new(__FILE__,__LINE__) DriveSprite(design->shot_img);
+
+ s->Scale((double) design->scale);
+ rep = s;
+ }
+ break;
+
+ case Graphic::SOLID: {
+ Solid* s = new(__FILE__,__LINE__) Solid;
+ s->UseModel(design->shot_model);
+ rep = s;
+
+ radius = rep->Radius();
+ }
+ break;
+ }
+
+ if (rep)
+ rep->MoveTo(pos);
+
+ light = 0;
+
+ if (design->light > 0) {
+ light = new(__FILE__,__LINE__) Light(design->light);
+ light->SetColor(design->light_color);
+ }
+
+ mass = design->mass;
+ drag = design->drag;
+ thrust = 0.0f;
+
+ dr_drg = design->roll_drag;
+ dp_drg = design->pitch_drag;
+ dy_drg = design->yaw_drag;
+
+ SetAngularRates((float) design->roll_rate, (float) design->pitch_rate, (float) design->yaw_rate);
+
+ if (design->flash_img != 0) {
+ flash = new(__FILE__,__LINE__) Sprite(design->flash_img);
+ flash->Scale((double) design->flash_scale);
+ flash->MoveTo(pos - cam.vpn() * design->length);
+ flash->SetLuminous(true);
+ }
+
+ if (design->flare_img != 0) {
+ flare = new(__FILE__,__LINE__) DriveSprite(design->flare_img);
+ flare->Scale((double) design->flare_scale);
+ flare->MoveTo(pos);
+ }
+
+ if (owner) {
+ iff_code = (BYTE) owner->GetIFF();
+ Observe((SimObject*) owner);
+ }
+
+ sprintf_s(name, "Shot(%s)", design->name.data());
+}
+
+// +--------------------------------------------------------------------+
+
+Shot::~Shot()
+{
+ GRAPHIC_DESTROY(flash);
+ GRAPHIC_DESTROY(flare);
+ GRAPHIC_DESTROY(trail);
+
+ if (sound) {
+ sound->Stop();
+ sound->Release();
+ }
+}
+
+// +--------------------------------------------------------------------+
+
+const char*
+Shot::DesignName() const
+{
+ return design->name;
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::SetCharge(float c)
+{
+ charge = c;
+
+ // trim beam life to amount of energy available:
+ if (beam)
+ life = design->life * charge / design->charge;
+}
+
+void
+Shot::SetFuse(double seconds)
+{
+ if (seconds > 0 && !beam)
+ life = seconds;
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::SeekTarget(SimObject* target, System* sub)
+{
+ if (dir && !primary) {
+ SeekerAI* seeker = (SeekerAI*) dir;
+ SimObject* old_target = seeker->GetTarget();
+
+ if (old_target->Type()==SimObject::SIM_SHIP) {
+ Ship* tgt_ship = (Ship*) old_target;
+ tgt_ship->DropThreat(this);
+ }
+ }
+
+ delete dir;
+ dir = 0;
+
+ if (target) {
+ SeekerAI* seeker = new(__FILE__,__LINE__) SeekerAI(this);
+ seeker->SetTarget(target, sub);
+ seeker->SetPursuit(design->guided);
+ seeker->SetDelay(1);
+
+ dir = seeker;
+
+ if (!primary && target->Type()==SimObject::SIM_SHIP) {
+ Ship* tgt_ship = (Ship*) target;
+ tgt_ship->AddThreat(this);
+ }
+ }
+}
+
+bool
+Shot::IsTracking(Ship* tgt) const
+{
+ return tgt && (GetTarget() == tgt);
+}
+
+SimObject*
+Shot::GetTarget() const
+{
+ if (dir) {
+ SeekerAI* seeker = (SeekerAI*) dir;
+
+ if (seeker->GetDelay() <= 0)
+ return seeker->GetTarget();
+ }
+
+ return 0;
+}
+
+bool
+Shot::IsFlak() const
+{
+ return design && design->flak;
+}
+
+// +--------------------------------------------------------------------+
+
+bool
+Shot::IsHostileTo(const SimObject* o) const
+{
+ if (o) {
+ if (o->Type() == SIM_SHIP) {
+ Ship* s = (Ship*) o;
+
+ if (s->IsRogue())
+ return true;
+
+ if (s->GetIFF() > 0 && s->GetIFF() != GetIFF())
+ return true;
+ }
+
+ else if (o->Type() == SIM_SHOT || o->Type() == SIM_DRONE) {
+ Shot* s = (Shot*) o;
+
+ if (s->GetIFF() > 0 && s->GetIFF() != GetIFF())
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::ExecFrame(double seconds)
+{
+ altitude_agl = -1.0e6f;
+
+ // add random flickering effect:
+ double flicker = 0.75 + (double) rand() / 8e4;
+ if (flicker > 1) flicker = 1;
+
+ if (flare) {
+ flare->SetShade(flicker);
+ }
+ else if (beam) {
+ Bolt* blob = (Bolt*) rep;
+ blob->SetShade(flicker);
+ offset -= (float) (seconds * 10);
+ }
+
+ if (Game::Paused())
+ return;
+
+ if (beam) {
+ if (!first_frame) {
+ if (life > 0) {
+ life -= seconds;
+
+ if (life < 0)
+ life = 0;
+ }
+ }
+ }
+ else {
+ origin = Location();
+
+ if (!first_frame)
+ Physical::ExecFrame(seconds);
+ else
+ Physical::ExecFrame(0);
+
+ double len = design->length;
+ if (len < 50) len = 50;
+
+ if (!trail && life > 0 && design->life - life > 0.2) {
+ if (design->trail.length()) {
+ trail = new(__FILE__,__LINE__) Trail(design->trail_img, design->trail_length);
+
+ if (design->trail_width > 0)
+ trail->SetWidth(design->trail_width);
+
+ if (design->trail_dim > 0)
+ trail->SetDim(design->trail_dim);
+
+ trail->AddPoint(Location() + Heading() * -100);
+
+ Scene* scene = 0;
+
+ if (rep)
+ scene = rep->GetScene();
+
+ if (scene)
+ scene->AddGraphic(trail);
+ }
+ }
+
+ if (trail)
+ trail->AddPoint(Location());
+
+ if (!armed) {
+ SeekerAI* seeker = (SeekerAI*) dir;
+
+ if (seeker && seeker->GetDelay() <= 0)
+ armed = true;
+ }
+
+ // handle submunitions:
+ else if (design->det_range > 0 && design->det_count > 0) {
+ if (dir && !primary) {
+ SeekerAI* seeker = (SeekerAI*) dir;
+ SimObject* target = seeker->GetTarget();
+
+ if (target) {
+ double range = Point(Location() - target->Location()).length();
+
+ if (range < design->det_range) {
+ life = 0;
+
+ Sim* sim = Sim::GetSim();
+ WeaponDesign* child_design = WeaponDesign::Find(design->det_child);
+
+ if (sim && child_design) {
+ double spread = design->det_spread;
+
+ Camera aim_cam;
+ aim_cam.Clone(Cam());
+ aim_cam.LookAt(target->Location());
+
+ for (int i = 0; i < design->det_count; i++) {
+ Shot* child = sim->CreateShot(Location(), aim_cam, child_design,
+ owner, owner->GetRegion());
+
+ child->SetCharge(child_design->charge);
+
+ if (child_design->guided)
+ child->SeekTarget(target, seeker->GetSubTarget());
+
+ if (child_design->beam)
+ child->SetBeamPoints(Location(), target->Location());
+
+ if (i) aim_cam.LookAt(target->Location());
+ aim_cam.Pitch(Random(-spread, spread));
+ aim_cam.Yaw(Random(-spread, spread));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (flash && !first_frame)
+ GRAPHIC_DESTROY(flash);
+
+ if (thrust < design->thrust)
+ thrust += (float) (seconds * 5.0e3);
+ else
+ thrust = design->thrust;
+ }
+
+ first_frame = 0;
+
+ if (flare)
+ flare->MoveTo(Location());
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::Disarm()
+{
+ if (armed && !primary) {
+ armed = false;
+ delete dir;
+ dir = 0;
+ }
+}
+
+void
+Shot::Destroy()
+{
+ life = 0;
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::SetBeamPoints(const Point& from, const Point& to)
+{
+ if (beam) {
+ MoveTo(to);
+ origin = from;
+
+ if (sound) {
+ sound->SetLocation(from);
+ }
+
+ if (rep) {
+ Bolt* s = (Bolt*) rep;
+ s->SetEndPoints(from, to);
+
+ double len = Point(to - from).length() / 500;
+ s->SetTextureOffset(offset, offset + len);
+ }
+ }
+
+ if (flash) {
+ flash->MoveTo(origin);
+ }
+}
+
+// +--------------------------------------------------------------------+
+
+double
+Shot::AltitudeMSL() const
+{
+ return Location().y;
+}
+
+double
+Shot::AltitudeAGL() const
+{
+ if (altitude_agl < -1000) {
+ Shot* pThis = (Shot*) this; // cast-away const
+ Point loc = Location();
+ Terrain* terrain = region->GetTerrain();
+
+ if (terrain)
+ pThis->altitude_agl = (float) (loc.y - terrain->Height(loc.x, loc.z));
+
+ else
+ pThis->altitude_agl = (float) loc.y;
+
+ if (!_finite(altitude_agl)) {
+ pThis->altitude_agl = 0.0f;
+ }
+ }
+
+ return altitude_agl;
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::Initialize()
+{
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::Close()
+{
+}
+
+// +--------------------------------------------------------------------+
+
+double
+Shot::Damage() const
+{
+ double damage = 0;
+
+ // beam damage based on length:
+ if (beam) {
+ double fade = 1;
+
+ if (design) {
+ // linear fade with distance:
+ double len = Point(origin - Location()).length();
+
+ if (len > design->min_range)
+ fade = (design->length - len) / (design->length - design->min_range);
+ }
+
+ damage = base_damage * charge * fade * Game::FrameTime();
+ }
+
+ // energy wep damage based on time:
+ else if (primary) {
+ damage = base_damage * charge * life;
+ }
+
+ // missile damage is constant:
+ else {
+ damage = base_damage * charge;
+ }
+
+ return damage;
+}
+
+double
+Shot::Length() const
+{
+ if (design)
+ return design->length;
+
+ return 500;
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::Activate(Scene& scene)
+{
+ SimObject::Activate(scene);
+
+ if (trail)
+ scene.AddGraphic(trail);
+
+ if (flash)
+ scene.AddGraphic(flash);
+
+ if (flare)
+ scene.AddGraphic(flare);
+
+ if (first_frame) {
+ if (design->sound_resource) {
+ sound = design->sound_resource->Duplicate();
+
+ if (sound) {
+ long max_vol = AudioConfig::EfxVolume();
+ long volume = -1000;
+
+ if (volume > max_vol)
+ volume = max_vol;
+
+ if (beam) {
+ sound->SetLocation(origin);
+ sound->SetVolume(volume);
+ sound->Play();
+ }
+ else {
+ sound->SetLocation(Location());
+ sound->SetVolume(volume);
+ sound->Play();
+ sound = 0; // fire and forget:
+ }
+ }
+ }
+ }
+}
+
+// +--------------------------------------------------------------------+
+
+void
+Shot::Deactivate(Scene& scene)
+{
+ SimObject::Deactivate(scene);
+
+ if (trail)
+ scene.DelGraphic(trail);
+
+ if (flash)
+ scene.DelGraphic(flash);
+
+ if (flare)
+ scene.DelGraphic(flare);
+}
+
+// +--------------------------------------------------------------------+
+
+int
+Shot::GetIFF() const
+{
+ return iff_code;
+}
+
+// +--------------------------------------------------------------------+
+
+Color
+Shot::MarkerColor() const
+{
+ return Ship::IFFColor(GetIFF());
+}
+
+// +--------------------------------------------------------------------+
+
+const char*
+Shot::GetObserverName() const
+{
+ return name;
+}
+
+// +--------------------------------------------------------------------+
+
+bool
+Shot::Update(SimObject* obj)
+{
+ if (obj == (SimObject*) owner)
+ owner = 0;
+
+ return SimObserver::Update(obj);
+}