diff options
Diffstat (limited to 'Stars45/Mfd.cpp')
-rw-r--r-- | Stars45/Mfd.cpp | 1405 |
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; -} - - - - |