summaryrefslogtreecommitdiffhomepage
path: root/Stars45/Weapon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Stars45/Weapon.cpp')
-rw-r--r--Stars45/Weapon.cpp1704
1 files changed, 852 insertions, 852 deletions
diff --git a/Stars45/Weapon.cpp b/Stars45/Weapon.cpp
index 163a71a..93a7da7 100644
--- a/Stars45/Weapon.cpp
+++ b/Stars45/Weapon.cpp
@@ -1,15 +1,15 @@
/* Project Starshatter 4.5
- Destroyer Studios LLC
- Copyright © 1997-2004. All Rights Reserved.
+ Destroyer Studios LLC
+ Copyright © 1997-2004. All Rights Reserved.
- SUBSYSTEM: Stars.exe
- FILE: Weapon.cpp
- AUTHOR: John DiCamillo
+ SUBSYSTEM: Stars.exe
+ FILE: Weapon.cpp
+ AUTHOR: John DiCamillo
- OVERVIEW
- ========
- Weapon class
+ OVERVIEW
+ ========
+ Weapon class
*/
#include "MemDebug.h"
@@ -31,132 +31,132 @@
// +----------------------------------------------------------------------+
Weapon::Weapon(WeaponDesign* d, int nmuz, Vec3* muzzles, double az, double el)
- : System(WEAPON, d->type, d->name, d->value,
- d->capacity, d->capacity, d->recharge_rate),
- design(d), group(d->group), ammo(-1), ripple_count(0),
- aim_azimuth((float) az), aim_elevation((float) el),
- old_azimuth(0.0f), old_elevation(0.0f), aim_time(0),
- enabled(true), refire(0.0f),
- mass(d->carry_mass), resist(d->carry_resist),
- guided(d->guided), shot_speed(d->speed),
- active_barrel(0), locked(false), centered(false), firing(false), blocked(false),
- index(0), target(0), subtarget(0), beams(0), orders(MANUAL),
- control(SINGLE_FIRE), sweep(SWEEP_TIGHT), turret(0), turret_base(0)
+: System(WEAPON, d->type, d->name, d->value,
+d->capacity, d->capacity, d->recharge_rate),
+design(d), group(d->group), ammo(-1), ripple_count(0),
+aim_azimuth((float) az), aim_elevation((float) el),
+old_azimuth(0.0f), old_elevation(0.0f), aim_time(0),
+enabled(true), refire(0.0f),
+mass(d->carry_mass), resist(d->carry_resist),
+guided(d->guided), shot_speed(d->speed),
+active_barrel(0), locked(false), centered(false), firing(false), blocked(false),
+index(0), target(0), subtarget(0), beams(0), orders(MANUAL),
+control(SINGLE_FIRE), sweep(SWEEP_TIGHT), turret(0), turret_base(0)
{
- ZeroMemory(visible_stores, sizeof(visible_stores));
+ ZeroMemory(visible_stores, sizeof(visible_stores));
- if (design->primary)
- abrv = Game::GetText("sys.weapon.primary.abrv");
- else
- abrv = Game::GetText("sys.weapon.secondary.abrv");
+ if (design->primary)
+ abrv = Game::GetText("sys.weapon.primary.abrv");
+ else
+ abrv = Game::GetText("sys.weapon.secondary.abrv");
- nbarrels = nmuz;
+ nbarrels = nmuz;
- if (nbarrels > MAX_BARRELS)
- nbarrels = MAX_BARRELS;
+ if (nbarrels > MAX_BARRELS)
+ nbarrels = MAX_BARRELS;
- if (nbarrels == 0 && design->nbarrels > 0) {
- nbarrels = design->nbarrels;
+ if (nbarrels == 0 && design->nbarrels > 0) {
+ nbarrels = design->nbarrels;
- for (int i = 0; i < nbarrels; i++)
- muzzle_pts[i] = rel_pts[i] = design->muzzle_pts[i] * design->scale;
+ for (int i = 0; i < nbarrels; i++)
+ muzzle_pts[i] = rel_pts[i] = design->muzzle_pts[i] * design->scale;
- ammo = design->ammo * nbarrels;
- }
- else if (nbarrels == 1 && design->nstores > 0) {
- nbarrels = design->nstores;
+ ammo = design->ammo * nbarrels;
+ }
+ else if (nbarrels == 1 && design->nstores > 0) {
+ nbarrels = design->nstores;
- for (int i = 0; i < nbarrels; i++)
- muzzle_pts[i] = rel_pts[i] = (muzzles[0] + design->attachments[i]);
+ for (int i = 0; i < nbarrels; i++)
+ muzzle_pts[i] = rel_pts[i] = (muzzles[0] + design->attachments[i]);
- ammo = nbarrels;
- }
- else {
- for (int i = 0; i < nbarrels; i++)
- muzzle_pts[i] = rel_pts[i] = muzzles[i];
+ ammo = nbarrels;
+ }
+ else {
+ for (int i = 0; i < nbarrels; i++)
+ muzzle_pts[i] = rel_pts[i] = muzzles[i];
- ammo = design->ammo * nbarrels;
- }
+ ammo = design->ammo * nbarrels;
+ }
- if (design->syncro)
- active_barrel = -1;
+ if (design->syncro)
+ active_barrel = -1;
- emcon_power[0] = 0;
- emcon_power[1] = 0;
- emcon_power[2] = 100;
+ emcon_power[0] = 0;
+ emcon_power[1] = 0;
+ emcon_power[2] = 100;
- aim_az_max = design->aim_az_max;
- aim_az_min = design->aim_az_min;
- aim_az_rest = design->aim_az_rest;
+ aim_az_max = design->aim_az_max;
+ aim_az_min = design->aim_az_min;
+ aim_az_rest = design->aim_az_rest;
- aim_el_max = design->aim_el_max;
- aim_el_min = design->aim_el_min;
- aim_el_rest = design->aim_el_rest;
+ aim_el_max = design->aim_el_max;
+ aim_el_min = design->aim_el_min;
+ aim_el_rest = design->aim_el_rest;
}
// +----------------------------------------------------------------------+
Weapon::Weapon(const Weapon& w)
- : System(w), design(w.design), ammo(-1), ripple_count(0),
- enabled(true), refire(0.0f),
- mass(w.mass), resist(w.resist),
- aim_azimuth(w.aim_azimuth), aim_elevation(w.aim_elevation),
- old_azimuth(0.0f), old_elevation(0.0f), aim_time(0),
- guided(w.guided), shot_speed(w.shot_speed),
- active_barrel(0), locked(false), centered(false), firing(false), blocked(false),
- target(0), subtarget(0), beams(0), orders(MANUAL),
- control(SINGLE_FIRE), sweep(SWEEP_TIGHT), group(w.group),
- aim_az_max(w.aim_az_max), aim_az_min(w.aim_az_min), aim_az_rest(w.aim_az_rest),
- aim_el_max(w.aim_el_max), aim_el_min(w.aim_el_min), aim_el_rest(w.aim_el_rest),
- turret(0), turret_base(0)
+: System(w), design(w.design), ammo(-1), ripple_count(0),
+enabled(true), refire(0.0f),
+mass(w.mass), resist(w.resist),
+aim_azimuth(w.aim_azimuth), aim_elevation(w.aim_elevation),
+old_azimuth(0.0f), old_elevation(0.0f), aim_time(0),
+guided(w.guided), shot_speed(w.shot_speed),
+active_barrel(0), locked(false), centered(false), firing(false), blocked(false),
+target(0), subtarget(0), beams(0), orders(MANUAL),
+control(SINGLE_FIRE), sweep(SWEEP_TIGHT), group(w.group),
+aim_az_max(w.aim_az_max), aim_az_min(w.aim_az_min), aim_az_rest(w.aim_az_rest),
+aim_el_max(w.aim_el_max), aim_el_min(w.aim_el_min), aim_el_rest(w.aim_el_rest),
+turret(0), turret_base(0)
{
- Mount(w);
- ZeroMemory(visible_stores, sizeof(visible_stores));
+ Mount(w);
+ ZeroMemory(visible_stores, sizeof(visible_stores));
- nbarrels = w.nbarrels;
-
- for (int i = 0; i < nbarrels; i++) {
- muzzle_pts[i] = rel_pts[i] = w.muzzle_pts[i];
- }
+ nbarrels = w.nbarrels;
- ammo = design->ammo * nbarrels;
+ for (int i = 0; i < nbarrels; i++) {
+ muzzle_pts[i] = rel_pts[i] = w.muzzle_pts[i];
+ }
- if (design->syncro)
- active_barrel = -1;
+ ammo = design->ammo * nbarrels;
- if (design->beam) {
- beams = new(__FILE__,__LINE__) Shot* [nbarrels];
- ZeroMemory(beams, sizeof(Shot*) * nbarrels);
- }
+ if (design->syncro)
+ active_barrel = -1;
- if (aim_az_rest >= 2*PI)
- aim_az_rest = design->aim_az_rest;
+ if (design->beam) {
+ beams = new(__FILE__,__LINE__) Shot* [nbarrels];
+ ZeroMemory(beams, sizeof(Shot*) * nbarrels);
+ }
- if (aim_el_rest >= 2*PI)
- aim_el_rest = design->aim_el_rest;
+ if (aim_az_rest >= 2*PI)
+ aim_az_rest = design->aim_az_rest;
+
+ if (aim_el_rest >= 2*PI)
+ aim_el_rest = design->aim_el_rest;
}
// +--------------------------------------------------------------------+
Weapon::~Weapon()
{
- if (beams) {
- for (int i = 0; i < nbarrels; i++) {
- if (beams[i]) {
- Ignore(beams[i]);
- delete beams[i];
- beams[i] = 0;
- }
- }
-
- delete [] beams;
- }
-
- GRAPHIC_DESTROY(turret);
- GRAPHIC_DESTROY(turret_base);
-
- for (int i = 0; i < MAX_BARRELS; i++)
- GRAPHIC_DESTROY(visible_stores[i]);
+ if (beams) {
+ for (int i = 0; i < nbarrels; i++) {
+ if (beams[i]) {
+ Ignore(beams[i]);
+ delete beams[i];
+ beams[i] = 0;
+ }
+ }
+
+ delete [] beams;
+ }
+
+ GRAPHIC_DESTROY(turret);
+ GRAPHIC_DESTROY(turret_base);
+
+ for (int i = 0; i < MAX_BARRELS; i++)
+ GRAPHIC_DESTROY(visible_stores[i]);
}
// +--------------------------------------------------------------------+
@@ -164,37 +164,37 @@ Weapon::~Weapon()
bool
Weapon::IsPrimary() const
{
- return design->primary;
+ return design->primary;
}
bool
Weapon::IsDrone() const
{
- return design->drone;
+ return design->drone;
}
bool
Weapon::IsDecoy() const
{
- return design->decoy_type != 0;
+ return design->decoy_type != 0;
}
bool
Weapon::IsProbe() const
{
- return design->probe != 0;
+ return design->probe != 0;
}
bool
Weapon::IsMissile() const
{
- return !design->primary;
+ return !design->primary;
}
bool
Weapon::IsBeam() const
{
- return design->beam;
+ return design->beam;
}
// +--------------------------------------------------------------------+
@@ -202,10 +202,10 @@ Weapon::IsBeam() const
Shot*
Weapon::GetBeam(int i)
{
- if (beams && i >= 0 && i < nbarrels)
- return beams[i];
+ if (beams && i >= 0 && i < nbarrels)
+ return beams[i];
- return 0;
+ return 0;
}
// +--------------------------------------------------------------------+
@@ -213,74 +213,74 @@ Weapon::GetBeam(int i)
void
Weapon::SetOwner(Ship* s)
{
- ship = s;
-
- if (design->turret_model) {
- Solid* t = new(__FILE__,__LINE__) Solid;
- t->UseModel(design->turret_model);
- turret = t;
- }
-
- if (design->turret_base_model) {
- Solid* t = new(__FILE__,__LINE__) Solid;
- t->UseModel(design->turret_base_model);
- turret_base = t;
- }
-
- if (!design->primary &&
- design->visible_stores &&
- ammo == nbarrels &&
- design->shot_model != 0)
- {
- for (int i = 0; i < nbarrels; i++) {
- Solid* s = new(__FILE__,__LINE__) Solid;
- s->UseModel(design->shot_model);
-
- visible_stores[i] = s;
- }
- }
+ ship = s;
+
+ if (design->turret_model) {
+ Solid* t = new(__FILE__,__LINE__) Solid;
+ t->UseModel(design->turret_model);
+ turret = t;
+ }
+
+ if (design->turret_base_model) {
+ Solid* t = new(__FILE__,__LINE__) Solid;
+ t->UseModel(design->turret_base_model);
+ turret_base = t;
+ }
+
+ if (!design->primary &&
+ design->visible_stores &&
+ ammo == nbarrels &&
+ design->shot_model != 0)
+ {
+ for (int i = 0; i < nbarrels; i++) {
+ Solid* s = new(__FILE__,__LINE__) Solid;
+ s->UseModel(design->shot_model);
+
+ visible_stores[i] = s;
+ }
+ }
}
Solid*
Weapon::GetTurret()
{
- return turret;
+ return turret;
}
Solid*
Weapon::GetTurretBase()
{
- return turret_base;
+ return turret_base;
}
Solid*
Weapon::GetVisibleStore(int i)
{
- if (i >= 0 && i < MAX_BARRELS)
- return visible_stores[i];
+ if (i >= 0 && i < MAX_BARRELS)
+ return visible_stores[i];
- return 0;
+ return 0;
}
void
Weapon::SetAmmo(int a)
{
- if (a >= 0) {
- if (active_barrel >= 0 && design->visible_stores) {
- while (a < ammo) {
- if (active_barrel >= nbarrels)
- active_barrel = 0;
-
- if (visible_stores[active_barrel]) {
- GRAPHIC_DESTROY(visible_stores[active_barrel]);
- active_barrel++;
- ammo--;
- }
- }
- }
-
- ammo = a;
- }
+ if (a >= 0) {
+ if (active_barrel >= 0 && design->visible_stores) {
+ while (a < ammo) {
+ if (active_barrel >= nbarrels)
+ active_barrel = 0;
+
+ if (visible_stores[active_barrel]) {
+ GRAPHIC_DESTROY(visible_stores[active_barrel]);
+ active_barrel++;
+ ammo--;
+ }
+ }
+ }
+
+ ammo = a;
+ }
}
// +--------------------------------------------------------------------+
@@ -288,79 +288,79 @@ Weapon::SetAmmo(int a)
void
Weapon::ExecFrame(double seconds)
{
- System::ExecFrame(seconds);
-
- if (refire > 0)
- refire -= (float) seconds;
-
- locked = false;
- centered = false;
-
- if (!ship)
- return;
-
- if (orders == POINT_DEFENSE && enabled)
- SelectTarget();
-
- if (beams && !target) {
- for (int i = 0; i < nbarrels; i++) {
- if (beams[i]) {
- // aim beam straight:
- Aim();
- SetBeamPoints(false);
- return;
- }
- }
- }
-
- if (design->self_aiming) {
- Track(target, subtarget);
- }
- else if (turret) {
- ZeroAim();
- }
-
- if (ship->CheckFire())
- return;
-
- // aim beam at target:
- bool aim_beams = false;
-
- if (beams) {
- for (int i = 0; i < nbarrels; i++) {
- if (beams[i]) {
- aim_beams = true;
- SetBeamPoints(true);
- break;
- }
- }
- }
-
- if (!aim_beams) {
- if (ripple_count > 0) {
- if (Fire())
- ripple_count--;
- }
-
- else if (locked && !blocked) {
- if (!ship->IsHostileTo(target))
- return;
-
- if (orders == AUTO && centered) {
- if (energy >= design->charge &&
- (ammo < 0 || target && target->Integrity() >= 1) &&
- objective.length() < design->max_range)
- Fire();
- }
-
- else if (orders == POINT_DEFENSE) {
- if (energy >= design->min_charge &&
- (ammo < 0 || target && target->Integrity() >= 1) &&
- objective.length() < design->max_range)
- Fire();
- }
- }
- }
+ System::ExecFrame(seconds);
+
+ if (refire > 0)
+ refire -= (float) seconds;
+
+ locked = false;
+ centered = false;
+
+ if (!ship)
+ return;
+
+ if (orders == POINT_DEFENSE && enabled)
+ SelectTarget();
+
+ if (beams && !target) {
+ for (int i = 0; i < nbarrels; i++) {
+ if (beams[i]) {
+ // aim beam straight:
+ Aim();
+ SetBeamPoints(false);
+ return;
+ }
+ }
+ }
+
+ if (design->self_aiming) {
+ Track(target, subtarget);
+ }
+ else if (turret) {
+ ZeroAim();
+ }
+
+ if (ship->CheckFire())
+ return;
+
+ // aim beam at target:
+ bool aim_beams = false;
+
+ if (beams) {
+ for (int i = 0; i < nbarrels; i++) {
+ if (beams[i]) {
+ aim_beams = true;
+ SetBeamPoints(true);
+ break;
+ }
+ }
+ }
+
+ if (!aim_beams) {
+ if (ripple_count > 0) {
+ if (Fire())
+ ripple_count--;
+ }
+
+ else if (locked && !blocked) {
+ if (!ship->IsHostileTo(target))
+ return;
+
+ if (orders == AUTO && centered) {
+ if (energy >= design->charge &&
+ (ammo < 0 || target && target->Integrity() >= 1) &&
+ objective.length() < design->max_range)
+ Fire();
+ }
+
+ else if (orders == POINT_DEFENSE) {
+ if (energy >= design->min_charge &&
+ (ammo < 0 || target && target->Integrity() >= 1) &&
+ objective.length() < design->max_range)
+ Fire();
+ }
+ }
+ }
}
// +----------------------------------------------------------------------+
@@ -368,23 +368,23 @@ Weapon::ExecFrame(double seconds)
void
Weapon::Distribute(double delivered_energy, double seconds)
{
- if (UsesWatts()) {
- if (seconds < 0.01)
- seconds = 0.01;
+ if (UsesWatts()) {
+ if (seconds < 0.01)
+ seconds = 0.01;
- // convert Joules to Watts:
- energy = (float) (delivered_energy/seconds);
- }
+ // convert Joules to Watts:
+ energy = (float) (delivered_energy/seconds);
+ }
- else if (!Game::Paused()) {
- energy += (float) (delivered_energy * 1.25);
+ else if (!Game::Paused()) {
+ energy += (float) (delivered_energy * 1.25);
- if (energy > capacity)
- energy = capacity;
+ if (energy > capacity)
+ energy = capacity;
- else if (energy < 0)
- energy = 0.0f;
- }
+ else if (energy < 0)
+ energy = 0.0f;
+ }
}
@@ -393,25 +393,25 @@ Weapon::Distribute(double delivered_energy, double seconds)
bool
Weapon::Update(SimObject* obj)
{
- if (obj == target) {
- target = 0;
- }
+ if (obj == target) {
+ target = 0;
+ }
- else if (beams) {
- for (int i = 0; i < nbarrels; i++)
- if (obj == beams[i])
- beams[i] = 0;
- }
+ else if (beams) {
+ for (int i = 0; i < nbarrels; i++)
+ if (obj == beams[i])
+ beams[i] = 0;
+ }
- return SimObserver::Update(obj);
+ return SimObserver::Update(obj);
}
const char*
Weapon::GetObserverName() const
{
- static char name[256];
- sprintf(name, "Weapon %s", design->name);
- return name;
+ static char name[256];
+ sprintf(name, "Weapon %s", design->name);
+ return name;
}
// +--------------------------------------------------------------------+
@@ -419,22 +419,22 @@ Weapon::GetObserverName() const
void
Weapon::SetFiringOrders(int o)
{
- if (o >= MANUAL && o <= POINT_DEFENSE)
- orders = o;
+ if (o >= MANUAL && o <= POINT_DEFENSE)
+ orders = o;
}
void
Weapon::SetControlMode(int m)
{
- if (m >= SINGLE_FIRE && m <= SALVO_FIRE)
- control = m;
+ if (m >= SINGLE_FIRE && m <= SALVO_FIRE)
+ control = m;
}
void
Weapon::SetSweep(int s)
{
- if (s >= SWEEP_NONE && s <= SWEEP_WIDE)
- sweep = s;
+ if (s >= SWEEP_NONE && s <= SWEEP_WIDE)
+ sweep = s;
}
// +--------------------------------------------------------------------+
@@ -442,7 +442,7 @@ Weapon::SetSweep(int s)
bool
Weapon::CanTarget(DWORD classification) const
{
- return (design->target_type & classification) ? true : false;
+ return (design->target_type & classification) ? true : false;
}
// +--------------------------------------------------------------------+
@@ -450,44 +450,44 @@ Weapon::CanTarget(DWORD classification) const
void
Weapon::SetTarget(SimObject* targ, System* sub)
{
- // check self targeting:
- if (targ == (SimObject*) ship)
- return;
-
- // check target class filter:
- if (targ) {
- switch (targ->Type()) {
- case SimObject::SIM_SHIP: {
- Ship* tgt_ship = (Ship*) targ;
-
- if ((tgt_ship->Class() & design->target_type) == 0)
- return;
- }
- break;
-
- case SimObject::SIM_SHOT:
- return;
-
- case SimObject::SIM_DRONE: {
- if ((design->target_type & Ship::DRONE) == 0)
- return;
- }
- break;
-
- default:
- return;
- }
- }
-
- // if ok, target this object:
- if (target != targ) {
- target = targ;
-
- if (target)
- Observe(target);
- }
-
- subtarget = sub;
+ // check self targeting:
+ if (targ == (SimObject*) ship)
+ return;
+
+ // check target class filter:
+ if (targ) {
+ switch (targ->Type()) {
+ case SimObject::SIM_SHIP: {
+ Ship* tgt_ship = (Ship*) targ;
+
+ if ((tgt_ship->Class() & design->target_type) == 0)
+ return;
+ }
+ break;
+
+ case SimObject::SIM_SHOT:
+ return;
+
+ case SimObject::SIM_DRONE: {
+ if ((design->target_type & Ship::DRONE) == 0)
+ return;
+ }
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ // if ok, target this object:
+ if (target != targ) {
+ target = targ;
+
+ if (target)
+ Observe(target);
+ }
+
+ subtarget = sub;
}
// +--------------------------------------------------------------------+
@@ -495,78 +495,78 @@ Weapon::SetTarget(SimObject* targ, System* sub)
void
Weapon::SelectTarget()
{
- bool select_locked = false;
- SimObject* targ = 0;
- double dist = 1e9;
- double az = 0;
- double el = 0;
-
- if (ammo && enabled && (availability > crit_level)) {
- ZeroAim();
-
- ListIter<Contact> contact = ship->ContactList();
-
- // lock onto any threatening shots first (if we can):
- if (design->target_type & Ship::DRONE) {
- while (++contact) {
- Shot* c_shot = contact->GetShot();
-
- if (c_shot && contact->Threat(ship)) {
-
- // distance from self to target:
- double distance = Point(c_shot->Location() - muzzle_pts[0]).length();
-
- if (distance > design->min_range &&
- distance < design->max_range &&
- distance < dist) {
- // check aim basket:
- select_locked = CanLockPoint(c_shot->Location(), az, el);
-
- if (select_locked) {
- targ = c_shot;
- dist = distance;
- }
- }
- }
- }
- }
-
- // lock onto a threatening ship only if it is (much) closer:
- dist *= 0.2;
- contact.reset();
- while (++contact) {
- Ship* c_ship = contact->GetShip();
-
- if (!c_ship) continue;
-
- // can we lock onto this target?
- if ((c_ship->IsRogue() || c_ship->GetIFF() > 0 && c_ship->GetIFF() != ship->GetIFF()) &&
- (c_ship->Class() & design->target_type) &&
- c_ship->Weapons().size() > 0) {
- // distance from self to target:
- double distance = Point(c_ship->Location() - muzzle_pts[0]).length();
-
- if (distance < design->max_range && distance < dist) {
- // check aim basket:
- select_locked = CanLockPoint(c_ship->Location(), az, el);
-
- if (select_locked) {
- targ = c_ship;
- dist = distance;
- }
- }
- }
- }
- }
-
- if (!ammo || !enabled) {
- SetTarget(0,0);
- locked = false;
- }
-
- else {
- SetTarget(targ, 0);
- }
+ bool select_locked = false;
+ SimObject* targ = 0;
+ double dist = 1e9;
+ double az = 0;
+ double el = 0;
+
+ if (ammo && enabled && (availability > crit_level)) {
+ ZeroAim();
+
+ ListIter<Contact> contact = ship->ContactList();
+
+ // lock onto any threatening shots first (if we can):
+ if (design->target_type & Ship::DRONE) {
+ while (++contact) {
+ Shot* c_shot = contact->GetShot();
+
+ if (c_shot && contact->Threat(ship)) {
+
+ // distance from self to target:
+ double distance = Point(c_shot->Location() - muzzle_pts[0]).length();
+
+ if (distance > design->min_range &&
+ distance < design->max_range &&
+ distance < dist) {
+ // check aim basket:
+ select_locked = CanLockPoint(c_shot->Location(), az, el);
+
+ if (select_locked) {
+ targ = c_shot;
+ dist = distance;
+ }
+ }
+ }
+ }
+ }
+
+ // lock onto a threatening ship only if it is (much) closer:
+ dist *= 0.2;
+ contact.reset();
+ while (++contact) {
+ Ship* c_ship = contact->GetShip();
+
+ if (!c_ship) continue;
+
+ // can we lock onto this target?
+ if ((c_ship->IsRogue() || c_ship->GetIFF() > 0 && c_ship->GetIFF() != ship->GetIFF()) &&
+ (c_ship->Class() & design->target_type) &&
+ c_ship->Weapons().size() > 0) {
+ // distance from self to target:
+ double distance = Point(c_ship->Location() - muzzle_pts[0]).length();
+
+ if (distance < design->max_range && distance < dist) {
+ // check aim basket:
+ select_locked = CanLockPoint(c_ship->Location(), az, el);
+
+ if (select_locked) {
+ targ = c_ship;
+ dist = distance;
+ }
+ }
+ }
+ }
+ }
+
+ if (!ammo || !enabled) {
+ SetTarget(0,0);
+ locked = false;
+ }
+
+ else {
+ SetTarget(targ, 0);
+ }
}
// +--------------------------------------------------------------------+
@@ -574,15 +574,15 @@ Weapon::SelectTarget()
int
Weapon::Track(SimObject* targ, System* sub)
{
- if (ammo && enabled && (availability > crit_level)) {
- firing = 0;
- Aim();
- }
- else if (turret) {
- ZeroAim();
- }
-
- return locked;
+ if (ammo && enabled && (availability > crit_level)) {
+ firing = 0;
+ Aim();
+ }
+ else if (turret) {
+ ZeroAim();
+ }
+
+ return locked;
}
// +--------------------------------------------------------------------+
@@ -590,75 +590,75 @@ Weapon::Track(SimObject* targ, System* sub)
Shot*
Weapon::Fire()
{
- if (Game::Paused())
- return 0;
+ if (Game::Paused())
+ return 0;
- if (ship && ship->CheckFire())
- return 0;
+ if (ship && ship->CheckFire())
+ return 0;
- if (ship->IsStarship() && target && !centered)
- return 0;
+ if (ship->IsStarship() && target && !centered)
+ return 0;
- if (beams && active_barrel >= 0 && active_barrel < nbarrels && beams[active_barrel])
- return 0;
+ if (beams && active_barrel >= 0 && active_barrel < nbarrels && beams[active_barrel])
+ return 0;
- Shot* shot = 0;
+ Shot* shot = 0;
- if (ammo && enabled &&
- (refire <= 0) && (energy > design->min_charge) &&
- (availability > crit_level)) {
+ if (ammo && enabled &&
+ (refire <= 0) && (energy > design->min_charge) &&
+ (availability > crit_level)) {
- refire = design->refire_delay;
+ refire = design->refire_delay;
- NetGame* net_game = NetGame::GetInstance();
- bool net_client = net_game ? net_game->IsClient() : false;
+ NetGame* net_game = NetGame::GetInstance();
+ bool net_client = net_game ? net_game->IsClient() : false;
- // all barrels
- if (active_barrel < 0) {
- if (net_client || IsPrimary())
- NetUtil::SendWepTrigger(this, nbarrels);
+ // all barrels
+ if (active_barrel < 0) {
+ if (net_client || IsPrimary())
+ NetUtil::SendWepTrigger(this, nbarrels);
- if (!net_game || IsPrimary()) {
- for (int i = 0; i < nbarrels; i++)
- shot = FireBarrel(i);
- }
+ if (!net_game || IsPrimary()) {
+ for (int i = 0; i < nbarrels; i++)
+ shot = FireBarrel(i);
+ }
- else if (net_game && net_game->IsServer() && IsMissile()) {
- for (int i = 0; i < nbarrels; i++) {
- shot = FireBarrel(i);
- NetUtil::SendWepRelease(this, shot);
- }
- }
- }
+ else if (net_game && net_game->IsServer() && IsMissile()) {
+ for (int i = 0; i < nbarrels; i++) {
+ shot = FireBarrel(i);
+ NetUtil::SendWepRelease(this, shot);
+ }
+ }
+ }
- // single barrel
- else {
- if (net_client || IsPrimary())
- NetUtil::SendWepTrigger(this, nbarrels);
+ // single barrel
+ else {
+ if (net_client || IsPrimary())
+ NetUtil::SendWepTrigger(this, nbarrels);
- if (!net_game || IsPrimary()) {
- shot = FireBarrel(active_barrel++);
- }
+ if (!net_game || IsPrimary()) {
+ shot = FireBarrel(active_barrel++);
+ }
- else if (net_game && net_game->IsServer() && IsMissile()) {
- shot = FireBarrel(active_barrel++);
- NetUtil::SendWepRelease(this, shot);
- }
+ else if (net_game && net_game->IsServer() && IsMissile()) {
+ shot = FireBarrel(active_barrel++);
+ NetUtil::SendWepRelease(this, shot);
+ }
- if (active_barrel >= nbarrels) {
- active_barrel = 0;
- refire += design->salvo_delay;
- }
- }
+ if (active_barrel >= nbarrels) {
+ active_barrel = 0;
+ refire += design->salvo_delay;
+ }
+ }
- if (design->ripple_count > 0 && ripple_count <= 0)
- ripple_count = design->ripple_count-1;
+ if (design->ripple_count > 0 && ripple_count <= 0)
+ ripple_count = design->ripple_count-1;
- if (status != NOMINAL)
- refire *= 2;
- }
+ if (status != NOMINAL)
+ refire *= 2;
+ }
- return shot;
+ return shot;
}
// +--------------------------------------------------------------------+
@@ -666,62 +666,62 @@ Weapon::Fire()
Shot*
Weapon::NetFirePrimary(SimObject* tgt, System* sub, int count)
{
- Shot* shot = 0;
+ Shot* shot = 0;
- if (!IsPrimary() || Game::Paused())
- return shot;
+ if (!IsPrimary() || Game::Paused())
+ return shot;
- if (active_barrel < 0 || active_barrel >= nbarrels)
- active_barrel = 0;
+ if (active_barrel < 0 || active_barrel >= nbarrels)
+ active_barrel = 0;
- target = tgt;
- subtarget = sub;
- aim_time = 0;
+ target = tgt;
+ subtarget = sub;
+ aim_time = 0;
- for (int i = 0; i < count; i++) {
- shot = FireBarrel(active_barrel++);
+ for (int i = 0; i < count; i++) {
+ shot = FireBarrel(active_barrel++);
- if (active_barrel >= nbarrels) {
- active_barrel = 0;
- refire += design->salvo_delay;
- }
- }
+ if (active_barrel >= nbarrels) {
+ active_barrel = 0;
+ refire += design->salvo_delay;
+ }
+ }
- if (target)
- Observe(target);
+ if (target)
+ Observe(target);
- return shot;
+ return shot;
}
Shot*
Weapon::NetFireSecondary(SimObject* tgt, System* sub, DWORD objid)
{
- Shot* shot = 0;
+ Shot* shot = 0;
- if (IsPrimary() || Game::Paused())
- return shot;
+ if (IsPrimary() || Game::Paused())
+ return shot;
- if (active_barrel < 0 || active_barrel >= nbarrels)
- active_barrel = 0;
+ if (active_barrel < 0 || active_barrel >= nbarrels)
+ active_barrel = 0;
- target = tgt;
- subtarget = sub;
- aim_time = 0;
+ target = tgt;
+ subtarget = sub;
+ aim_time = 0;
- shot = FireBarrel(active_barrel++);
+ shot = FireBarrel(active_barrel++);
- if (active_barrel >= nbarrels) {
- active_barrel = 0;
- refire += design->salvo_delay;
- }
+ if (active_barrel >= nbarrels) {
+ active_barrel = 0;
+ refire += design->salvo_delay;
+ }
- if (shot)
- shot->SetObjID(objid);
+ if (shot)
+ shot->SetObjID(objid);
- if (target)
- Observe(target);
+ if (target)
+ Observe(target);
- return shot;
+ return shot;
}
// +--------------------------------------------------------------------+
@@ -729,112 +729,112 @@ Weapon::NetFireSecondary(SimObject* tgt, System* sub, DWORD objid)
Shot*
Weapon::FireBarrel(int n)
{
- const Point& base_vel = ship->Velocity();
- Shot* shot = 0;
- SimRegion* region = ship->GetRegion();
-
- if (!region || n < 0 || n >= nbarrels || Game::Paused())
- return 0;
-
- firing = 1;
- Aim();
-
- Camera rail_cam;
- rail_cam.Clone(aim_cam);
-
- Point shotpos = muzzle_pts[n];
- if (design->length > 0)
- shotpos = shotpos + aim_cam.vpn() * design->length;
-
- // guns may be slewed towards target:
- if (design->primary) {
- shot = CreateShot(shotpos, aim_cam, design, ship);
-
- if (shot) {
- shot->SetVelocity(shot->Velocity() + base_vel);
- }
- }
-
- // missiles always launch in rail direction:
- else {
- // unless they are on a mobile launcher
- if (turret && design->self_aiming) {
- shot = CreateShot(shotpos, aim_cam, design, ship);
- shot->SetVelocity(base_vel);
- }
- else {
- shot = CreateShot(shotpos, rail_cam, design, ship);
- if (shot /* && !turret */) {
- Matrix orient = ship->Cam().Orientation();
- if (aim_azimuth != 0) orient.Yaw(aim_azimuth);
- if (aim_elevation != 0) orient.Pitch(aim_elevation);
-
- Point eject = design->eject * orient;
- shot->SetVelocity(base_vel + eject);
- }
- }
-
- if (shot && visible_stores[n]) {
- GRAPHIC_DESTROY(visible_stores[n]);
- }
- }
-
- if (shot) {
- if (ammo > 0)
- ammo--;
-
- if (guided && target)
- shot->SeekTarget(target, subtarget);
-
- float shot_load;
- if (energy > design->charge)
- shot_load = design->charge;
- else
- shot_load = energy;
-
- energy -= shot_load;
- shot->SetCharge(shot_load * availability);
-
- if (target && design->flak && !design->guided) {
- double speed = shot->Velocity().length();
- double range = (target->Location() - shot->Location()).length();
-
- if (range > design->min_range && range < design->max_range) {
- shot->SetFuse(range / speed);
- }
- }
-
- region->InsertObject(shot);
-
- if (beams) {
- beams[n] = shot;
- Observe(beams[n]);
-
- // aim beam at target:
- SetBeamPoints(true);
- }
-
- if (ship) {
- ShipStats* stats = ShipStats::Find(ship->Name());
-
- if (design->primary)
- stats->AddGunShot();
- else if (design->decoy_type == 0 && design->damage > 0)
- stats->AddMissileShot();
- }
- }
-
- return shot;
+ const Point& base_vel = ship->Velocity();
+ Shot* shot = 0;
+ SimRegion* region = ship->GetRegion();
+
+ if (!region || n < 0 || n >= nbarrels || Game::Paused())
+ return 0;
+
+ firing = 1;
+ Aim();
+
+ Camera rail_cam;
+ rail_cam.Clone(aim_cam);
+
+ Point shotpos = muzzle_pts[n];
+ if (design->length > 0)
+ shotpos = shotpos + aim_cam.vpn() * design->length;
+
+ // guns may be slewed towards target:
+ if (design->primary) {
+ shot = CreateShot(shotpos, aim_cam, design, ship);
+
+ if (shot) {
+ shot->SetVelocity(shot->Velocity() + base_vel);
+ }
+ }
+
+ // missiles always launch in rail direction:
+ else {
+ // unless they are on a mobile launcher
+ if (turret && design->self_aiming) {
+ shot = CreateShot(shotpos, aim_cam, design, ship);
+ shot->SetVelocity(base_vel);
+ }
+ else {
+ shot = CreateShot(shotpos, rail_cam, design, ship);
+ if (shot /* && !turret */) {
+ Matrix orient = ship->Cam().Orientation();
+ if (aim_azimuth != 0) orient.Yaw(aim_azimuth);
+ if (aim_elevation != 0) orient.Pitch(aim_elevation);
+
+ Point eject = design->eject * orient;
+ shot->SetVelocity(base_vel + eject);
+ }
+ }
+
+ if (shot && visible_stores[n]) {
+ GRAPHIC_DESTROY(visible_stores[n]);
+ }
+ }
+
+ if (shot) {
+ if (ammo > 0)
+ ammo--;
+
+ if (guided && target)
+ shot->SeekTarget(target, subtarget);
+
+ float shot_load;
+ if (energy > design->charge)
+ shot_load = design->charge;
+ else
+ shot_load = energy;
+
+ energy -= shot_load;
+ shot->SetCharge(shot_load * availability);
+
+ if (target && design->flak && !design->guided) {
+ double speed = shot->Velocity().length();
+ double range = (target->Location() - shot->Location()).length();
+
+ if (range > design->min_range && range < design->max_range) {
+ shot->SetFuse(range / speed);
+ }
+ }
+
+ region->InsertObject(shot);
+
+ if (beams) {
+ beams[n] = shot;
+ Observe(beams[n]);
+
+ // aim beam at target:
+ SetBeamPoints(true);
+ }
+
+ if (ship) {
+ ShipStats* stats = ShipStats::Find(ship->Name());
+
+ if (design->primary)
+ stats->AddGunShot();
+ else if (design->decoy_type == 0 && design->damage > 0)
+ stats->AddMissileShot();
+ }
+ }
+
+ return shot;
}
Shot*
Weapon::CreateShot(const Point& loc, const Camera& cam, WeaponDesign* dsn, const Ship* own)
{
- if (dsn->drone)
- return new(__FILE__,__LINE__) Drone(loc, cam, dsn, own);
+ if (dsn->drone)
+ return new(__FILE__,__LINE__) Drone(loc, cam, dsn, own);
- else
- return new(__FILE__,__LINE__) Shot(loc, cam, dsn, own);
+ else
+ return new(__FILE__,__LINE__) Shot(loc, cam, dsn, own);
}
// +--------------------------------------------------------------------+
@@ -842,56 +842,56 @@ Weapon::CreateShot(const Point& loc, const Camera& cam, WeaponDesign* dsn, const
void
Weapon::Orient(const Physical* rep)
{
- System::Orient(rep);
-
- const Matrix& orientation = rep->Cam().Orientation();
- Point loc = rep->Location();
-
- // align graphics with camera:
- if (turret) {
- if (!design->self_aiming)
- ZeroAim();
-
- const Matrix& aim = aim_cam.Orientation();
-
- turret->MoveTo(mount_loc);
- turret->SetOrientation(aim);
-
- if (turret_base) {
- Matrix base = orientation;
-
- if (design->turret_axis == 1) {
- base.Pitch(aim_elevation);
- base.Pitch(old_elevation);
- }
- else {
- base.Yaw(aim_azimuth);
- base.Yaw(old_azimuth);
- }
-
- turret_base->MoveTo(mount_loc);
- turret_base->SetOrientation(base);
- }
-
- for (int i = 0; i < nbarrels; i++) {
- muzzle_pts[i] = (rel_pts[i] * aim) + mount_loc;
-
- if (visible_stores[i]) {
- visible_stores[i]->SetOrientation(aim);
- visible_stores[i]->MoveTo(muzzle_pts[i]);
- }
- }
- }
- else {
- for (int i = 0; i < nbarrels; i++) {
- muzzle_pts[i] = (rel_pts[i] * orientation) + loc;
-
- if (visible_stores[i]) {
- visible_stores[i]->SetOrientation(orientation);
- visible_stores[i]->MoveTo(muzzle_pts[i]);
- }
- }
- }
+ System::Orient(rep);
+
+ const Matrix& orientation = rep->Cam().Orientation();
+ Point loc = rep->Location();
+
+ // align graphics with camera:
+ if (turret) {
+ if (!design->self_aiming)
+ ZeroAim();
+
+ const Matrix& aim = aim_cam.Orientation();
+
+ turret->MoveTo(mount_loc);
+ turret->SetOrientation(aim);
+
+ if (turret_base) {
+ Matrix base = orientation;
+
+ if (design->turret_axis == 1) {
+ base.Pitch(aim_elevation);
+ base.Pitch(old_elevation);
+ }
+ else {
+ base.Yaw(aim_azimuth);
+ base.Yaw(old_azimuth);
+ }
+
+ turret_base->MoveTo(mount_loc);
+ turret_base->SetOrientation(base);
+ }
+
+ for (int i = 0; i < nbarrels; i++) {
+ muzzle_pts[i] = (rel_pts[i] * aim) + mount_loc;
+
+ if (visible_stores[i]) {
+ visible_stores[i]->SetOrientation(aim);
+ visible_stores[i]->MoveTo(muzzle_pts[i]);
+ }
+ }
+ }
+ else {
+ for (int i = 0; i < nbarrels; i++) {
+ muzzle_pts[i] = (rel_pts[i] * orientation) + loc;
+
+ if (visible_stores[i]) {
+ visible_stores[i]->SetOrientation(orientation);
+ visible_stores[i]->MoveTo(muzzle_pts[i]);
+ }
+ }
+ }
}
// +--------------------------------------------------------------------+
@@ -899,27 +899,27 @@ Weapon::Orient(const Physical* rep)
void
Weapon::SetBeamPoints(bool aim)
{
- for (int i = 0; i < nbarrels; i++) {
- if (beams && beams[i]) {
- Point from = muzzle_pts[i];
- Point to;
- double len = design->length;
-
- if (len < 1 || len > 1e7)
- len = design->max_range;
-
- if (len < 1)
- len = 3e5;
-
- else if (len > 1e7)
- len = 1e7;
-
- // always use the aim cam, to enforce slew_rate
- to = from + aim_cam.vpn() * len;
-
- beams[i]->SetBeamPoints(from, to);
- }
- }
+ for (int i = 0; i < nbarrels; i++) {
+ if (beams && beams[i]) {
+ Point from = muzzle_pts[i];
+ Point to;
+ double len = design->length;
+
+ if (len < 1 || len > 1e7)
+ len = design->max_range;
+
+ if (len < 1)
+ len = 3e5;
+
+ else if (len > 1e7)
+ len = 1e7;
+
+ // always use the aim cam, to enforce slew_rate
+ to = from + aim_cam.vpn() * len;
+
+ beams[i]->SetBeamPoints(from, to);
+ }
+ }
}
// +--------------------------------------------------------------------+
@@ -927,217 +927,217 @@ Weapon::SetBeamPoints(bool aim)
void
Weapon::Aim()
{
- locked = false;
- centered = false;
-
- FindObjective();
-
- if (target) {
- double az = 0;
- double el = 0;
-
- locked = CanLockPoint(obj_w, az, el, &objective);
-
- double spread_az = design->spread_az;
- double spread_el = design->spread_el;
-
- // beam sweep target:
- if (design->beam) {
- double factor = 0;
- double az_phase = 0;
- double el_phase = 0;
-
- if (target->Type() == SimObject::SIM_SHIP) {
- Ship* s = (Ship*) target;
-
- if (s->IsStarship()) {
- switch (sweep) {
- default:
- case SWEEP_NONE: factor = 0; break;
- case SWEEP_TIGHT: factor = 1; break;
- case SWEEP_WIDE: factor = 2; break;
- }
- }
- }
-
- if (factor > 0) {
- factor *= atan2(target->Radius(), (double) objective.z);
-
- for (int i = 0; i < nbarrels; i++) {
- if (beams && beams[i]) {
- az_phase = sin(beams[i]->Life() * 0.4 * PI);
- el_phase = sin(beams[i]->Life() * 1.0 * PI);
- break;
- }
- }
-
- az += factor * spread_az * az_phase;
- el += factor * spread_el * el_phase * 0.25;
- }
- }
-
- else if (!design->beam) {
- if (spread_az > 0)
- az += Random(-spread_az, spread_az);
-
- if (spread_el > 0)
- el += Random(-spread_el, spread_el);
- }
-
- AimTurret(az, -el);
-
- // check range for guided weapons:
- if (locked && guided) {
- double range = objective.length();
-
- if (range > design->max_track)
- locked = false;
-
- else if (range > design->max_range) {
- if (firing) {
- if (RandomChance(1,4)) // 1 in 4 chance of locking anyway
- locked = false;
- }
- else {
- locked = false;
- }
- }
- }
-
- if (locked) {
- Point tloc = target->Location();
- tloc = Transform(tloc);
-
- if (tloc.z > 1) {
- az = atan2(fabs(tloc.x), tloc.z);
- el = atan2(fabs(tloc.y), tloc.z);
-
- double firing_cone = 10*DEGREES;
-
- if (orders == MANUAL)
- firing_cone = 30*DEGREES;
-
- if (az < firing_cone && el < firing_cone)
- centered = true;
- }
- }
- }
- else {
- AimTurret(aim_az_rest, -aim_el_rest);
- }
+ locked = false;
+ centered = false;
+
+ FindObjective();
+
+ if (target) {
+ double az = 0;
+ double el = 0;
+
+ locked = CanLockPoint(obj_w, az, el, &objective);
+
+ double spread_az = design->spread_az;
+ double spread_el = design->spread_el;
+
+ // beam sweep target:
+ if (design->beam) {
+ double factor = 0;
+ double az_phase = 0;
+ double el_phase = 0;
+
+ if (target->Type() == SimObject::SIM_SHIP) {
+ Ship* s = (Ship*) target;
+
+ if (s->IsStarship()) {
+ switch (sweep) {
+ default:
+ case SWEEP_NONE: factor = 0; break;
+ case SWEEP_TIGHT: factor = 1; break;
+ case SWEEP_WIDE: factor = 2; break;
+ }
+ }
+ }
+
+ if (factor > 0) {
+ factor *= atan2(target->Radius(), (double) objective.z);
+
+ for (int i = 0; i < nbarrels; i++) {
+ if (beams && beams[i]) {
+ az_phase = sin(beams[i]->Life() * 0.4 * PI);
+ el_phase = sin(beams[i]->Life() * 1.0 * PI);
+ break;
+ }
+ }
+
+ az += factor * spread_az * az_phase;
+ el += factor * spread_el * el_phase * 0.25;
+ }
+ }
+
+ else if (!design->beam) {
+ if (spread_az > 0)
+ az += Random(-spread_az, spread_az);
+
+ if (spread_el > 0)
+ el += Random(-spread_el, spread_el);
+ }
+
+ AimTurret(az, -el);
+
+ // check range for guided weapons:
+ if (locked && guided) {
+ double range = objective.length();
+
+ if (range > design->max_track)
+ locked = false;
+
+ else if (range > design->max_range) {
+ if (firing) {
+ if (RandomChance(1,4)) // 1 in 4 chance of locking anyway
+ locked = false;
+ }
+ else {
+ locked = false;
+ }
+ }
+ }
+
+ if (locked) {
+ Point tloc = target->Location();
+ tloc = Transform(tloc);
+
+ if (tloc.z > 1) {
+ az = atan2(fabs(tloc.x), tloc.z);
+ el = atan2(fabs(tloc.y), tloc.z);
+
+ double firing_cone = 10*DEGREES;
+
+ if (orders == MANUAL)
+ firing_cone = 30*DEGREES;
+
+ if (az < firing_cone && el < firing_cone)
+ centered = true;
+ }
+ }
+ }
+ else {
+ AimTurret(aim_az_rest, -aim_el_rest);
+ }
}
void
Weapon::FindObjective()
{
- ZeroAim();
+ ZeroAim();
- if (!target || !design->self_aiming) {
- objective = Point();
- return;
- }
+ if (!target || !design->self_aiming) {
+ objective = Point();
+ return;
+ }
- obj_w = target->Location();
+ obj_w = target->Location();
- if (subtarget) {
- obj_w = subtarget->MountLocation();
- }
- else if (target->Type() == SimObject::SIM_SHIP) {
- Ship* tgt_ship = (Ship*) target;
+ if (subtarget) {
+ obj_w = subtarget->MountLocation();
+ }
+ else if (target->Type() == SimObject::SIM_SHIP) {
+ Ship* tgt_ship = (Ship*) target;
- if (tgt_ship->IsGroundUnit())
- obj_w += Point(0,150,0);
- }
+ if (tgt_ship->IsGroundUnit())
+ obj_w += Point(0,150,0);
+ }
- if (!design->beam && shot_speed > 0) {
- // distance from self to target:
- double distance = Point(obj_w - muzzle_pts[0]).length();
+ if (!design->beam && shot_speed > 0) {
+ // distance from self to target:
+ double distance = Point(obj_w - muzzle_pts[0]).length();
- // TRUE shot speed is relative to ship speed:
- Point eff_shot_vel = ship->Velocity() + aim_cam.vpn() * shot_speed - target->Velocity();
- double eff_shot_speed = eff_shot_vel.length();
+ // TRUE shot speed is relative to ship speed:
+ Point eff_shot_vel = ship->Velocity() + aim_cam.vpn() * shot_speed - target->Velocity();
+ double eff_shot_speed = eff_shot_vel.length();
- // time to reach target:
- double time = distance / eff_shot_speed;
+ // time to reach target:
+ double time = distance / eff_shot_speed;
- // where the target will be when the shot reaches it:
- obj_w += (target->Velocity() - ship->Velocity()) * time +
- target->Acceleration() * 0.25 * time * time;
- }
+ // where the target will be when the shot reaches it:
+ obj_w += (target->Velocity() - ship->Velocity()) * time +
+ target->Acceleration() * 0.25 * time * time;
+ }
- // transform into camera coords:
- objective = Transform(obj_w);
+ // transform into camera coords:
+ objective = Transform(obj_w);
}
Point
Weapon::Transform(const Point& pt)
{
- Point result;
-
- Point obj_t = pt - aim_cam.Pos();
- result.x = obj_t * aim_cam.vrt();
- result.y = obj_t * aim_cam.vup();
- result.z = obj_t * aim_cam.vpn();
-
- return result;
+ Point result;
+
+ Point obj_t = pt - aim_cam.Pos();
+ result.x = obj_t * aim_cam.vrt();
+ result.y = obj_t * aim_cam.vup();
+ result.z = obj_t * aim_cam.vpn();
+
+ return result;
}
bool
Weapon::CanLockPoint(const Point& test, double& az, double& el, Point* obj)
{
- Point pt = Transform(test);
- bool locked = true;
-
- // first compute az:
- if (fabs(pt.z) < 0.1) pt.z = 0.1;
- az = atan(pt.x / pt.z);
- if (pt.z < 0) az -= PI;
- if (az < -PI) az += 2*PI;
-
- // then, rotate target into az-coords to compute el:
- Camera tmp;
- tmp.Clone(aim_cam);
- aim_cam.Yaw(az);
- pt = Transform(test);
- aim_cam.Clone(tmp);
-
- if (fabs(pt.z) < 0.1) pt.z = 0.1;
- el = atan(pt.y / pt.z);
-
- if (obj) *obj = pt;
-
- // is the target in the basket?
- // clamp if necessary:
-
- if (az > aim_az_max) {
- az = aim_az_max;
- locked = false;
- }
- else if (az < aim_az_min) {
- az = aim_az_min;
- locked = false;
- }
-
- if (el > aim_el_max) {
- el = aim_el_max;
- locked = false;
- }
- else if (el < aim_el_min) {
- el = aim_el_min;
- locked = false;
- }
-
- if (IsDrone() && guided) {
- double firing_cone = 10*DEGREES;
-
- if (orders == MANUAL)
- firing_cone = 20*DEGREES;
-
- if (az < firing_cone && el < firing_cone)
- locked = true;
- }
-
- return locked;
+ Point pt = Transform(test);
+ bool locked = true;
+
+ // first compute az:
+ if (fabs(pt.z) < 0.1) pt.z = 0.1;
+ az = atan(pt.x / pt.z);
+ if (pt.z < 0) az -= PI;
+ if (az < -PI) az += 2*PI;
+
+ // then, rotate target into az-coords to compute el:
+ Camera tmp;
+ tmp.Clone(aim_cam);
+ aim_cam.Yaw(az);
+ pt = Transform(test);
+ aim_cam.Clone(tmp);
+
+ if (fabs(pt.z) < 0.1) pt.z = 0.1;
+ el = atan(pt.y / pt.z);
+
+ if (obj) *obj = pt;
+
+ // is the target in the basket?
+ // clamp if necessary:
+
+ if (az > aim_az_max) {
+ az = aim_az_max;
+ locked = false;
+ }
+ else if (az < aim_az_min) {
+ az = aim_az_min;
+ locked = false;
+ }
+
+ if (el > aim_el_max) {
+ el = aim_el_max;
+ locked = false;
+ }
+ else if (el < aim_el_min) {
+ el = aim_el_min;
+ locked = false;
+ }
+
+ if (IsDrone() && guided) {
+ double firing_cone = 10*DEGREES;
+
+ if (orders == MANUAL)
+ firing_cone = 20*DEGREES;
+
+ if (az < firing_cone && el < firing_cone)
+ locked = true;
+ }
+
+ return locked;
}
// +--------------------------------------------------------------------+
@@ -1145,40 +1145,40 @@ Weapon::CanLockPoint(const Point& test, double& az, double& el, Point* obj)
void
Weapon::AimTurret(double az, double el)
{
- double seconds = (Game::GameTime() - aim_time) / 1000.0;
+ double seconds = (Game::GameTime() - aim_time) / 1000.0;
- // don't let the weapon turn faster than turret slew rate:
- double max_turn = design->slew_rate * seconds;
+ // don't let the weapon turn faster than turret slew rate:
+ double max_turn = design->slew_rate * seconds;
- if (fabs(az-old_azimuth) > max_turn) {
- if (az > old_azimuth)
- az = old_azimuth + max_turn;
- else
- az = old_azimuth - max_turn;
- }
+ if (fabs(az-old_azimuth) > max_turn) {
+ if (az > old_azimuth)
+ az = old_azimuth + max_turn;
+ else
+ az = old_azimuth - max_turn;
+ }
- if (fabs(el-old_elevation) > PI/2 * seconds) {
- if (el > old_elevation)
- el = old_elevation + max_turn;
- else
- el = old_elevation - max_turn;
- }
+ if (fabs(el-old_elevation) > PI/2 * seconds) {
+ if (el > old_elevation)
+ el = old_elevation + max_turn;
+ else
+ el = old_elevation - max_turn;
+ }
- aim_cam.Yaw(az);
- aim_cam.Pitch(el);
+ aim_cam.Yaw(az);
+ aim_cam.Pitch(el);
- old_azimuth = (float) az;
- old_elevation = (float) el;
+ old_azimuth = (float) az;
+ old_elevation = (float) el;
- aim_time = Game::GameTime();
+ aim_time = Game::GameTime();
}
void
Weapon::ZeroAim()
{
- aim_cam.Clone(ship->Cam());
- if (aim_azimuth != 0) aim_cam.Yaw(aim_azimuth);
- if (aim_elevation != 0) aim_cam.Pitch(aim_elevation);
+ aim_cam.Clone(ship->Cam());
+ if (aim_azimuth != 0) aim_cam.Yaw(aim_azimuth);
+ if (aim_elevation != 0) aim_cam.Pitch(aim_elevation);
- aim_cam.MoveTo(muzzle_pts[0]);
+ aim_cam.MoveTo(muzzle_pts[0]);
}