From d17521c8b9085a91d08fecfd0b51bbbf7b1dccac Mon Sep 17 00:00:00 2001 From: "milo24x7@gmail.com" Date: Sun, 7 Jul 2013 22:08:49 +0000 Subject: Updated open source license declaration and fixed some formatting issues. --- Stars45/Shot.cpp | 1276 +++++++++++++++++++++++++++--------------------------- 1 file changed, 650 insertions(+), 626 deletions(-) (limited to 'Stars45/Shot.cpp') 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); +} -- cgit v1.1