summaryrefslogtreecommitdiffhomepage
path: root/Stars45/Mfd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Stars45/Mfd.cpp')
-rw-r--r--Stars45/Mfd.cpp1405
1 files changed, 0 insertions, 1405 deletions
diff --git a/Stars45/Mfd.cpp b/Stars45/Mfd.cpp
deleted file mode 100644
index f79f2af..0000000
--- a/Stars45/Mfd.cpp
+++ /dev/null
@@ -1,1405 +0,0 @@
-/* Starshatter: The Open Source Project
- Copyright (c) 2021-2022, Starshatter: The Open Source Project Contributors
- Copyright (c) 2011-2012, Starshatter OpenSource Distribution Contributors
- Copyright (c) 1997-2006, Destroyer Studios LLC.
-
- AUTHOR: John DiCamillo
-
-
- OVERVIEW
- ========
- Class for all Multi Function Displays
-*/
-
-#include "Mfd.h"
-#include "HUDView.h"
-#include "Ship.h"
-#include "NavSystem.h"
-#include "Power.h"
-#include "Shield.h"
-#include "Sensor.h"
-#include "Contact.h"
-#include "ShipDesign.h"
-#include "Shot.h"
-#include "Weapon.h"
-#include "WeaponGroup.h"
-#include "Sim.h"
-#include "StarSystem.h"
-#include "Starshatter.h"
-#include "Drive.h"
-#include "QuantumDrive.h"
-#include "Power.h"
-#include "Instruction.h"
-
-#include "NetGame.h"
-
-#include "CameraView.h"
-#include "Color.h"
-#include "Font.h"
-#include "FontMgr.h"
-#include "Window.h"
-#include "Video.h"
-#include "Screen.h"
-#include "DataLoader.h"
-#include "Scene.h"
-#include "Graphic.h"
-#include "Sprite.h"
-#include "Keyboard.h"
-#include "Mouse.h"
-#include "Game.h"
-#include "Clock.h"
-#include "ContentBundle.h"
-
-static Bitmap sensor_fov;
-static Bitmap sensor_fwd;
-static Bitmap sensor_hsd;
-static Bitmap sensor_3d;
-
-static BYTE* sensor_fov_shade;
-static BYTE* sensor_fwd_shade;
-static BYTE* sensor_hsd_shade;
-static BYTE* sensor_3d_shade;
-
-static Color hud_color = Color::Black;
-static Color txt_color = Color::Black;
-
-// +--------------------------------------------------------------------+
-
-MFD::MFD(Window* c, int n)
-: window(c), rect(0,0,0,0), index(n), mode(MFD_MODE_OFF), sprite(0),
-ship(0), hidden(true), camview(0), lines(0), mouse_latch(0), mouse_in(false),
-cockpit_hud_texture(0)
-{
- sprite = new Sprite(&sensor_fov);
-
- sprite->SetBlendMode(2);
- sprite->SetFilter(0);
- sprite->Hide();
-
- Font* font = FontMgr::Find("HUD");
-
- for (int i = 0; i < TXT_LAST; i++) {
- mfd_text[i].font = font;
- mfd_text[i].color = Color::White;
- mfd_text[i].hidden = true;
- }
-}
-
-MFD::~MFD()
-{
- GRAPHIC_DESTROY(sprite);
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::Initialize()
-{
- static int initialized = 0;
- if (initialized) return;
-
- HUDView::PrepareBitmap("sensor_fov.pcx", sensor_fov, sensor_fov_shade);
- HUDView::PrepareBitmap("sensor_fwd.pcx", sensor_fwd, sensor_fwd_shade);
- HUDView::PrepareBitmap("sensor_hsd.pcx", sensor_hsd, sensor_hsd_shade);
- HUDView::PrepareBitmap("sensor_3d.pcx", sensor_3d, sensor_3d_shade);
-
- sensor_fov.SetType(Bitmap::BMP_TRANSLUCENT);
- sensor_fwd.SetType(Bitmap::BMP_TRANSLUCENT);
- sensor_hsd.SetType(Bitmap::BMP_TRANSLUCENT);
- sensor_3d.SetType(Bitmap::BMP_TRANSLUCENT);
-
- initialized = 1;
-}
-
-void
-MFD::Close()
-{
- sensor_fov.ClearImage();
- sensor_fwd.ClearImage();
- sensor_hsd.ClearImage();
- sensor_3d.ClearImage();
-
- delete [] sensor_fov_shade;
- delete [] sensor_fwd_shade;
- delete [] sensor_hsd_shade;
- delete [] sensor_3d_shade;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::UseCameraView(CameraView* v)
-{
- if (v && !camview) {
- camview = v;
- }
-}
-
-void
-MFD::SetColor(Color c)
-{
- HUDView* hud = HUDView::GetInstance();
-
- if (hud) {
- hud_color = hud->GetHUDColor();
- txt_color = hud->GetTextColor();
- }
- else {
- hud_color = c;
- txt_color = c;
- }
-
- HUDView::ColorizeBitmap(sensor_fov, sensor_fov_shade, c);
- HUDView::ColorizeBitmap(sensor_fwd, sensor_fwd_shade, c);
- HUDView::ColorizeBitmap(sensor_hsd, sensor_hsd_shade, c);
- HUDView::ColorizeBitmap(sensor_3d, sensor_3d_shade, c);
-}
-
-void
-MFD::SetText3DColor(Color c)
-{
- for (int i = 0; i < TXT_LAST; i++)
- mfd_text[i].color = c;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::Show()
-{
- switch (mode) {
- case MFD_MODE_FOV:
- case MFD_MODE_HSD:
- case MFD_MODE_3D:
- if (sprite)
- sprite->Show();
- break;
- }
-
- hidden = false;
-}
-
-void
-MFD::Hide()
-{
- if (sprite)
- sprite->Hide();
-
- for (int i = 0; i < TXT_LAST; i++)
- HideMFDText(i);
-
- hidden = true;
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::SetRect(const Rect& r)
-{
- rect = r;
-
- if (sprite)
- sprite->MoveTo(Point(rect.x + sprite->Width()/2,
- rect.y + sprite->Height()/2,
- 1));
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::SetMode(int m)
-{
- if (m < MFD_MODE_OFF || m > MFD_MODE_3D)
- mode = MFD_MODE_OFF;
- else
- mode = m;
-
- sprite->Hide();
-
- for (int i = 0; i < TXT_LAST; i++)
- HideMFDText(i);
-
- switch (mode) {
- case MFD_MODE_GAME:
- case MFD_MODE_SHIP:
- lines = 0;
- break;
-
- case MFD_MODE_FOV:
- sprite->SetAnimation(&sensor_fov);
- sprite->Show();
- sprite->Reshape(sensor_fov.Width()-8, 16);
- break;
- case MFD_MODE_HSD:
- sprite->SetAnimation(&sensor_hsd);
- sprite->Show();
- sprite->Reshape(sensor_hsd.Width()-8, 16);
- break;
- case MFD_MODE_3D:
- sprite->SetAnimation(&sensor_3d);
- sprite->Show();
- sprite->Reshape(sensor_3d.Width()-8, 16);
- break;
- }
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::Draw()
-{
- mouse_in = false;
-
- if (Mouse::LButton() == 0)
- mouse_latch = 0;
-
- if (rect.Contains(Mouse::X(), Mouse::Y()))
- mouse_in = true;
-
- // click to turn on MFD when off:
- if (mode < MFD_MODE_FOV && Mouse::LButton() && !mouse_latch) {
- mouse_latch = 1;
- if (mouse_in) {
- HUDView* hud = HUDView::GetInstance();
- if (hud)
- hud->CycleMFDMode(index);
- }
- }
-
- for (int i = 0; i < TXT_LAST; i++)
- HideMFDText(i);
-
- if (hidden || mode < MFD_MODE_FOV) {
- if (cockpit_hud_texture) {
- int x1 = index*128;
- int y1 = 256;
- int x2 = x1 + 128;
- int y2 = y1 + 128;
-
- cockpit_hud_texture->FillRect(x1, y1, x2, y2, Color::Black);
- }
-
- if (hidden)
- return;
- }
-
- if (sprite && !sprite->Hidden()) {
- if (cockpit_hud_texture) {
- int x1 = index*128;
- int y1 = 256;
- int w = sprite->Width();
- int h = sprite->Height();
-
- cockpit_hud_texture->BitBlt(x1, y1, *sprite->Frame(), 0,0,w,h);
- }
- else {
- int cx = rect.x + rect.w/2;
- int cy = rect.y + rect.h/2;
- int w2 = sprite->Width()/2;
- int h2 = sprite->Height()/2;
-
- window->DrawBitmap(cx-w2, cy-h2, cx+w2, cy+h2, sprite->Frame(), Video::BLEND_ALPHA);
- }
- }
-
- switch (mode) {
- default:
- case MFD_MODE_OFF: break;
- case MFD_MODE_GAME: DrawGameMFD(); break;
- case MFD_MODE_SHIP: DrawStatusMFD(); break;
-
- // sensor sub-modes:
- case MFD_MODE_FOV: DrawSensorMFD(); break;
- case MFD_MODE_HSD: DrawHSD(); break;
- case MFD_MODE_3D: Draw3D(); break;
- }
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::DrawSensorLabels(const char* mfd_mode)
-{
- Sensor* sensor = ship->GetSensor();
- char mode_buf[8] = " ";
- int scan_r = rect.w;
- int scan_x = rect.x;
- int scan_y = rect.y;
-
- switch (sensor->GetMode()) {
- case Sensor::PAS: strcpy_s(mode_buf, ContentBundle::GetInstance()->GetText("MFD.mode.passive").data()); break;
- case Sensor::STD: strcpy_s(mode_buf, ContentBundle::GetInstance()->GetText("MFD.mode.standard").data()); break;
- case Sensor::ACM: strcpy_s(mode_buf, ContentBundle::GetInstance()->GetText("MFD.mode.auto-combat").data()); break;
- case Sensor::GM: strcpy_s(mode_buf, ContentBundle::GetInstance()->GetText("MFD.mode.ground").data()); break;
- case Sensor::PST: strcpy_s(mode_buf, ContentBundle::GetInstance()->GetText("MFD.mode.passive").data()); break;
- case Sensor::CST: strcpy_s(mode_buf, ContentBundle::GetInstance()->GetText("MFD.mode.combined").data()); break;
- default: break;
- }
-
- Rect mode_rect(scan_x+2, scan_y+2, 40, 12);
- DrawMFDText(0, mode_buf, mode_rect, DT_LEFT);
-
- char range_txt[12];
- double beam_range = sensor->GetBeamRange() + 1;
- if (beam_range >= 1e6)
- sprintf_s(range_txt, "-%dM+", (int) (beam_range / 1e6));
- else
- sprintf_s(range_txt, "-%3d+", (int) (beam_range / 1e3));
-
- Rect range_rect(scan_x+2, scan_y+scan_r-12, 40, 12);
- DrawMFDText(1, range_txt, range_rect, DT_LEFT);
-
- Rect disp_rect(scan_x+scan_r-41, scan_y+2, 40, 12);
- DrawMFDText(2, mfd_mode, disp_rect, DT_RIGHT);
-
- Rect probe_rect(scan_x+scan_r-41, scan_y+scan_r-12, 40, 12);
-
- if (ship->GetProbeLauncher()) {
- char probes[32];
- sprintf_s(probes, "%s %02d", ContentBundle::GetInstance()->GetText("MFD.probe").data(), ship->GetProbeLauncher()->Ammo());
- DrawMFDText(3, probes, probe_rect, DT_RIGHT);
- }
- else {
- HideMFDText(3);
- }
-
- if (Mouse::LButton() && !mouse_latch) {
- mouse_latch = 1;
-
- if (mode_rect.Contains(Mouse::X(), Mouse::Y())) {
- if (sensor->GetMode() < Sensor::PST) {
- int sensor_mode = sensor->GetMode() + 1;
- if (sensor_mode > Sensor::GM)
- sensor_mode = Sensor::PAS;
-
- sensor->SetMode((Sensor::Mode) sensor_mode);
- }
- }
-
- else if (range_rect.Contains(Mouse::X(), Mouse::Y())) {
- if (Mouse::X() > range_rect.x+range_rect.w/2)
- sensor->IncreaseRange();
- else
- sensor->DecreaseRange();
- }
-
- else if (disp_rect.Contains(Mouse::X(), Mouse::Y())) {
- HUDView* hud = HUDView::GetInstance();
- if (hud)
- hud->CycleMFDMode(index);
- }
-
- else if (probe_rect.Contains(Mouse::X(), Mouse::Y())) {
- ship->LaunchProbe();
- }
- }
-}
-
-// +--------------------------------------------------------------------+
-
-// AZIMUTH-ELEVATION ANGULAR SCANNER
-
-void
-MFD::DrawSensorMFD()
-{
- int scan_r = rect.w;
- int scan_x = cockpit_hud_texture ? (index*128) : rect.x;
- int scan_y = cockpit_hud_texture ? 256 : rect.y;
- int r = scan_r / 2;
-
- double xctr = (scan_r / 2.0) - 0.5;
- double yctr = (scan_r / 2.0) + 0.5;
-
- Sensor* sensor = ship->GetSensor();
- if (!sensor) {
- DrawMFDText(0, ContentBundle::GetInstance()->GetText("MFD.inactive").data(), rect, DT_CENTER);
- return;
- }
-
- int w = sprite->Width();
- int h = sprite->Height();
-
- if (w < sprite->Frame()->Width())
- w += 2;
-
- if (h < sprite->Frame()->Height())
- h += 16;
-
- sprite->Reshape(w, h);
- sprite->Show();
-
- if (h < sprite->Frame()->Height())
- return;
-
- double sweep_scale = r / (PI/2);
-
- if (sensor->GetBeamLimit() > 90*DEGREES)
- sweep_scale = (double) r / (90*DEGREES);
-
- int az = (int) (sensor->GetBeamLimit() * sweep_scale);
- int el = az;
- int xc = (int) (scan_x + xctr);
- int yc = (int) (scan_y + yctr);
-
- if (mode == MFD_MODE_FOV) {
- if (sensor->GetMode() < Sensor::GM) {
- if (cockpit_hud_texture)
- cockpit_hud_texture->DrawEllipse(xc-az, yc-el, xc+az, yc+el, hud_color);
- else
- window->DrawEllipse(xc-az, yc-el, xc+az, yc+el, hud_color);
- }
- }
- else {
- char az_txt[8];
- sprintf_s(az_txt, "%d", (int) (sensor->GetBeamLimit() / DEGREES));
-
- Rect az_rect(scan_x+2, scan_y+scan_r-12, 32, 12);
- DrawMFDText(1, az_txt, az_rect, DT_LEFT);
-
- az_rect.x = scan_x + (scan_r/2) - (az_rect.w/2);
- DrawMFDText(2, "0", az_rect, DT_CENTER);
-
- az_rect.x = scan_x + scan_r - az_rect.w - 2;
- DrawMFDText(3, az_txt, az_rect, DT_RIGHT);
- }
-
- // draw next nav point:
- Instruction* navpt = ship->GetNextNavPoint();
- if (navpt && navpt->Region() == ship->GetRegion()) {
- const Camera* cam = &ship->Cam();
-
- // translate:
- Point pt = navpt->Location().OtherHand() - ship->Location();
-
- // rotate:
- double tx = pt * cam->vrt();
- double ty = pt * cam->vup();
- double tz = pt * cam->vpn();
-
- if (tz > 1.0) {
- // convert to spherical coords:
- double rng = pt.length();
- double az = asin(fabs(tx) / rng);
- double el = asin(fabs(ty) / rng);
-
- if (tx < 0) az = -az;
- if (ty < 0) el = -el;
-
- if (fabs(az) < 90*DEGREES) {
- az *= sweep_scale;
- el *= sweep_scale;
-
- int x = (int) (r + az);
- int y = (int) (r - el);
-
- // clip again:
- if (x > 0 && x < scan_r &&
- y > 0 && y < scan_r) {
-
- // draw:
- int xc = scan_x + x;
- int yc = scan_y + y;
-
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawLine(xc-2, yc-2, xc+2, yc+2, Color::White);
- cockpit_hud_texture->DrawLine(xc-2, yc+2, xc+2, yc-2, Color::White);
- }
- else {
- window->DrawLine(xc-2, yc-2, xc+2, yc+2, Color::White);
- window->DrawLine(xc-2, yc+2, xc+2, yc-2, Color::White);
- }
- }
- }
- }
- }
-
- int num_contacts = ship->NumContacts();
- ListIter<Contact> iter = ship->ContactList();
-
- while (++iter) {
- Contact* contact = iter.value();
- Ship* c_ship = contact->GetShip();
- double az, el, rng;
- bool aft = false;
-
- if (c_ship == ship) continue;
-
- contact->GetBearing(ship, az, el, rng);
-
- // clip (is in-front):
- if (fabs(az) < 90*DEGREES) {
- az *= sweep_scale;
- el *= sweep_scale;
- }
-
- // rear anulus:
- else {
- double len = sqrt(az*az + el*el);
-
- if (len > 1e-6) {
- az = r * az/len;
- el = r * el/len;
- }
- else {
- az = -r;
- el = 0;
- }
-
- aft = true;
- }
-
- int x = (int) (r + az);
- int y = (int) (r - el);
-
- // clip again:
- if (x < 0 || x > scan_r) continue;
- if (y < 0 || y > scan_r) continue;
-
- // draw:
- Color mark = HUDView::MarkerColor(contact);
-
- if (aft)
- mark = mark * 0.75;
-
- int xc = scan_x + x;
- int yc = scan_y + y;
- int size = 1;
-
- if (c_ship && c_ship == ship->GetTarget())
- size = 2;
-
- if (cockpit_hud_texture)
- cockpit_hud_texture->FillRect(xc-size, yc-size, xc+size, yc+size, mark);
- else
- window->FillRect(xc-size, yc-size, xc+size, yc+size, mark);
-
- if (contact->Threat(ship)) {
- if (c_ship) {
- if (cockpit_hud_texture)
- cockpit_hud_texture->DrawEllipse(xc-4, yc-4, xc+3, yc+3, mark);
- else
- window->DrawEllipse(xc-4, yc-4, xc+3, yc+3, mark);
- }
- else {
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawLine(xc, yc-5, xc+5, yc, mark);
- cockpit_hud_texture->DrawLine(xc+5, yc, xc, yc+5, mark);
- cockpit_hud_texture->DrawLine(xc, yc+5, xc-5, yc, mark);
- cockpit_hud_texture->DrawLine(xc-5, yc, xc, yc-5, mark);
- }
- else {
- window->DrawLine(xc, yc-5, xc+5, yc, mark);
- window->DrawLine(xc+5, yc, xc, yc+5, mark);
- window->DrawLine(xc, yc+5, xc-5, yc, mark);
- window->DrawLine(xc-5, yc, xc, yc-5, mark);
- }
- }
- }
- }
-
- DrawSensorLabels(ContentBundle::GetInstance()->GetText("MFD.mode.field-of-view").data());
-}
-
-// +--------------------------------------------------------------------+
-
-// HORIZONTAL SITUATION DISPLAY
-
-void
-MFD::DrawHSD()
-{
- int scan_r = rect.w;
- int scan_x = cockpit_hud_texture ? (index*128) : rect.x;
- int scan_y = cockpit_hud_texture ? 256 : rect.y;
- int r = scan_r / 2 - 4;
-
- double xctr = (scan_r / 2.0) - 0.5;
- double yctr = (scan_r / 2.0) + 0.5;
-
- int xc = (int) xctr + scan_x;
- int yc = (int) yctr + scan_y;
-
- Sensor* sensor = ship->GetSensor();
- if (!sensor) {
- DrawMFDText(0, ContentBundle::GetInstance()->GetText("MFD.inactive").data(), rect, DT_CENTER);
- return;
- }
-
- int w = sprite->Width();
- int h = sprite->Height();
-
- if (w < sprite->Frame()->Width())
- w += 2;
-
- if (h < sprite->Frame()->Height())
- h += 16;
-
- sprite->Reshape(w, h);
- sprite->Show();
-
- if (h < sprite->Frame()->Height())
- return;
-
- if (sensor->GetMode() < Sensor::PST) {
- double s = sin(sensor->GetBeamLimit());
- double c = cos(sensor->GetBeamLimit());
-
- int x0 = (int) (0.1*r*s);
- int y0 = (int) (0.1*r*c);
- int x1 = (int) (1.0*r*s);
- int y1 = (int) (1.0*r*c);
-
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawLine(xc-x0, yc-y0, xc-x1, yc-y1, hud_color);
- cockpit_hud_texture->DrawLine(xc+x0, yc-y0, xc+x1, yc-y1, hud_color);
- }
- else {
- window->DrawLine(xc-x0, yc-y0, xc-x1, yc-y1, hud_color);
- window->DrawLine(xc+x0, yc-y0, xc+x1, yc-y1, hud_color);
- }
- }
-
- double rscale = (double) r/(sensor->GetBeamRange());
-
- Camera hsd_cam = ship->Cam();
- Point look = ship->Location() + ship->Heading() * 1000;
- look.y = ship->Location().y;
-
- hsd_cam.LookAt(look);
-
- // draw tick marks on range rings:
- for (int dir = 0; dir < 4; dir++) {
- Point tick;
-
- switch (dir) {
- case 0: tick = Point( 0, 0, 1000); break;
- case 1: tick = Point( 1000, 0, 0); break;
- case 2: tick = Point( 0, 0, -1000); break;
- case 3: tick = Point(-1000, 0, 0); break;
- }
-
- double tx = tick * hsd_cam.vrt();
- double tz = tick * hsd_cam.vpn();
- double az = asin(fabs(tx) / 1000);
-
- if (tx < 0) az = -az;
-
- if (tz < 0)
- if (az < 0) az = -PI - az;
- else az = PI - az;
-
- for (double range = 0.3; range < 1; range += 0.3) {
- int x0 = (int) (sin(az) * r * range);
- int y0 = (int) (cos(az) * r * range);
- int x1 = (int) (sin(az) * r * (range + 0.1));
- int y1 = (int) (cos(az) * r * (range + 0.1));
-
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawLine(xc+x0, yc-y0, xc+x1, yc-y1, hud_color);
- }
- else {
- window->DrawLine(xc+x0, yc-y0, xc+x1, yc-y1, hud_color);
- }
- }
- }
-
- // draw next nav point:
- Instruction* navpt = ship->GetNextNavPoint();
- if (navpt && navpt->Region() == ship->GetRegion()) {
- const Camera* cam = &hsd_cam;
-
- // translate:
- Point pt = navpt->Location().OtherHand() - ship->Location();
-
- // rotate:
- double tx = pt * cam->vrt();
- double ty = pt * cam->vup();
- double tz = pt * cam->vpn();
-
- // convert to spherical coords:
- double rng = pt.length();
- double az = asin(fabs(tx) / rng);
-
- if (rng > sensor->GetBeamRange())
- rng = sensor->GetBeamRange();
-
- if (tx < 0)
- az = -az;
-
- if (tz < 0)
- if (az < 0)
- az = -PI - az;
- else
- az = PI - az;
-
- // draw:
- int x = (int) (xc + sin(az) * rng * rscale);
- int y = (int) (yc - cos(az) * rng * rscale);
-
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawLine(x-2, y-2, x+2, y+2, Color::White);
- cockpit_hud_texture->DrawLine(x-2, y+2, x+2, y-2, Color::White);
- }
- else {
- window->DrawLine(x-2, y-2, x+2, y+2, Color::White);
- window->DrawLine(x-2, y+2, x+2, y-2, Color::White);
- }
- }
-
- // draw contact markers:
- double limit = sensor->GetBeamRange();
- ListIter<Contact> contact = ship->ContactList();
-
- while (++contact) {
- Ship* c_ship = contact->GetShip();
- if (c_ship == ship) continue;
-
- // translate:
- Point targ_pt = contact->Location() - hsd_cam.Pos();
-
- // rotate:
- double tx = targ_pt * hsd_cam.vrt();
- double rg = contact->Range(ship, limit);
- double true_range = targ_pt.length();
- double az = asin(fabs(tx) / true_range);
-
- // clip:
- if (rg > limit || rg <= 0)
- continue;
-
- if (tx < 0)
- az = -az;
-
- if (!contact->InFront(ship))
- if (az < 0)
- az = -PI - az;
- else
- az = PI - az;
-
- // draw:
- int x = (int) (xc + sin(az) * rg * rscale);
- int y = (int) (yc - cos(az) * rg * rscale);
- int size = 2;
-
- // clip again:
- if (x < scan_x || y < scan_y)
- continue;
-
- if (c_ship && c_ship == ship->GetTarget())
- size = 3;
-
- Color mark = HUDView::MarkerColor(contact.value());
- if (cockpit_hud_texture) {
- cockpit_hud_texture->FillRect(x-size, y-size, x+size, y+size, mark);
- }
- else {
- window->FillRect(x-size, y-size, x+size, y+size, mark);
- }
-
- if (contact->Threat(ship)) {
- if (c_ship) {
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawEllipse(x-4, y-4, x+3, y+3, mark);
- }
- else {
- window->DrawEllipse(x-4, y-4, x+3, y+3, mark);
- }
- }
- else {
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawLine(x, y-5, x+5, y, mark);
- cockpit_hud_texture->DrawLine(x+5, y, x, y+5, mark);
- cockpit_hud_texture->DrawLine(x, y+5, x-5, y, mark);
- cockpit_hud_texture->DrawLine(x-5, y, x, y-5, mark);
- }
- else {
- window->DrawLine(x, y-5, x+5, y, mark);
- window->DrawLine(x+5, y, x, y+5, mark);
- window->DrawLine(x, y+5, x-5, y, mark);
- window->DrawLine(x-5, y, x, y-5, mark);
- }
- }
- }
- }
-
- DrawSensorLabels(ContentBundle::GetInstance()->GetText("MFD.mode.horizontal").data());
-}
-
-// +--------------------------------------------------------------------+
-
-// ELITE-STYLE 3D RADAR
-
-void
-MFD::Draw3D()
-{
- int scan_r = rect.w;
- int scan_x = cockpit_hud_texture ? (index*128) : rect.x;
- int scan_y = cockpit_hud_texture ? 256 : rect.y;
- int r = scan_r / 2 - 4;
-
- double xctr = (scan_r / 2.0) - 0.5;
- double yctr = (scan_r / 2.0) + 0.5;
-
- int xc = (int) xctr + scan_x;
- int yc = (int) yctr + scan_y;
-
- Sensor* sensor = ship->GetSensor();
- if (!sensor) {
- DrawMFDText(0, ContentBundle::GetInstance()->GetText("MFD.inactive").data(), rect, DT_CENTER);
- return;
- }
-
- int w = sprite->Width();
- int h = sprite->Height();
-
- if (w < sprite->Frame()->Width())
- w += 2;
-
- if (h < sprite->Frame()->Height())
- h += 16;
-
- sprite->Reshape(w, h);
- sprite->Show();
-
- if (h < sprite->Frame()->Height())
- return;
-
- double rscale = (double) r/(sensor->GetBeamRange());
-
- Camera hsd_cam = ship->Cam();
-
- if (ship->IsStarship()) {
- Point look = ship->Location() + ship->Heading() * 1000;
- look.y = ship->Location().y;
-
- hsd_cam.LookAt(look);
- }
-
-
- // draw next nav point:
- Instruction* navpt = ship->GetNextNavPoint();
- if (navpt && navpt->Region() == ship->GetRegion()) {
- const Camera* cam = &hsd_cam;
-
- // translate:
- Point pt = navpt->Location().OtherHand() - ship->Location();
-
- // rotate:
- double tx = pt * cam->vrt();
- double ty = pt * cam->vup();
- double tz = pt * cam->vpn();
-
- // convert to cylindrical coords:
- double rng = pt.length();
- double az = asin(fabs(tx) / rng);
-
- if (rng > sensor->GetBeamRange())
- rng = sensor->GetBeamRange();
-
- if (tx < 0)
- az = -az;
-
- if (tz < 0) {
- if (az < 0)
- az = -PI - az;
- else
- az = PI - az;
- }
-
- // accentuate vertical:
- if (ty > 10)
- ty = log10(ty-9) * r/8;
-
- else if (ty < -10)
- ty = -log10(9-ty) * r/8;
-
- else
- ty = 0;
-
- // draw:
- int x = (int) (sin(az) * rng * rscale);
- int y = (int) (cos(az) * rng * rscale/2);
- int z = (int) (ty);
-
- int x0 = xc+x;
- int y0 = yc-y-z;
-
- if (cockpit_hud_texture) {
- cockpit_hud_texture->DrawLine(x0-2, y0-2, x0+2, y0+2, Color::White);
- cockpit_hud_texture->DrawLine(x0-2, y0+2, x0+2, y0-2, Color::White);
- }
- else {
- window->DrawLine(x0-2, y0-2, x0+2, y0+2, Color::White);
- window->DrawLine(x0-2, y0+2, x0+2, y0-2, Color::White);
- }
-
- if (cockpit_hud_texture) {
- if (z > 0)
- cockpit_hud_texture->DrawLine(x0, y0+1, x0, y0+z, Color::White);
- else if (z < 0)
- cockpit_hud_texture->DrawLine(x0, y0+z, x0, y0-1, Color::White);
- }
- else {
- if (z > 0)
- window->DrawLine(x0, y0+1, x0, y0+z, Color::White);
- else if (z < 0)
- window->DrawLine(x0, y0+z, x0, y0-1, Color::White);
- }
- }
-
-
- // draw contact markers:
- double limit = sensor->GetBeamRange();
- ListIter<Contact> contact = ship->ContactList();
-
- while (++contact) {
- Ship* c_ship = contact->GetShip();
- if (c_ship == ship) continue;
-
- // translate:
- Point targ_pt = contact->Location() - hsd_cam.Pos();
-
- // rotate:
- double tx = targ_pt * hsd_cam.vrt();
- double ty = targ_pt * hsd_cam.vup();
- double rg = contact->Range(ship, limit);
- double true_range = targ_pt.length();
- double az = asin(fabs(tx) / true_range);
-
- // clip:
- if (rg > limit || rg <= 0)
- continue;
-
- if (tx < 0)
- az = -az;
-
- if (!contact->InFront(ship))
- if (az < 0)
- az = -PI - az;
- else
- az = PI - az;
-
- // accentuate vertical:
- ty *= 4;
-
- // draw:
- int x = (int) (sin(az) * rg * rscale);
- int y = (int) (cos(az) * rg * rscale/2);
- int z = (int) (ty * rscale/2);
- int size = 1;
-
- int x0 = xc+x;
- int y0 = yc-y-z;
-
- if (c_ship && c_ship == ship->GetTarget())
- size = 2;
-
- Color mark = HUDView::MarkerColor(contact.value());
-
- if (cockpit_hud_texture) {
- cockpit_hud_texture->FillRect(x0-size, y0-size, x0+size, y0+size, mark);
-
- if (contact->Threat(ship)) {
- if (c_ship) {
- cockpit_hud_texture->DrawEllipse(x0-4, y0-4, x0+3, y0+3, mark);
- }
- else {
- cockpit_hud_texture->DrawLine(x0, y0-5, x0+5, y0, mark);
- cockpit_hud_texture->DrawLine(x0+5, y0, x0, y0+5, mark);
- cockpit_hud_texture->DrawLine(x0, y0+5, x0-5, y0, mark);
- cockpit_hud_texture->DrawLine(x0-5, y0, x0, y0-5, mark);
- }
- }
-
- if (z > 0)
- cockpit_hud_texture->FillRect(x0-1, y0+size, x0, y0+z, mark);
- else if (z < 0)
- cockpit_hud_texture->FillRect(x0-1, y0+z, x0, y0-size, mark);
- }
- else {
- window->FillRect(x0-size, y0-size, x0+size, y0+size, mark);
-
- if (contact->Threat(ship)) {
- if (c_ship) {
- window->DrawEllipse(x0-4, y0-4, x0+3, y0+3, mark);
- }
- else {
- window->DrawLine(x0, y0-5, x0+5, y0, mark);
- window->DrawLine(x0+5, y0, x0, y0+5, mark);
- window->DrawLine(x0, y0+5, x0-5, y0, mark);
- window->DrawLine(x0-5, y0, x0, y0-5, mark);
- }
- }
-
- if (z > 0)
- window->FillRect(x0-1, y0+size, x0, y0+z, mark);
- else if (z < 0)
- window->FillRect(x0-1, y0+z, x0, y0-size, mark);
- }
- }
-
- DrawSensorLabels(ContentBundle::GetInstance()->GetText("MFD.mode.3D").data());
-}
-
-// +--------------------------------------------------------------------+
-
-// GROUND MAP
-
-void
-MFD::DrawMap()
-{
- Rect text_rect(rect.x, rect.y, rect.w, 12);
- DrawMFDText(0, ContentBundle::GetInstance()->GetText("MFD.mode.ground").data(), text_rect, DT_CENTER);
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::DrawGauge(int x, int y, int percent)
-{
- if (cockpit_hud_texture) {
- x += this->index * 128 - this->rect.x;
- y += 256 - this->rect.y;
- cockpit_hud_texture->DrawRect(x, y, x+53, y+8, Color::DarkGray);
- }
- else {
- window->DrawRect(x, y, x+53, y+8, Color::DarkGray);
- }
-
- if (percent < 3) return;
- if (percent > 100) percent = 100;
-
- percent /= 2;
-
- if (cockpit_hud_texture)
- cockpit_hud_texture->FillRect(x+2, y+2, x+2+percent, y+7, Color::Gray);
- else
- window->FillRect(x+2, y+2, x+2+percent, y+7, Color::Gray);
-}
-
-void
-MFD::DrawGameMFD()
-{
- if (lines < 10) lines++;
-
- char txt[64];
- Rect txt_rect(rect.x, rect.y, rect.w, 12);
-
- int t = 0;
-
- if (!HUDView::IsArcade() && HUDView::ShowFPS()) {
- sprintf_s(txt, "FPS: %6.2f", Clock::GetInstance()->Rate());
- DrawMFDText(t++, txt, txt_rect, DT_LEFT);
- txt_rect.y += 10;
-
- if (lines <= 1) return;
-
- Starshatter* game = Starshatter::GetInstance();
- sprintf_s(txt, "Polys: %d", game->GetPolyStats().npolys);
- DrawMFDText(t++, txt, txt_rect, DT_LEFT);
- txt_rect.y += 10;
- }
-
- if (ship) {
- DrawMFDText(t++, ship->Name(), txt_rect, DT_LEFT);
- txt_rect.y += 10;
- }
-
- if (lines <= 2) return;
-
- int hours = (Clock::GetInstance()->GameTime() / 3600000) ;
- int minutes = (Clock::GetInstance()->GameTime() / 60000) % 60;
- int seconds = (Clock::GetInstance()->GameTime() / 1000) % 60;
-
- if (ship) {
- DWORD clock = ship->MissionClock();
-
- hours = (clock / 3600000) ;
- minutes = (clock / 60000) % 60;
- seconds = (clock / 1000) % 60;
- }
-
- if (static_cast<int>(Clock::GetInstance()->TimeCompression()) != 1)
- sprintf_s(txt, "%02d:%02d:%02d x%.1f", hours, minutes, seconds, Clock::GetInstance()->TimeCompression()); //-V576
- else
- sprintf_s(txt, "%02d:%02d:%02d", hours, minutes, seconds);
-
- DrawMFDText(t++, txt, txt_rect, DT_LEFT);
- txt_rect.y += 10;
-
- if (HUDView::IsArcade() || lines <= 3) return;
-
- DrawMFDText(t++, ship->GetRegion()->Name(), txt_rect, DT_LEFT);
- txt_rect.y += 10;
-
- if (lines <= 4) return;
-
- if (ship) {
- switch (ship->GetFlightPhase()) {
- case Ship::DOCKED: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.DOCKED").data(), txt_rect, DT_LEFT); break;
- case Ship::ALERT: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.ALERT").data(), txt_rect, DT_LEFT); break;
- case Ship::LOCKED: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.LOCKED").data(), txt_rect, DT_LEFT); break;
- case Ship::LAUNCH: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.LAUNCH").data(), txt_rect, DT_LEFT); break;
- case Ship::TAKEOFF: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.TAKEOFF").data(), txt_rect, DT_LEFT); break;
- case Ship::ACTIVE: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.ACTIVE").data(), txt_rect, DT_LEFT); break;
- case Ship::APPROACH: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.APPROACH").data(), txt_rect, DT_LEFT); break;
- case Ship::RECOVERY: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.RECOVERY").data(), txt_rect, DT_LEFT); break;
- case Ship::DOCKING: DrawMFDText(t++, ContentBundle::GetInstance()->GetText("MFD.phase.DOCKING").data(), txt_rect, DT_LEFT); break;
- }
- }
-}
-
-void
-MFD::DrawStatusMFD()
-{
- if (lines < 10) lines++;
-
- Rect status_rect(rect.x, rect.y, rect.w, 12);
- int row = 0;
- char txt[32];
-
- if (ship) {
- if (status_rect.y > 320 && !ship->IsStarship())
- status_rect.y += 32;
-
- Drive* drive = ship->GetDrive();
- if (drive) {
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.THRUST").data(), status_rect, DT_LEFT);
- DrawGauge(status_rect.x+70, status_rect.y, (int) ship->Throttle());
- status_rect.y += 10;
- }
-
- if (lines <= 1) return;
-
- if (ship->Reactors().size() > 0) {
- PowerSource* reactor = ship->Reactors()[0];
- if (reactor) {
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.FUEL").data(), status_rect, DT_LEFT);
- DrawGauge(status_rect.x+70, status_rect.y, reactor->Charge());
- status_rect.y += 10;
- }
- }
-
- if (lines <= 2) return;
-
- QuantumDrive* quantum_drive = ship->GetQuantumDrive();
- if (quantum_drive) {
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.QUANTUM").data(), status_rect, DT_LEFT);
- DrawGauge(status_rect.x+70, status_rect.y, (int) quantum_drive->Charge());
- status_rect.y += 10;
- }
-
- if (lines <= 3) return;
-
- double hull = ship->Integrity() / ship->Design()->integrity * 100;
- int hull_status = System::CRITICAL;
-
- if (hull > 66)
- hull_status = System::NOMINAL;
- else if (hull > 33)
- hull_status = System::DEGRADED;
-
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.HULL").data(), status_rect, DT_LEFT);
- DrawGauge(status_rect.x+70, status_rect.y, (int) hull);
- status_rect.y += 10;
-
- if (lines <= 4) return;
-
- Shield* shield = ship->GetShield();
- if (shield) {
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.SHIELD").data(), status_rect, DT_LEFT);
- DrawGauge(status_rect.x+70, status_rect.y, ship->ShieldStrength());
- status_rect.y += 10;
- }
-
- if (lines <= 5) return;
-
- Weapon* primary = ship->GetPrimary();
- if (primary) {
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.GUNS").data(), status_rect, DT_LEFT);
- DrawGauge(status_rect.x+70, status_rect.y, primary->Charge());
- status_rect.y += 10;
- }
-
- if (lines <= 6) return;
-
- if (HUDView::IsArcade()) {
- for (int i = 0; i < ship->Weapons().size() && i < 4; i++) {
- WeaponGroup* w = ship->Weapons().at(i);
-
- if (w->IsMissile()) {
- char ammo[8];
-
- if (ship->GetSecondaryGroup() == w)
- sprintf_s(ammo, "%d *", w->Ammo());
- else
- sprintf_s(ammo, "%d", w->Ammo());
-
- DrawMFDText(row++, (const char*) w->GetDesign()->name, status_rect, DT_LEFT);
- status_rect.x += 70;
- DrawMFDText(row++, ammo, status_rect, DT_LEFT);
- status_rect.x -= 70;
- status_rect.y += 10;
- }
- }
-
- if (ship->GetDecoy()) {
- char ammo[8];
- sprintf_s(ammo, "%d", ship->GetDecoy()->Ammo());
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.DECOY").data(), status_rect, DT_LEFT);
- status_rect.x += 70;
- DrawMFDText(row++, ammo, status_rect, DT_LEFT);
- status_rect.x -= 70;
- status_rect.y += 10;
- }
-
- if (NetGame::GetInstance()) {
- char lives[8];
- sprintf_s(lives, "%d", ship->RespawnCount() + 1);
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.LIVES").data(), status_rect, DT_LEFT);
- status_rect.x += 70;
- DrawMFDText(row++, lives, status_rect, DT_LEFT);
- status_rect.x -= 70;
- status_rect.y += 10;
- }
-
- return;
- }
-
- Sensor* sensor = ship->GetSensor();
- if (sensor) {
- if (ship->GetFlightPhase() != Ship::ACTIVE) {
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.SENSOR").data(), status_rect, DT_LEFT);
- status_rect.x += 70;
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.OFFLINE").data(), status_rect, DT_LEFT);
- status_rect.x -= 70;
- status_rect.y += 10;
- }
-
- else {
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.EMCON").data(), status_rect, DT_LEFT);
- status_rect.x += 70;
-
- sprintf_s(txt, "%s %d", ContentBundle::GetInstance()->GetText("MFD.status.MODE").data(), ship->GetEMCON());
-
- if (!sensor->IsPowerOn() || sensor->GetEnergy() == 0) {
- if (!Game::GetInstance()->Paused() && (Clock::GetInstance()->RealTime()/1000) & 2)
- strcpy_s(txt, ContentBundle::GetInstance()->GetText("MFD.status.SENSOR-OFF").data());
- }
-
- DrawMFDText(row++, txt, status_rect, DT_LEFT);
- status_rect.x -= 70;
- status_rect.y += 10;
- }
- }
-
- if (lines <= 7) return;
-
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.SYSTEMS").data(), status_rect, DT_LEFT);
- status_rect.x += 70;
- DrawMFDText(row++, ship->GetDirectorInfo(), status_rect, DT_LEFT);
-
- if (NetGame::GetInstance()) {
- char lives[8];
- sprintf_s(lives, "%d", ship->RespawnCount() + 1);
- status_rect.x -= 70;
- status_rect.y += 10;
- DrawMFDText(row++, ContentBundle::GetInstance()->GetText("MFD.status.LIVES").data(), status_rect, DT_LEFT);
- status_rect.x += 70;
- DrawMFDText(row++, lives, status_rect, DT_LEFT);
- }
- }
-}
-
-// +--------------------------------------------------------------------+
-
-void
-MFD::SetStatusColor(int status)
-{
- Color status_color;
-
- switch (status) {
- default:
- case System::NOMINAL: status_color = txt_color; break;
- case System::DEGRADED: status_color = Color(255,255, 0); break;
- case System::CRITICAL: status_color = Color(255, 0, 0); break;
- case System::DESTROYED: status_color = Color( 0, 0, 0); break;
- }
-}
-
-// +--------------------------------------------------------------------+
-
-bool MFD::IsMouseLatched() const
-{
- return mouse_in;
-}
-
-// +--------------------------------------------------------------------+
-
-void MFD::DrawMFDText(int index, const char* txt, Rect& txt_rect, int align, int status)
-{
- if (index >= MFD::TXT_LAST) {
- Print("MFD DrawMFDText() invalid mfd_text index %d '%s'\n", index, txt);
- }
- else {
- HUDText& mt = mfd_text[index];
- Color mc = mt.color;
-
- switch (status) {
- default:
- case System::NOMINAL: mc = txt_color; break;
- case System::DEGRADED: mc = Color(255,255, 0); break;
- case System::CRITICAL: mc = Color(255, 0, 0); break;
- case System::DESTROYED: mc = Color( 0, 0, 0); break;
- }
-
- char txt_buf[256];
- int n = strlen(txt);
-
- if (n > 250) n = 250;
- int i;
-
- for (i = 0; i < n; i++) {
- if (islower(txt[i]))
- txt_buf[i] = toupper(txt[i]);
- else
- txt_buf[i] = txt[i];
- }
-
- txt_buf[i] = 0;
-
-
- if (cockpit_hud_texture) {
- Rect hud_rect(txt_rect);
-
- hud_rect.x = txt_rect.x + this->index * 128 - this->rect.x;
- hud_rect.y = txt_rect.y + 256 - this->rect.y;
-
- mt.font->SetColor(mc);
- mt.font->DrawText(txt_buf, 0, hud_rect, align | DT_SINGLELINE, cockpit_hud_texture);
- mt.rect = rect;
- mt.hidden = false;
- }
- else {
- if (txt_rect.Contains(Mouse::X(), Mouse::Y()))
- mc = Color::White;
-
- mt.font->SetColor(mc);
- mt.font->DrawText(txt_buf, 0, txt_rect, align | DT_SINGLELINE);
- mt.rect = rect;
- mt.hidden = false;
- }
-
- }
-}
-
-void MFD::HideMFDText(int index)
-{
- if (index >= MFD::TXT_LAST)
- Print("MFD HideMFDText() invalid mfd_text index %d\n", index);
- else
- mfd_text[index].hidden = true;
-}
-
-
-
-