From 86686836c93525ec16219235de9d62624d6f80d9 Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Thu, 31 Aug 2023 11:03:18 +0300 Subject: [PATCH 1/8] Refactor cloaking in the game --- engine/CMakeLists.txt | 1 + engine/src/cmd/ai/fire.cpp | 4 +- engine/src/cmd/ai/firekeyboard.cpp | 4 +- engine/src/cmd/ai/firekeyboard.h | 1 - engine/src/cmd/ai/tactics.cpp | 6 +- engine/src/cmd/armed.cpp | 2 +- engine/src/cmd/basecomputer.cpp | 6 +- engine/src/cmd/briefing.cpp | 6 +- engine/src/cmd/cloak.cpp | 135 +++++++++++++++++ engine/src/cmd/cloak.h | 143 +++++++++++++++++ engine/src/cmd/cont_terrain.cpp | 3 +- engine/src/cmd/damageable.cpp | 5 +- engine/src/cmd/drawable.cpp | 48 +++--- engine/src/cmd/drawable.h | 6 +- engine/src/cmd/jump_capable.cpp | 2 +- engine/src/cmd/unit_csv.cpp | 34 +---- engine/src/cmd/unit_generic.cpp | 219 +++++---------------------- engine/src/cmd/unit_generic.h | 28 +--- engine/src/gfx/cockpit.cpp | 6 +- engine/src/gfx/halo_system.cpp | 4 +- engine/src/gfx/mesh.cpp | 2 +- engine/src/gfx/mesh.h | 14 +- engine/src/gfx/mesh_gfx.cpp | 54 +++---- engine/src/gfx/nav/navscreen.cpp | 4 +- engine/src/python/python_unit_wrap.h | 2 +- 25 files changed, 417 insertions(+), 322 deletions(-) create mode 100644 engine/src/cmd/cloak.cpp create mode 100644 engine/src/cmd/cloak.h diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 4b9e6aca1e..5e1040760e 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -827,6 +827,7 @@ SET(LIBCMD_SOURCES src/cmd/intelligent.cpp src/cmd/energetic.cpp + src/cmd/cloak.cpp src/cmd/planetary_orbit.cpp diff --git a/engine/src/cmd/ai/fire.cpp b/engine/src/cmd/ai/fire.cpp index 095ce08610..3c6d1b8769 100644 --- a/engine/src/cmd/ai/fire.cpp +++ b/engine/src/cmd/ai/fire.cpp @@ -430,7 +430,7 @@ class ChooseTargetClass { } bool ShouldTargetUnit(Unit *un, float distance) { - if (un->CloakVisible() > .8) { + if (un->cloak.Visible()) { float rangetotarget = distance; float rel0 = parent->getRelation(un); float rel[] = { @@ -841,7 +841,7 @@ void FireAt::Execute() { bool istargetjumpableplanet = false; if ((targ = parent->Target())) { istargetjumpableplanet = isJumpablePlanet(targ); - if (targ->CloakVisible() > .8 && !targ->Destroyed()) { + if (targ->cloak.Visible() && !targ->Destroyed()) { had_target = true; if (parent->getNumMounts() > 0) { if (!istargetjumpableplanet) { diff --git a/engine/src/cmd/ai/firekeyboard.cpp b/engine/src/cmd/ai/firekeyboard.cpp index 776aaf1e35..3f03e307d3 100644 --- a/engine/src/cmd/ai/firekeyboard.cpp +++ b/engine/src/cmd/ai/firekeyboard.cpp @@ -63,7 +63,6 @@ extern bool toggle_pause(); FireKeyboard::FireKeyboard(unsigned int whichplayer, unsigned int whichjoystick) : Order(WEAPON, 0) { memset(savedTargets, 0, sizeof(void *) * NUMSAVEDTARGETS); this->autotrackingtoggle = 1; - this->cloaktoggle = true; this->whichjoystick = whichjoystick; this->whichplayer = whichplayer; gunspeed = gunrange = .0001; @@ -1779,8 +1778,7 @@ void FireKeyboard::Execute() { } if (f().cloakkey == PRESS) { f().cloakkey = DOWN; - parent->Cloak(cloaktoggle); - cloaktoggle = !cloaktoggle; + parent->cloak.Toggle(); } if (f().lockkey == PRESS) { f().lockkey = DOWN; diff --git a/engine/src/cmd/ai/firekeyboard.h b/engine/src/cmd/ai/firekeyboard.h index 94c1431cbc..3cc6ca2cff 100644 --- a/engine/src/cmd/ai/firekeyboard.h +++ b/engine/src/cmd/ai/firekeyboard.h @@ -34,7 +34,6 @@ #define NUMSAVEDTARGETS 10 class FireKeyboard : public Order { bool itts; - bool cloaktoggle; bool refresh_target; float gunspeed; float gunrange; diff --git a/engine/src/cmd/ai/tactics.cpp b/engine/src/cmd/ai/tactics.cpp index adcbcaa9cd..86884d90be 100644 --- a/engine/src/cmd/ai/tactics.cpp +++ b/engine/src/cmd/ai/tactics.cpp @@ -31,13 +31,13 @@ void CloakFor::Execute() { if (time == 0) { - parent->Cloak(enable); + parent->cloak.Activate(); } time += SIMULATION_ATOM; if (time > maxtime) { done = true; if (maxtime != 0) { - parent->Cloak(!enable); + parent->cloak.Deactivate(); } return; } @@ -48,7 +48,7 @@ CloakFor::~CloakFor() { VS_LOG_AND_FLUSH(trace, (boost::format("clk%1$x") % this)); #endif if (parent && time <= maxtime) { - parent->Cloak(!enable); + parent->cloak.Deactivate(); } } diff --git a/engine/src/cmd/armed.cpp b/engine/src/cmd/armed.cpp index 25fa01bbc3..40f99bb2b6 100644 --- a/engine/src/cmd/armed.cpp +++ b/engine/src/cmd/armed.cpp @@ -199,7 +199,7 @@ void Armed::ActivateGuns(const WeaponInfo *sz, bool ms) { void Armed::Fire(unsigned int weapon_type_bitmask, bool listen_to_owner) { Unit *unit = static_cast(this); - if ((unit->cloaking >= 0 && !configuration()->weapons.can_fire_in_cloak) || + if ((unit->cloak.Active() && !configuration()->weapons.can_fire_in_cloak) || (unit->graphicOptions.InWarp && !configuration()->weapons.can_fire_in_spec)) { UnFire(); return; diff --git a/engine/src/cmd/basecomputer.cpp b/engine/src/cmd/basecomputer.cpp index e97d524dc8..63f243cf58 100644 --- a/engine/src/cmd/basecomputer.cpp +++ b/engine/src/cmd/basecomputer.cpp @@ -5565,17 +5565,17 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C } } //cloaking device? If we don't have one, no need to mention it ever exists, right? - if (playerUnit->cloaking != -1) { + if (playerUnit->cloak.Capable()) { if (!mode) { PRETTY_ADDU(statcolor + "Cloaking device available, energy usage: #-c", - playerUnit->cloakenergy * RSconverter * Wconv, + playerUnit->cloak.Energy() * RSconverter * Wconv, 0, "MJ/s"); } else { switch (replacement_mode) { case 0: //Replacement or new Module PRETTY_ADDU(statcolor + "Installs a cloaking device.#n# Activated energy usage: #-c", - playerUnit->cloakenergy * RSconverter * Wconv, + playerUnit->cloak.Energy() * RSconverter * Wconv, 0, "MJ/s"); break; diff --git a/engine/src/cmd/briefing.cpp b/engine/src/cmd/briefing.cpp index 436c5d733e..537368fead 100644 --- a/engine/src/cmd/briefing.cpp +++ b/engine/src/cmd/briefing.cpp @@ -116,11 +116,7 @@ void Briefing::Ship::Render(const Matrix &cam, double interpol) { Matrix camfinal; MultMatrix(camfinal, cam, final); for (unsigned int i = 0; i < meshdata.size(); i++) { - int scloak = int(cloak * ((-1) > 1)); //FIXME short fix? - if ((scloak & 0x1) == 0) { - scloak += 1; - } - meshdata[i]->Draw(1, camfinal, 1, cloak > .99 ? -1 : scloak); + meshdata[i]->Draw(1, camfinal, 1); } } diff --git a/engine/src/cmd/cloak.cpp b/engine/src/cmd/cloak.cpp new file mode 100644 index 0000000000..127969770f --- /dev/null +++ b/engine/src/cmd/cloak.cpp @@ -0,0 +1,135 @@ +/* + * cloak.cpp + * + * Copyright (C) 2001-2023 Daniel Horn, Benjaman Meyer, Roy Falk, Stephen G. Tuggy, + * and other Vega Strike contributors. + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +#include "cloak.h" +#include "unit_csv_factory.h" +#include "vegastrike.h" +#include "configuration/configuration.h" + +Cloak::Cloak() +{ + status = CloakingStatus::disabled; + + energy = 0; + rate = 100; + glass = false; + current = 0; + minimum = 0; +} + +Cloak::Cloak(std::string unit_key) +{ + if(UnitCSVFactory::GetVariable(unit_key, "Can_Cloak", false)) { + status = CloakingStatus::ready; + } else { + status = CloakingStatus::disabled; + } + + glass = UnitCSVFactory::GetVariable(unit_key, "Cloak_Glass", false); + rate = UnitCSVFactory::GetVariable(unit_key, "Cloak_Rate", 0.0); + energy = UnitCSVFactory::GetVariable(unit_key, "Cloak_Energy", 0.0); + minimum = UnitCSVFactory::GetVariable(unit_key, "Cloak_Min", 0.0); + minimum = std::min(1.0, std::max(0.0, minimum)); + current = 0; +} + +void Cloak::Update(Energetic *energetic) +{ + // Unit is not capable of cloaking or damaged or just not cloaking + if(status == CloakingStatus::disabled || + status == CloakingStatus::damaged || + status == CloakingStatus::ready) { + return; + } + + // Use warp power for cloaking (SPEC capacitor) + const static bool warp_energy_for_cloak = configuration()->warp_config.use_warp_energy_for_cloak; + double available_energy = warp_energy_for_cloak ? energetic->warpenergy : energetic->energy.Value(); + + + // Insufficient energy to cloak ship + if(available_energy < this->energy) { + status = CloakingStatus::decloaking; + } else { + // Subtract the energy used + if (warp_energy_for_cloak) { + energetic->warpenergy -= (simulation_atom_var * energy); + } else { + energetic->energy -= (simulation_atom_var * energy); + } + } + + if(status == CloakingStatus::decloaking) { + current = std::max(0.0, current - rate * simulation_atom_var); + + if(current == 0) { + status = CloakingStatus::ready; + } + } + + if(status == CloakingStatus::cloaking) { + current = std::min(1.0, current + rate * simulation_atom_var); + + if(current > minimum) { + status = CloakingStatus::cloaked; + } + } + + +} + +void Cloak::Toggle() { + // Unit is not capable of cloaking or damaged + if(status == CloakingStatus::disabled || + status == CloakingStatus::damaged) { + return; + } + + // If we're ready start cloaking + if(status == CloakingStatus::ready) { + status = CloakingStatus::cloaking; + return; + } + + // In any other case, start decloaking + status = CloakingStatus::decloaking; +} + +void Cloak::Activate() { + if(status == CloakingStatus::ready) { + status = CloakingStatus::cloaking; + } +} + +void Cloak::Deactivate() { + // Unit is not capable of cloaking or damaged or just not cloaking + if(status == CloakingStatus::disabled || + status == CloakingStatus::damaged || + status == CloakingStatus::ready) { + return; + } + + // Start decloaking + status = CloakingStatus::decloaking; +} diff --git a/engine/src/cmd/cloak.h b/engine/src/cmd/cloak.h new file mode 100644 index 0000000000..7a708a40f5 --- /dev/null +++ b/engine/src/cmd/cloak.h @@ -0,0 +1,143 @@ +/* + * cloak.h + * + * Copyright (C) 2001-2023 Daniel Horn, Benjaman Meyer, Roy Falk, Stephen G. Tuggy, + * and other Vega Strike contributors. + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +#ifndef CLOAK_H +#define CLOAK_H + +#include + +#include "energetic.h" +#include "damageable_layer.h" + +enum class CloakingStatus { + disabled, + damaged, + ready, + cloaking, + cloaked, + decloaking +}; + +class Cloak +{ + friend class Unit; + + CloakingStatus status; + + // How much energy cloaking takes per frame + double energy; + + // How fast does this starship cloak/decloak + double rate; + + // If this unit cloaks like glass or like fading. + // Glass is alpha only. Non glass affects rgb as well. + bool glass; + + // Current cloak value. 0 is uncloaked. 1 is fully cloaked. + double current; + + // The minimum cloaking value... + double minimum; + +public: + Cloak(); + Cloak(std::string unit_key); + + void Update(Energetic *energetic); + void Toggle(); // Toggle cloak on/off + + bool Capable() const { + return (status != CloakingStatus::disabled); + } + + bool Cloaking() { + return (status == CloakingStatus::cloaking); + } + + bool Cloaked() { + return (status == CloakingStatus::cloaked); + } + + // Active is cloaking, cloaked or decloaking + bool Active() { + return (status == CloakingStatus::cloaking || + status == CloakingStatus::cloaked || + status == CloakingStatus::decloaking); + } + + bool Damaged() { + return (status == CloakingStatus::damaged); + } + + bool Ready() { + return (status == CloakingStatus::ready); + } + + bool Glass() { + return glass; + } + + double Current() { + return current; + } + + double Energy() { + return energy; + } + + //how visible the ship is from 0 to 1 + double Visible() const { + return 1-current; + } + + // TODO: more granular damage + // TODO: damageable component + void Damage() { + status = CloakingStatus::damaged; + current = 0; + } + + void Repair() { + if(status == CloakingStatus::damaged) { + status = CloakingStatus::ready; + current = 0; + } + } + + void Disable() { + status = CloakingStatus::disabled; + current = 0; + } + + void Enable() { + status = CloakingStatus::ready; + current = 0; + } + + void Activate(); + void Deactivate(); +}; + +#endif // CLOAK_H diff --git a/engine/src/cmd/cont_terrain.cpp b/engine/src/cmd/cont_terrain.cpp index d7a15c9393..fcac14c502 100644 --- a/engine/src/cmd/cont_terrain.cpp +++ b/engine/src/cmd/cont_terrain.cpp @@ -287,7 +287,8 @@ void ContinuousTerrain::Draw() { md[i].mesh->rSize() ); if (d) { - md[i].mesh->Draw(1000, md[i].mat, d, -1, (_Universe->AccessCamera()->GetNebula() != NULL) ? -1 : 0); + static Cloak dummy_cloak; + md[i].mesh->Draw(1000, md[i].mat, d, dummy_cloak, (_Universe->AccessCamera()->GetNebula() != NULL) ? -1 : 0); } } } diff --git a/engine/src/cmd/damageable.cpp b/engine/src/cmd/damageable.cpp index 8ab291bf7a..7847c00040 100644 --- a/engine/src/cmd/damageable.cpp +++ b/engine/src/cmd/damageable.cpp @@ -565,8 +565,9 @@ void Damageable::RegenerateShields(const float difficulty, const bool player_shi } - // Discharge shields due to energy or SPEC - if ((in_warp && !shields_in_spec) || !unit->sufficient_energy_to_recharge_shields) { + // Discharge shields due to energy or SPEC or cloak + if ((in_warp && !shields_in_spec) || !unit->sufficient_energy_to_recharge_shields || + unit->cloak.Active()) { shield->Discharge(discharge_rate, min_shield_discharge); } else { // Shield regeneration diff --git a/engine/src/cmd/drawable.cpp b/engine/src/cmd/drawable.cpp index a4095163a5..0c357a37ea 100644 --- a/engine/src/cmd/drawable.cpp +++ b/engine/src/cmd/drawable.cpp @@ -204,15 +204,10 @@ void Drawable::Draw(const Transformation &parent, const Matrix &parentMatrix) { bool On_Screen = false; bool Unit_On_Screen = false; float Apparent_Size = 0.0f; - int cloak = unit->cloaking; Matrix wmat; if (!cam_setup_phase) { // Following stuff is only needed in actual drawing phase - if (unit->cloaking > unit->cloakmin) { - cloak = (int) (unit->cloaking - interpolation_blend_factor * unit->cloakrate * simulation_atom_var); - cloak = cloakVal(cloak, unit->cloakmin, unit->cloakrate, unit->cloakglass); - } if ((*unit->current_hull) < (*unit->max_hull)) { damagelevel = (*unit->current_hull) / (*unit->max_hull); chardamage = (255 - (unsigned char) (damagelevel * 255)); @@ -272,10 +267,9 @@ void Drawable::Draw(const Transformation &parent, const Matrix &parentMatrix) { if (frustd) { //if the radius is at least half a pixel at detail 1 (equivalent to pixradius >= 0.5 / detail) float currentFrame = meshdata[i]->getCurrentFrame(); - this->meshdata[i]->Draw(lod, wmat, d, - i == this->meshdata.size() - 1 ? -1 : cloak, + this->meshdata[i]->Draw(lod, wmat, d, unit->cloak, (camera->GetNebula() == unit->nebula && unit->nebula != NULL) ? -1 : 0, - chardamage); //cloakign and nebula + chardamage); //cloaking and nebula On_Screen = true; unsigned int numAnimFrames = 0; static const string default_animation; @@ -349,8 +343,8 @@ void Drawable::Draw(const Transformation &parent, const Matrix &parentMatrix) { return; } - DrawSubunits(On_Screen, wmat, cloak, avgscale, chardamage); - DrawHalo(On_Screen, Apparent_Size, wmat, cloak); + DrawSubunits(On_Screen, wmat, unit->cloak, avgscale, chardamage); + DrawHalo(On_Screen, Apparent_Size, wmat, unit->cloak); Sparkle(On_Screen, ctm); } @@ -412,10 +406,7 @@ void Drawable::DrawNow(const Matrix &mato, float lod) { pos = mato.p; VectorAndPositionToMatrix(mat, p, q, r, pos); } - int cloak = unit->cloaking; - if (unit->cloaking > unit->cloakmin) { - cloak = cloakVal(cloak, unit->cloakmin, unit->cloakrate, unit->cloakglass); - } + for (i = 0; i <= this->nummesh(); i++) { //NOTE LESS THAN OR EQUALS...to cover shield mesh if (this->meshdata[i] == NULL) { @@ -426,7 +417,7 @@ void Drawable::DrawNow(const Matrix &mato, float lod) { float d = GFXSphereInFrustum(TransformedPosition, this->meshdata[i]->clipRadialSize() * vlpqrScaleFactor); if (d) { //d can be used for level of detail //this->meshdata[i]->DrawNow(lod,false,mat,cloak);//cloakign and nebula - this->meshdata[i]->Draw(lod, mat, d, cloak); + this->meshdata[i]->Draw(lod, mat, d, unit->cloak); } } Unit *un; @@ -468,22 +459,20 @@ void Drawable::DrawNow(const Matrix &mato, float lod) { (d - gun->rSize() < g_game.znear) ? g_game.znear : d - gun->rSize()); ScaleMatrix(mmat, Vector(mahnt->xyscale, mahnt->xyscale, mahnt->zscale)); gun->setCurrentFrame(unit->mounts[i].ComputeAnimatedFrame(gun)); - gun->Draw(lod, mmat, d, cloak, - (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula != NULL) ? -1 + gun->Draw(lod, mmat, d, unit->cloak, (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula != NULL) ? -1 : 0, chardamage, true); //cloakign and nebula if (mahnt->type->gun1) { gun = mahnt->type->gun1; gun->setCurrentFrame(unit->mounts[i].ComputeAnimatedFrame(gun)); - gun->Draw(lod, - mmat, - d, - cloak, - (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula + gun->Draw(lod, mmat, + d, + unit->cloak, + (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula != NULL) ? -1 : 0, - chardamage, - true); //cloakign and nebula + chardamage, + true); //cloakign and nebula } } } @@ -497,7 +486,7 @@ void Drawable::DrawNow(const Matrix &mato, float lod) { if (!(unit->docked & (unit->DOCKED | unit->DOCKED_INSIDE))) { halos->Draw(mat, Scale, - cloak, + unit->cloak.Visible(), 0, unit->GetHullPercent(), velocity, @@ -707,7 +696,7 @@ void Drawable::Sparkle(bool on_screen, Matrix *ctm) { } } -void Drawable::DrawHalo(bool on_screen, float apparent_size, Matrix wmat, int cloak) { +void Drawable::DrawHalo(bool on_screen, float apparent_size, Matrix wmat, Cloak cloak) { Unit *unit = vega_dynamic_cast_ptr(this); // Units not shown don't emit a halo @@ -746,12 +735,12 @@ void Drawable::DrawHalo(bool on_screen, float apparent_size, Matrix wmat, int cl //nor is maxaccel. Instead, each halo should have its own limits specified in units.csv float nebd = (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula != nullptr) ? -1 : 0; float hulld = unit->GetHull() > 0 ? damage_level : 1.0; - halos->Draw(wmat, Scale, cloak, nebd, hulld, velocity, + halos->Draw(wmat, Scale, unit->cloak.Visible(), nebd, hulld, velocity, linaccel, angaccel, maxaccel, cmas, unit->faction); } -void Drawable::DrawSubunits(bool on_screen, Matrix wmat, int cloak, float average_scale, unsigned char char_damage) { +void Drawable::DrawSubunits(bool on_screen, Matrix wmat, Cloak cloak, float average_scale, unsigned char char_damage) { Unit *unit = vega_dynamic_cast_ptr(this); Transformation *ct = &unit->cumulative_transformation; @@ -811,8 +800,7 @@ void Drawable::DrawSubunits(bool on_screen, Matrix wmat, int cloak, float averag if (lod > 0.5 && pixradius > 2.5) { ScaleMatrix(mat, Vector(mount->xyscale, mount->xyscale, mount->zscale)); gun->setCurrentFrame(unit->mounts[i].ComputeAnimatedFrame(gun)); - gun->Draw(lod, mat, d, cloak, - (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula != NULL) ? -1 : 0, + gun->Draw(lod, mat, d, cloak, (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula != NULL) ? -1 : 0, char_damage, true); //cloakign and nebula } diff --git a/engine/src/cmd/drawable.h b/engine/src/cmd/drawable.h index 119305b1a8..dc0db5d7ee 100644 --- a/engine/src/cmd/drawable.h +++ b/engine/src/cmd/drawable.h @@ -32,6 +32,8 @@ #include #include +#include "cloak.h" + class Mesh; class Flightgroup; class Unit; @@ -134,8 +136,8 @@ class Drawable { virtual std::string drawableGetName() = 0; void Sparkle(bool on_screen, Matrix *ctm); - void DrawHalo(bool on_screen, float apparent_size, Matrix wmat, int cloak); - void DrawSubunits(bool on_screen, Matrix wmat, int cloak, float average_scale, unsigned char char_damage); + void DrawHalo(bool on_screen, float apparent_size, Matrix wmat, Cloak cloak); + void DrawSubunits(bool on_screen, Matrix wmat, Cloak cloak, float average_scale, unsigned char char_damage); //Split this mesh with into 2^level submeshes at arbitrary planes void Split(int level); diff --git a/engine/src/cmd/jump_capable.cpp b/engine/src/cmd/jump_capable.cpp index d8930247d6..571b470fb7 100644 --- a/engine/src/cmd/jump_capable.cpp +++ b/engine/src/cmd/jump_capable.cpp @@ -212,7 +212,7 @@ bool JumpCapable::AutoPilotToErrorMessage(const Unit *target, XMLSupport::parse_bool(vs_config->getVariable("physics", "teleport_autopilot", "true")); bool unsafe = false; if ((!teleport_autopilot) && (!nanspace)) { - if (Guaranteed == Mission::AUTO_NORMAL && unit->CloakVisible() > .5) { + if (Guaranteed == Mission::AUTO_NORMAL && unit->cloak.Cloaked()) { bool ignore_friendlies = true; for (un_iter i = ss->getUnitList().createIterator(); (un = *i) != NULL; ++i) { static bool canflythruplanets = diff --git a/engine/src/cmd/unit_csv.cpp b/engine/src/cmd/unit_csv.cpp index 91d28caa76..7c1d8bd806 100644 --- a/engine/src/cmd/unit_csv.cpp +++ b/engine/src/cmd/unit_csv.cpp @@ -922,28 +922,8 @@ void Unit::LoadRow(std::string unit_identifier, string modification, bool saved_ computer.radar.trackingcone = cos(UnitCSVFactory::GetVariable(unit_key, "Tracking_Cone", 180.0f) * VS_PI / 180); computer.radar.lockcone = cos(UnitCSVFactory::GetVariable(unit_key, "Lock_Cone", 180.0f) * VS_PI / 180); - cloakmin = static_cast(UnitCSVFactory::GetVariable(unit_key, "Cloak_Min", 0.0f) * 2147483136); - if (cloakmin < 0) { - cloakmin = 0; - } - - cloakglass = UnitCSVFactory::GetVariable(unit_key, "Cloak_Glass", false); - if ((cloakmin & 0x1) && !cloakglass) { - cloakmin -= 1; - } - - if ((cloakmin & 0x1) == 0 && cloakglass) { - cloakmin += 1; - } + cloak = Cloak(unit_key); - if (!UnitCSVFactory::GetVariable(unit_key, "Can_Cloak", false)) { - cloaking = -1; - } else { - cloaking = (int) (-2147483647) - 1; - } - - cloakrate = (int) (2147483136.0 * UnitCSVFactory::GetVariable(unit_key, "Cloak_Rate", 0.0f)); //short fix - cloakenergy = UnitCSVFactory::GetVariable(unit_key, "Cloak_Energy", 0.0f); repair_droid = UnitCSVFactory::GetVariable(unit_key, "Repair_Droid", 0); ecm = UnitCSVFactory::GetVariable(unit_key, "ECM_Rating", 0); @@ -1384,11 +1364,13 @@ string Unit::WriteUnitString() { unit["Tracking_Cone"] = tos(acos(computer.radar.trackingcone) * 180. / VS_PI); unit["Max_Cone"] = tos(acos(computer.radar.maxcone) * 180. / VS_PI); unit["Lock_Cone"] = tos(acos(computer.radar.lockcone) * 180. / VS_PI); - unit["Cloak_Min"] = tos(cloakmin / 2147483136.); - unit["Can_Cloak"] = tos(cloaking != -1); - unit["Cloak_Rate"] = tos(fabs(cloakrate / 2147483136.)); - unit["Cloak_Energy"] = tos(cloakenergy); - unit["Cloak_Glass"] = tos(cloakglass); + + // TODO: move to Cloak + unit["Cloak_Min"] = tos(cloak.minimum); + unit["Can_Cloak"] = tos(cloak.Capable()); + unit["Cloak_Rate"] = tos(cloak.rate); + unit["Cloak_Energy"] = tos(cloak.energy); + unit["Cloak_Glass"] = tos(cloak.glass); unit["Repair_Droid"] = tos(repair_droid); unit["ECM_Rating"] = tos(ecm > 0 ? ecm : -ecm); unit["Hud_Functionality"] = WriteHudDamage(this); diff --git a/engine/src/cmd/unit_generic.cpp b/engine/src/cmd/unit_generic.cpp index 410f02f861..4a236c2f53 100644 --- a/engine/src/cmd/unit_generic.cpp +++ b/engine/src/cmd/unit_generic.cpp @@ -133,7 +133,7 @@ void Unit::SetNebula(Nebula *neb) { bool Unit::InRange(const Unit *target, double &mm, bool cone, bool cap, bool lock) const { const float capship_size = configuration()->physics_config.capship_size; - if (this == target || target->CloakVisible() < .8) { + if (this == target || !target->cloak.Visible()) { return false; } if (cone && computer.radar.maxcone > -.98) { @@ -956,8 +956,11 @@ void Unit::UpdateSubunitPhysics(Unit *subunit, lastframe, uc, superunit); - //short fix - subunit->cloaking = (unsigned int) cloaking; + + // TODO: make the subunit->cloak a pointer to parent->cloak + // Also, no reason why subunits should handle their own physics but that's + // much harder to refactor + subunit->cloak.status = cloak.status; if (Destroyed()) { subunit->Target(NULL); UnFire(); //don't want to go off shooting while your body's splitting everywhere @@ -1293,14 +1296,8 @@ void Unit::DamageRandSys(float dam, const Vector &vec, float randnum, float degr if (degrees >= 90 && degrees < 120) { //DAMAGE Shield //DAMAGE cloak - if (randnum >= .95) { - this->cloaking = -1; - damages |= Damages::CLOAK_DAMAGED; - } else if (randnum >= .78) { - cloakenergy += ((1 - dam) * recharge); - damages |= Damages::CLOAK_DAMAGED; - } else if (randnum >= .7) { - cloakmin += (rand() % (32000 - cloakmin)); + if (randnum >= .7) { + this->cloak.Damage(); damages |= Damages::CLOAK_DAMAGED; } @@ -1661,25 +1658,12 @@ void Unit::SetOwner(Unit *target) { owner = target; } -void Unit::Cloak(bool loak) { - damages |= Damages::CLOAK_DAMAGED; - if (loak) { - static bool warp_energy_for_cloak = - XMLSupport::parse_bool(vs_config->getVariable("physics", "warp_energy_for_cloak", "true")); - if (cloakenergy < (warp_energy_for_cloak ? warpenergy : energy.Value())) { - cloakrate = (cloakrate >= 0) ? cloakrate : -cloakrate; - //short fix - if (cloaking < -1 && cloakrate != 0) { - //short fix - cloaking = 2147483647; - } else { - } - } +// Need this for python API. Do not delete. +void Unit::ActivateCloak(bool enable) { + if(enable) { + cloak.Activate(); } else { - cloakrate = (cloakrate >= 0) ? -cloakrate : cloakrate; - if (cloaking == cloakmin) { - ++cloaking; - } + cloak.Deactivate(); } } @@ -3344,14 +3328,14 @@ bool Unit::UpAndDownGrade(const Unit *up, tempdownmap); } } - if (cloaking != -1 && up->cloaking != -1) { + if (cloak.Capable() && up->cloak.Capable()) { if (touchme) { - cloaking = -1; + cloak.Disable(); } ++numave; ++percentage; if (gen_downgrade_list) { - AddToDowngradeMap(up->name, up->cloaking, ((char *) &this->cloaking) - ((char *) this), tempdownmap); + AddToDowngradeMap(up->name, up->cloak.current, ((char *) &this->cloak.current) - ((char *) this), tempdownmap); } } //NOTE: Afterburner type 2 (jmp) @@ -3380,16 +3364,17 @@ bool Unit::UpAndDownGrade(const Unit *up, } } } - if ((cloaking == -1 && up->cloaking != -1) || force_change_on_nothing) { + if ((!cloak.Capable() && up->cloak.Capable()) || force_change_on_nothing) { if (touchme) { - cloaking = up->cloaking; - cloakmin = up->cloakmin; - cloakrate = up->cloakrate; - cloakglass = up->cloakglass; - cloakenergy = up->cloakenergy; + cloak.Enable(); + + cloak.minimum = up->cloak.minimum; + cloak.rate = up->cloak.rate; + cloak.glass = up->cloak.glass; + cloak.energy = up->cloak.energy; } ++numave; - } else if (cloaking != -1 && up->cloaking != -1) { + } else if (cloak.Capable() && up->cloak.Capable()) { cancompletefully = false; } //NOTE: Afterburner type 2 (jmp) @@ -4259,95 +4244,7 @@ void Unit::applyTechniqueOverrides(const std::map &ove std::map Drawable::Units; -//helper func for Init -string toLowerCase(string in) { - string out; - for (unsigned int i = 0; i < in.length(); i++) { - switch (in[i]) { - case 'A': - out += 'a'; - break; - case 'B': - out += 'b'; - break; - case 'C': - out += 'c'; - break; - case 'D': - out += 'd'; - break; - case 'E': - out += 'e'; - break; - case 'F': - out += 'f'; - break; - case 'G': - out += 'g'; - break; - case 'H': - out += 'h'; - break; - case 'I': - out += 'i'; - break; - case 'J': - out += 'j'; - break; - case 'K': - out += 'k'; - break; - case 'L': - out += 'l'; - break; - case 'M': - out += 'm'; - break; - case 'N': - out += 'n'; - break; - case 'O': - out += 'o'; - break; - case 'P': - out += 'p'; - break; - case 'Q': - out += 'q'; - break; - case 'R': - out += 'r'; - break; - case 'S': - out += 's'; - break; - case 'T': - out += 't'; - break; - case 'U': - out += 'u'; - break; - case 'V': - out += 'v'; - break; - case 'W': - out += 'w'; - break; - case 'X': - out += 'x'; - break; - case 'Y': - out += 'y'; - break; - case 'Z': - out += 'z'; - break; - default: - out += in[i]; - } - } - return out; -} + unsigned int Drawable::unitCount = 0; @@ -4434,7 +4331,18 @@ void Unit::UpdatePhysics3(const Transformation &trans, if (fuel < 0) { fuel = 0; } - UpdateCloak(); + + static CloakingStatus previous_status = cloak.status; + cloak.Update(this); + + // Play once per cloaking + if(cloak.Cloaking() && previous_status != CloakingStatus::cloaking) { + previous_status = cloak.status; + playSound(SoundType::cloaking); + } else if(cloak.Cloaked() && previous_status != CloakingStatus::cloaked) { + previous_status = cloak.status; + adjustSound(SoundType::cloaking, cumulative_transformation.position, cumulative_velocity); + } // Recharge energy and shields const bool apply_difficulty_shields = configuration()->physics_config.difficulty_based_shield_recharge; @@ -4487,7 +4395,7 @@ void Unit::UpdatePhysics3(const Transformation &trans, float dist_sqr_to_target = FLT_MAX; Unit *target = Unit::Target(); bool increase_locking = false; - if (target && cloaking < 0 /*-1 or -32768*/) { + if (target && !cloak.Cloaked()) { if (target->isUnit() != Vega_UnitType::planet) { Vector TargetPos(InvTransform(cumulative_transformation_matrix, (target->Position())).Cast()); dist_sqr_to_target = TargetPos.MagnitudeSquared(); @@ -4530,7 +4438,7 @@ void Unit::UpdatePhysics3(const Transformation &trans, // TODO: simplify this if if (((false && mounts[i].status - == Mount::INACTIVE) || mounts[i].status == Mount::ACTIVE) && cloaking < 0 + == Mount::INACTIVE) || mounts[i].status == Mount::ACTIVE) && !cloak.Cloaked() && mounts[i].ammo != 0) { if (player_cockpit) { touched = true; @@ -4729,55 +4637,6 @@ void Unit::UpdatePhysics3(const Transformation &trans, } } -void Unit::UpdateCloak() { - // Use warp power for cloaking (SPEC capacitor) - const bool warp_energy_for_cloak = configuration()->warp_config.use_warp_energy_for_cloak; - - // We are not cloaked - exiting function - if (cloaking < cloakmin) { - return; - } - - // Insufficient energy to cloak ship - if (cloakenergy * simulation_atom_var > (warp_energy_for_cloak ? warpenergy : energy.Value())) { - Cloak(false); - return; - } - - // Cloaked ships don't have shields on - shield->Disable(); - - // We're cloaked - if (cloaking > cloakmin) { - adjustSound(SoundType::cloaking, cumulative_transformation.position, cumulative_velocity); - - //short fix - // TODO: figure out what they have fixed - if ((cloaking == (2147483647) - && cloakrate > 0) || (cloaking == cloakmin + 1 && cloakrate < 0)) { - playSound(SoundType::cloaking); - } - - //short fix - // TODO: figure out what they have fixed - cloaking -= (int) (cloakrate * simulation_atom_var); - if (cloaking <= cloakmin && cloakrate > 0) { - cloaking = cloakmin; - } - if (cloaking < 0 && cloakrate < 0) { - cloaking = -2147483647 - 1; - } - } - - // Calculate energy drain - if (cloakrate > 0 || cloaking == cloakmin) { - if (warp_energy_for_cloak) { - warpenergy -= (simulation_atom_var * cloakenergy); - } else { - energy -= (simulation_atom_var * cloakenergy); - } - } -} bool Unit::isPlayerShip() { return _Universe->isPlayerStarship(this) ? true : false; diff --git a/engine/src/cmd/unit_generic.h b/engine/src/cmd/unit_generic.h index 75aec3451f..4031de1f71 100644 --- a/engine/src/cmd/unit_generic.h +++ b/engine/src/cmd/unit_generic.h @@ -76,6 +76,7 @@ void UncheckUnit( class Unit*un ); #include "SharedPool.h" #include "role_bitmask.h" #include "upgradeable_unit.h" +#include "cloak.h" #include "configuration/configuration.h" #include "configuration/game_config.h" @@ -136,11 +137,14 @@ struct PlanetaryOrbitData; // TODO: move Armed to subclasses class Unit : public Armed, public Audible, public Drawable, public Damageable, public Energetic, public Intelligent, public Movable, public JumpCapable, public Carrier, public UpgradeableUnit { + protected: //How many lists are referencing us int ucref = 0; StringPool::Reference csvRow; + public: + Cloak cloak; /// Radar and related systems // TODO: take a deeper look at this much later... @@ -584,20 +588,6 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p float shieldtight = configuration()->physics_config.default_shield_tightness; public: - // TODO: move cloak to Cloakable? - ///How much energy cloaking takes per frame - float cloakenergy = 0; - ///how fast this starship decloaks/close...if negative, decloaking - int cloakrate = 100; //short fix - ///If this unit cloaks like glass or like fading - bool cloakglass = false; - - //-1 is not available... ranges between 0 32767 for "how invisible" unit currently is (32768... -32768) being visible) - // Despite the above comment, Init() would set it to -1 - int cloaking = -1; //short fix -//the minimum cloaking value... - int cloakmin = cloakglass ? 1 : 0; //short fix - // TODO: move to jump_capable? ///if the unit is a wormhole bool forcejump = false; @@ -613,16 +603,14 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p return ToLocalCoordinates((un->Position() - Position()).Cast()); } -//how visible the ship is from 0 to 1 +// how visible the ship is from 0 to 1 +// Need this function to expose it to python float CloakVisible() const { - if (cloaking < 0) { - return 1; - } - return ((float) cloaking) / 2147483647; + cloak.Visible(); } //cloaks or decloaks the starship depending on the bool - virtual void Cloak(bool cloak); + virtual void ActivateCloak(bool cloak); //deletes void Kill(bool eraseFromSave = true, bool quitting = false); diff --git a/engine/src/gfx/cockpit.cpp b/engine/src/gfx/cockpit.cpp index a8205c6ccd..fc4dcb7694 100644 --- a/engine/src/gfx/cockpit.cpp +++ b/engine/src/gfx/cockpit.cpp @@ -681,11 +681,11 @@ float GameCockpit::LookupUnitStat(int stat, Unit *target) { return (float) UnitImages::NOTAPPLICABLE; } case UnitImages::CLOAK_MODAL: - if (-1 == target->cloaking) { + if (!target->cloak.Capable() || target->cloak.Damaged()) { return (float) UnitImages::NOTAPPLICABLE; - } else if (((int) (-2147483647) - 1) == target->cloaking) { + } else if (target->cloak.Ready()) { return (float) UnitImages::READY; - } else if (target->cloaking == target->cloakmin) { + } else if (target->cloak.Cloaked()) { return (float) UnitImages::ACTIVE; } else { return (float) UnitImages::SWITCHING; diff --git a/engine/src/gfx/halo_system.cpp b/engine/src/gfx/halo_system.cpp index 7e723175bb..272d31813e 100644 --- a/engine/src/gfx/halo_system.cpp +++ b/engine/src/gfx/halo_system.cpp @@ -243,7 +243,9 @@ void HaloSystem::Draw(const Matrix &trans, GFXColor(1, 1, 1, 1), GFXColor(1, 1, 1, 1), blend); - i->mesh->Draw(50000000000000.0, m, 1, alpha, nebdist, 0, false, &xtraFX); + + static Cloak dummy_cloak; + i->mesh->Draw(50000000000000.0, m, alpha, dummy_cloak, nebdist, 0, false, &xtraFX); // If damaged, and halo is back-facing if (hullpercent < .99 && ((i->trans.getR().z / i->trans.getR().Magnitude()) > 0.707)) { diff --git a/engine/src/gfx/mesh.cpp b/engine/src/gfx/mesh.cpp index 9db212e539..0ba65b852a 100644 --- a/engine/src/gfx/mesh.cpp +++ b/engine/src/gfx/mesh.cpp @@ -50,7 +50,7 @@ #include "lin_time.h" #include "mesh_xml.h" #include "gfx/technique.h" -#include +#include #include #define LOD_HYSTHERESIS_DIVIDER (20) diff --git a/engine/src/gfx/mesh.h b/engine/src/gfx/mesh.h index aec5e45876..7998181530 100644 --- a/engine/src/gfx/mesh.h +++ b/engine/src/gfx/mesh.h @@ -343,13 +343,13 @@ class Mesh { ///Draws lod pixel wide mesh at Transformation LATER void Draw(float lod, - const Matrix &m = identity_matrix, - float toofar = 1, - int cloak = -1, - float nebdist = 0, - unsigned char damage = 0, - bool renormalize_normals = false, - const MeshFX *mfx = NULL); //short fix + const Matrix &m = identity_matrix, + float toofar = 1, + Cloak cloak = Cloak(), + float nebdist = 0, + unsigned char damage = 0, + bool renormalize_normals = false, + const MeshFX *mfx = NULL); //short fix ///Draws lod pixels wide, mesh at Transformation NOW. If centered, then will center on camera and disable cull void DrawNow(float lod, bool centered, diff --git a/engine/src/gfx/mesh_gfx.cpp b/engine/src/gfx/mesh_gfx.cpp index d9f8ba0018..1ebc3d8aee 100644 --- a/engine/src/gfx/mesh_gfx.cpp +++ b/engine/src/gfx/mesh_gfx.cpp @@ -465,13 +465,13 @@ Mesh::~Mesh() { } void Mesh::Draw(float lod, - const Matrix &m, - float toofar, - int cloak, - float nebdist, - unsigned char hulldamage, - bool renormalize, - const MeshFX *mfx) //short fix + const Matrix &m, + float toofar, + Cloak cloak, + float nebdist, + unsigned char hulldamage, + bool renormalize, + const MeshFX *mfx) //short fix { Mesh *origmesh = getLOD(lod); if (origmesh->rSize() > 0) { @@ -486,6 +486,8 @@ void Mesh::Draw(float lod, c.damage = hulldamage; c.mesh_seq = ((toofar + rSize()) > g_game.zfar) ? NUM_ZBUF_SEQ : draw_sequence; + + // Cloaking and Nebula c.cloaked = MeshDrawContext::NONE; if (nebdist < 0) { c.cloaked |= MeshDrawContext::FOG; @@ -493,30 +495,30 @@ void Mesh::Draw(float lod, if (renormalize) { c.cloaked |= MeshDrawContext::RENORMALIZE; } - if (cloak >= 0) { + + // This should have gradually made the ship cloak go transparent + // for cloak.Glass but it does the same thing as the ordinary cloak. + // TODO: revisit this. + if(cloak.Active()) { c.cloaked |= MeshDrawContext::CLOAK; - if ((cloak & 0x1)) { - c.cloaked |= MeshDrawContext::GLASSCLOAK; - c.mesh_seq = MESH_SPECIAL_FX_ONLY; //draw near the end with lights + c.cloaked |= MeshDrawContext::GLASSCLOAK; + + if (cloak.Glass()) { + c.CloakFX.a = cloak.Current(); + c.mesh_seq = 2; //MESH_SPECIAL_FX_ONLY; } else { c.mesh_seq = 2; + c.CloakFX.r = (1-cloak.Current()); + c.CloakFX.g = (1-cloak.Current()); + c.CloakFX.b = (1-cloak.Current()); + c.CloakFX.a = cloak.Current(); } - if (cloak <= CLKSCALE / 2) { - c.cloaked |= MeshDrawContext::NEARINVIS; - } - float tmp = ((float) cloak) / CLKSCALE; - c.CloakFX.r = (c.cloaked & MeshDrawContext::GLASSCLOAK) ? tmp : 1; - c.CloakFX.g = (c.cloaked & MeshDrawContext::GLASSCLOAK) ? tmp : 1; - c.CloakFX.b = (c.cloaked & MeshDrawContext::GLASSCLOAK) ? tmp : 1; - c.CloakFX.a = tmp; - /* - * c.CloakNebFX.ambient[0]=((float)cloak)/CLKSCALE; - * c.CloakNebFX.ag=((float)cloak)/CLKSCALE; - * c.CloakNebFX.ab=((float)cloak)/CLKSCALE; - * c.CloakNebFX.aa=((float)cloak)/CLKSCALE; - */ - ///all else == defaults, only ambient } + + if (cloak.Cloaking()) { + c.cloaked |= MeshDrawContext::NEARINVIS; + } + //c.mat[12]=pos.i; //c.mat[13]=pos.j; //c.mat[14]=pos.k;//to translate to local_pos which is now obsolete! diff --git a/engine/src/gfx/nav/navscreen.cpp b/engine/src/gfx/nav/navscreen.cpp index 4432e329ea..5720caeb00 100644 --- a/engine/src/gfx/nav/navscreen.cpp +++ b/engine/src/gfx/nav/navscreen.cpp @@ -429,9 +429,7 @@ void NavigationSystem::Draw() { Matrix mat(p, q, r, pos); if (mesh[i]) { - mesh[i]->Draw( - FLT_MAX, // lod - mat); + mesh[i]->Draw(FLT_MAX, mat); } } Mesh::ProcessZFarMeshes(true); diff --git a/engine/src/python/python_unit_wrap.h b/engine/src/python/python_unit_wrap.h index 677b664b91..f5b60bca31 100644 --- a/engine/src/python/python_unit_wrap.h +++ b/engine/src/python/python_unit_wrap.h @@ -80,7 +80,7 @@ WRAPPED3(bool, InRange, UnitWrapper, target, bool, cone, bool, cap, false ) WRAPPED0(float, CloakVisible, false ) -voidWRAPPED1( Cloak, +voidWRAPPED1( ActivateCloak, bool, cloak ) voidWRAPPED0( RemoveFromSystem ) WRAPPED4(QVector, From e38f3fa4231444df35977db95ff5304dc8ea59ce Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Tue, 10 Oct 2023 20:30:42 +0300 Subject: [PATCH 2/8] Move cloak code from unit_csv to cloak class Add missing return. Other minor fixes. --- engine/src/cmd/cloak.cpp | 9 +++++++++ engine/src/cmd/cloak.h | 19 +++++++++++++------ engine/src/cmd/drawable.cpp | 4 ++-- engine/src/cmd/unit_csv.cpp | 7 +------ engine/src/cmd/unit_generic.cpp | 7 +++++-- engine/src/cmd/unit_generic.h | 4 ++-- engine/src/gfx/mesh_gfx.cpp | 6 +++--- engine/src/resource/resource.h | 2 +- 8 files changed, 36 insertions(+), 22 deletions(-) diff --git a/engine/src/cmd/cloak.cpp b/engine/src/cmd/cloak.cpp index 127969770f..7f20ef5c86 100644 --- a/engine/src/cmd/cloak.cpp +++ b/engine/src/cmd/cloak.cpp @@ -54,6 +54,15 @@ Cloak::Cloak(std::string unit_key) current = 0; } +void Cloak::Save(std::map& unit) +{ + unit["Cloak_Min"] = std::to_string(minimum); + unit["Can_Cloak"] = std::to_string(Capable()); + unit["Cloak_Rate"] = std::to_string(rate); + unit["Cloak_Energy"] = std::to_string(energy); + unit["Cloak_Glass"] = std::to_string(glass); +} + void Cloak::Update(Energetic *energetic) { // Unit is not capable of cloaking or damaged or just not cloaking diff --git a/engine/src/cmd/cloak.h b/engine/src/cmd/cloak.h index 7a708a40f5..967145d279 100644 --- a/engine/src/cmd/cloak.h +++ b/engine/src/cmd/cloak.h @@ -26,6 +26,7 @@ #define CLOAK_H #include +#include #include "energetic.h" #include "damageable_layer.h" @@ -64,6 +65,7 @@ class Cloak public: Cloak(); Cloak(std::string unit_key); + void Save(std::map& unit); void Update(Energetic *energetic); void Toggle(); // Toggle cloak on/off @@ -76,7 +78,7 @@ class Cloak return (status == CloakingStatus::cloaking); } - bool Cloaked() { + bool Cloaked() const { return (status == CloakingStatus::cloaked); } @@ -99,16 +101,21 @@ class Cloak return glass; } - double Current() { - return current; - } - double Energy() { return energy; } + // Is the ship visible + bool Visible() { + return !Cloaked(); + } + + double Current() const { + return current; + } + //how visible the ship is from 0 to 1 - double Visible() const { + double Visibility() const { return 1-current; } diff --git a/engine/src/cmd/drawable.cpp b/engine/src/cmd/drawable.cpp index 0c357a37ea..04e20c2678 100644 --- a/engine/src/cmd/drawable.cpp +++ b/engine/src/cmd/drawable.cpp @@ -486,7 +486,7 @@ void Drawable::DrawNow(const Matrix &mato, float lod) { if (!(unit->docked & (unit->DOCKED | unit->DOCKED_INSIDE))) { halos->Draw(mat, Scale, - unit->cloak.Visible(), + unit->cloak.Visibility(), 0, unit->GetHullPercent(), velocity, @@ -735,7 +735,7 @@ void Drawable::DrawHalo(bool on_screen, float apparent_size, Matrix wmat, Cloak //nor is maxaccel. Instead, each halo should have its own limits specified in units.csv float nebd = (_Universe->AccessCamera()->GetNebula() == unit->nebula && unit->nebula != nullptr) ? -1 : 0; float hulld = unit->GetHull() > 0 ? damage_level : 1.0; - halos->Draw(wmat, Scale, unit->cloak.Visible(), nebd, hulld, velocity, + halos->Draw(wmat, Scale, unit->cloak.Visibility(), nebd, hulld, velocity, linaccel, angaccel, maxaccel, cmas, unit->faction); } diff --git a/engine/src/cmd/unit_csv.cpp b/engine/src/cmd/unit_csv.cpp index 7c1d8bd806..77c69eeb90 100644 --- a/engine/src/cmd/unit_csv.cpp +++ b/engine/src/cmd/unit_csv.cpp @@ -1365,12 +1365,7 @@ string Unit::WriteUnitString() { unit["Max_Cone"] = tos(acos(computer.radar.maxcone) * 180. / VS_PI); unit["Lock_Cone"] = tos(acos(computer.radar.lockcone) * 180. / VS_PI); - // TODO: move to Cloak - unit["Cloak_Min"] = tos(cloak.minimum); - unit["Can_Cloak"] = tos(cloak.Capable()); - unit["Cloak_Rate"] = tos(cloak.rate); - unit["Cloak_Energy"] = tos(cloak.energy); - unit["Cloak_Glass"] = tos(cloak.glass); + cloak.Save(unit); unit["Repair_Droid"] = tos(repair_droid); unit["ECM_Rating"] = tos(ecm > 0 ? ecm : -ecm); unit["Hud_Functionality"] = WriteHudDamage(this); diff --git a/engine/src/cmd/unit_generic.cpp b/engine/src/cmd/unit_generic.cpp index 4a236c2f53..b0e6691335 100644 --- a/engine/src/cmd/unit_generic.cpp +++ b/engine/src/cmd/unit_generic.cpp @@ -133,7 +133,7 @@ void Unit::SetNebula(Nebula *neb) { bool Unit::InRange(const Unit *target, double &mm, bool cone, bool cap, bool lock) const { const float capship_size = configuration()->physics_config.capship_size; - if (this == target || !target->cloak.Visible()) { + if (this == target || target->cloak.Cloaked()) { return false; } if (cone && computer.radar.maxcone > -.98) { @@ -3335,7 +3335,10 @@ bool Unit::UpAndDownGrade(const Unit *up, ++numave; ++percentage; if (gen_downgrade_list) { - AddToDowngradeMap(up->name, up->cloak.current, ((char *) &this->cloak.current) - ((char *) this), tempdownmap); + AddToDowngradeMap(up->name, + up->cloak.current, + ((char *) &this->cloak.current) - ((char *) this), + tempdownmap); } } //NOTE: Afterburner type 2 (jmp) diff --git a/engine/src/cmd/unit_generic.h b/engine/src/cmd/unit_generic.h index 4031de1f71..5f5288a8ca 100644 --- a/engine/src/cmd/unit_generic.h +++ b/engine/src/cmd/unit_generic.h @@ -605,8 +605,8 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p // how visible the ship is from 0 to 1 // Need this function to expose it to python - float CloakVisible() const { - cloak.Visible(); + float CloakVisible() { + cloak.Visibility(); } //cloaks or decloaks the starship depending on the bool diff --git a/engine/src/gfx/mesh_gfx.cpp b/engine/src/gfx/mesh_gfx.cpp index 1ebc3d8aee..c5a8d7e633 100644 --- a/engine/src/gfx/mesh_gfx.cpp +++ b/engine/src/gfx/mesh_gfx.cpp @@ -508,9 +508,9 @@ void Mesh::Draw(float lod, c.mesh_seq = 2; //MESH_SPECIAL_FX_ONLY; } else { c.mesh_seq = 2; - c.CloakFX.r = (1-cloak.Current()); - c.CloakFX.g = (1-cloak.Current()); - c.CloakFX.b = (1-cloak.Current()); + c.CloakFX.r = cloak.Visibility(); + c.CloakFX.g = cloak.Visibility(); + c.CloakFX.b = cloak.Visibility(); c.CloakFX.a = cloak.Current(); } } diff --git a/engine/src/resource/resource.h b/engine/src/resource/resource.h index 4ef41759d1..a43c4e75e3 100644 --- a/engine/src/resource/resource.h +++ b/engine/src/resource/resource.h @@ -37,7 +37,7 @@ class Resource { T adjusted_max_value_; bool no_max_; public: - Resource(const T &value, const T &min_value = 0, const T &max_value = -1); + Resource(const T &value = 0, const T &min_value = 0, const T &max_value = -1); Resource operator+=(const T &value); Resource operator-=(const T &value); From 0dd2465309cd276a5545ab47224962f05e5af173 Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Wed, 11 Oct 2023 21:23:40 +0300 Subject: [PATCH 3/8] Add missing return statement --- engine/src/cmd/unit_generic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/src/cmd/unit_generic.h b/engine/src/cmd/unit_generic.h index 5f5288a8ca..6cf18bda56 100644 --- a/engine/src/cmd/unit_generic.h +++ b/engine/src/cmd/unit_generic.h @@ -606,7 +606,7 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p // how visible the ship is from 0 to 1 // Need this function to expose it to python float CloakVisible() { - cloak.Visibility(); + return cloak.Visibility(); } //cloaks or decloaks the starship depending on the bool From c6633246db21030517067ce2fee1bec22b0988dc Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Tue, 17 Oct 2023 18:12:02 +0300 Subject: [PATCH 4/8] Implement radar code as a separate component Introduce the concept of components. --- engine/CMakeLists.txt | 8 ++ engine/src/cmd/ai/aggressive.cpp | 2 +- engine/src/cmd/ai/comm_ai.cpp | 4 +- engine/src/cmd/ai/fire.cpp | 6 +- engine/src/cmd/ai/firekeyboard.cpp | 10 +- engine/src/cmd/armed.cpp | 21 ++- engine/src/cmd/armed.h | 2 - engine/src/cmd/basecomputer.cpp | 83 +++++------ engine/src/cmd/computer.cpp | 54 -------- engine/src/cmd/computer.h | 51 ------- engine/src/cmd/drawable.cpp | 2 +- engine/src/cmd/unit_csv.cpp | 54 +------- engine/src/cmd/unit_generic.cpp | 122 +++++++--------- engine/src/cmd/unit_generic.h | 2 + engine/src/components/component.cpp | 45 ++++++ engine/src/components/component.h | 48 +++++++ engine/src/components/radar.cpp | 207 ++++++++++++++++++++++++++++ engine/src/components/radar.h | 117 ++++++++++++++++ engine/src/gfx/cockpit.cpp | 35 ++--- engine/src/gfx/nav/drawsystem.cpp | 2 +- engine/src/gfx/radar/sensor.cpp | 14 +- engine/src/gfx/radar/sensor.h | 2 + 22 files changed, 571 insertions(+), 320 deletions(-) create mode 100644 engine/src/components/component.cpp create mode 100644 engine/src/components/component.h create mode 100644 engine/src/components/radar.cpp create mode 100644 engine/src/components/radar.h diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 5e1040760e..7d35cb6145 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -126,6 +126,7 @@ INCLUDE_DIRECTORIES( ${Vega_Strike_SOURCE_DIR}/src/cmd ${Vega_Strike_SOURCE_DIR}/src/damage ${Vega_Strike_SOURCE_DIR}/src/resource + ${Vega_Strike_SOURCE_DIR}/src/components ${Vega_Strike_BINARY_DIR} ) ELSE (MSVC) @@ -134,6 +135,7 @@ INCLUDE_DIRECTORIES( ${Vega_Strike_SOURCE_DIR}/src/cmd ${Vega_Strike_SOURCE_DIR}/src/damage ${Vega_Strike_SOURCE_DIR}/src/resource + ${Vega_Strike_SOURCE_DIR}/src/components ${Vega_Strike_BINARY_DIR} /usr/include/harfbuzz/ ) @@ -657,6 +659,11 @@ SET(LIBRESOURCE src/resource/product.cpp ) +SET(LIBCOMPONENT + src/components/component.cpp + src/components/radar.cpp + ) + SET(LIBGUI_SOURCES src/gui/button.cpp src/gui/control.cpp @@ -1059,6 +1066,7 @@ ADD_LIBRARY(vegastrike-engine_com ${LIBCONFIG} ${LIBDAMAGE} ${LIBRESOURCE} + ${LIBCOMPONENT} ${LIBAI_SOURCES} ${LIBCMD_SOURCES} ${LIBNET_SOURCES} diff --git a/engine/src/cmd/ai/aggressive.cpp b/engine/src/cmd/ai/aggressive.cpp index 964d9a7b5e..67d66d1765 100644 --- a/engine/src/cmd/ai/aggressive.cpp +++ b/engine/src/cmd/ai/aggressive.cpp @@ -1325,7 +1325,7 @@ static Unit *ChooseNavPoint(Unit *parent, Unit **otherdest, float *lurk_on_arriv if (a != b) { int retrycount = maxrand; while (--retrycount > 0 - && (UnitUtil::getDistance(a, b) < parent->GetComputerData().radar.maxrange * 4 || a == b)) { + && (UnitUtil::getDistance(a, b) < parent->radar.GetMaxRange() * 4 || a == b)) { b = GetRandomNav(stats->navs, additionalrand[retrycount]); } if (retrycount != 0) { diff --git a/engine/src/cmd/ai/comm_ai.cpp b/engine/src/cmd/ai/comm_ai.cpp index 90aab335df..4b7a95bf11 100644 --- a/engine/src/cmd/ai/comm_ai.cpp +++ b/engine/src/cmd/ai/comm_ai.cpp @@ -364,7 +364,7 @@ Unit *CommunicatingAI::GetRandomUnit(float playaprob, float targprob) { } //FIXME FOR TESTING ONLY //return parent->Target(); - QVector where = parent->Position() + parent->GetComputerData().radar.maxrange * QVector(vsrandom.uniformInc(-1, 1), + QVector where = parent->Position() + parent->radar.GetMaxRange() * QVector(vsrandom.uniformInc(-1, 1), vsrandom.uniformInc(-1, 1), vsrandom.uniformInc(-1, 1)); Collidable wherewrapper(0, 0, where); @@ -393,7 +393,7 @@ void CommunicatingAI::RandomInitiateCommunication(float playaprob, float targpro if (target != NULL) { if (UnitUtil::getUnitSystemFile(target) == UnitUtil::getUnitSystemFile(parent) && UnitUtil::getFlightgroupName(parent) != "Base" && !isDockedAtAll(target) - && UnitUtil::getDistance(parent, target) <= target->GetComputerData().radar.maxrange) { + && UnitUtil::getDistance(parent, target) <= target->radar.GetMaxRange()) { //warning--odd hack they can talk to you if you can sense them--it's like SETI@home for (std::list::iterator i = messagequeue.begin(); i != messagequeue.end(); i++) { Unit *un = (*i)->sender.GetUnit(); diff --git a/engine/src/cmd/ai/fire.cpp b/engine/src/cmd/ai/fire.cpp index 3c6d1b8769..deaf06e95c 100644 --- a/engine/src/cmd/ai/fire.cpp +++ b/engine/src/cmd/ai/fire.cpp @@ -577,7 +577,7 @@ void FireAt::ChooseTargets(int numtargs, bool force) { "Targetting", "search_max_candidates", "64")); //Cutoff candidate count (if that many hostiles found, stop search - performance/quality tradeoff, 0=no cutoff) - UnitWithinRangeLocator > unitLocator(parent->GetComputerData().radar.maxrange, unitRad); + UnitWithinRangeLocator > unitLocator(parent->radar.GetMaxRange(), unitRad); StaticTuple maxranges{}; maxranges[0] = gunrange; @@ -629,7 +629,7 @@ void FireAt::ChooseTargets(int numtargs, bool force) { for (vector::iterator k = tbin.begin(); k != tbin.end(); ++k) { k->AssignTargets(my_target, parent->cumulative_transformation_matrix); } - parent->LockTarget(false); + parent->radar.Unlock(); if (wasnull) { if (mytarg) { nextframenumpollers[hastarg] += 2; @@ -657,7 +657,7 @@ void FireAt::ChooseTargets(int numtargs, bool force) { } } parent->Target(mytarg); - parent->LockTarget(true); + parent->radar.Lock(); SignalChosenTarget(); } diff --git a/engine/src/cmd/ai/firekeyboard.cpp b/engine/src/cmd/ai/firekeyboard.cpp index 3f03e307d3..62ecc84122 100644 --- a/engine/src/cmd/ai/firekeyboard.cpp +++ b/engine/src/cmd/ai/firekeyboard.cpp @@ -1782,7 +1782,7 @@ void FireKeyboard::Execute() { } if (f().lockkey == PRESS) { f().lockkey = DOWN; - parent->LockTarget(!parent->TargetLocked()); + parent->radar.ToggleLock(); } if (f().ECMkey == PRESS) { f().ECMkey = DOWN; @@ -1813,7 +1813,7 @@ void FireKeyboard::Execute() { f().targetskey = DOWN; ChooseTargets(parent, TargSig, false); refresh_target = true; - parent->LockTarget(true); + parent->radar.Lock(); } if (f().targetukey == PRESS) { f().targetukey = DOWN; @@ -1894,7 +1894,7 @@ void FireKeyboard::Execute() { f().rtargetskey = DOWN; ChooseTargets(parent, TargSig, true); refresh_target = true; - parent->LockTarget(true); + parent->radar.Lock(); } if (f().rtargetukey == PRESS) { f().rtargetukey = DOWN; @@ -2032,7 +2032,7 @@ void FireKeyboard::Execute() { } if (f().toggleautotracking == PRESS) { f().toggleautotracking = DOWN; - parent->GetComputerData().radar.trackingactive = !parent->GetComputerData().radar.trackingactive; + parent->radar.ToggleTracking(); } if (f().misk == PRESS || f().rmisk == PRESS) { bool forward; @@ -2058,7 +2058,7 @@ void FireKeyboard::Execute() { f().saveTargetKeys[i] = RELEASE; savedTargets[i] = parent->Target(); } - if (f().restoreTargetKeys[i] == PRESS && parent->GetComputerData().radar.canlock) { + if (f().restoreTargetKeys[i] == PRESS && parent->radar.CanLock()) { f().restoreTargetKeys[i] = RELEASE; Unit *un; for (un_iter u = _Universe->activeStarSystem()->getUnitList().createIterator(); diff --git a/engine/src/cmd/armed.cpp b/engine/src/cmd/armed.cpp index 40f99bb2b6..83826132c7 100644 --- a/engine/src/cmd/armed.cpp +++ b/engine/src/cmd/armed.cpp @@ -324,13 +324,7 @@ int Armed::LockMissile() const { return missilelock ? 1 : (dumblock ? -1 : 0); } -void Armed::LockTarget(bool myboo) { - Unit *unit = static_cast(this); - unit->computer.radar.locked = myboo; - if (myboo && unit->computer.radar.canlock == false && false == UnitUtil::isSignificant(unit->Target())) { - unit->computer.radar.locked = false; - } -} + QVector Armed::PositionITTS(const QVector &absposit, Vector velocity, float speed, bool steady_itts) const { const Unit *unit = static_cast(this); @@ -413,7 +407,7 @@ void Armed::setAverageGunSpeed() { bool Armed::TargetLocked(const Unit *checktarget) const { const Unit *unit = static_cast(this); - if (!unit->computer.radar.locked) { + if (!unit->radar.locked) { return false; } return (checktarget == NULL) || (unit->computer.target == checktarget); @@ -423,19 +417,24 @@ bool Armed::TargetTracked(const Unit *checktarget) { Unit *unit = static_cast(this); static bool must_lock_to_autotrack = XMLSupport::parse_bool( vs_config->getVariable("physics", "must_lock_to_autotrack", "true")); - bool we_do_track = unit->computer.radar.trackingactive + + bool we_do_track = unit->radar.tracking_active && (!_Universe->isPlayerStarship(unit) || TargetLocked() || !must_lock_to_autotrack); if (!we_do_track) { return false; } + if (checktarget == NULL) { return true; } + if (unit->computer.target != checktarget) { return false; } - float mycone = unit->computer.radar.trackingcone; + + float mycone = unit->radar.tracking_cone; we_do_track = CloseEnoughToAutotrack(unit, unit->computer.target.GetUnit(), mycone); + return we_do_track; } @@ -454,7 +453,7 @@ float Armed::TrackingGuns(bool &missilelock) { missilelock = false; for (int i = 0; i < getNumMounts(); ++i) { if (mounts[i].status == Mount::ACTIVE && isAutoTrackingMount(mounts[i].size)) { - trackingcone = unit->computer.radar.trackingcone; + trackingcone = unit->radar.tracking_cone; } if (mounts[i].status == Mount::ACTIVE && mounts[i].type->lock_time > 0 && mounts[i].time_to_lock <= 0) { missilelock = true; diff --git a/engine/src/cmd/armed.h b/engine/src/cmd/armed.h index 56f57af709..91534b1e13 100644 --- a/engine/src/cmd/armed.h +++ b/engine/src/cmd/armed.h @@ -61,8 +61,6 @@ class Armed { //-1 is no lock necessary 1 is locked int LockMissile() const; - void LockTarget(bool myboo); - //Finds the position from the local position if guns are aimed at it with speed QVector PositionITTS(const QVector &firingposit, Vector firingvelocity, float gunspeed, bool smooth_itts) const; diff --git a/engine/src/cmd/basecomputer.cpp b/engine/src/cmd/basecomputer.cpp index 63f243cf58..ea05716e0f 100644 --- a/engine/src/cmd/basecomputer.cpp +++ b/engine/src/cmd/basecomputer.cpp @@ -5236,15 +5236,15 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C } } if (!mode) { - PRETTY_ADDU(statcolor + "Tracking range: #-c", uc.radar.maxrange / 1000, 0, "km"); - if ((acos(uc.radar.maxcone) * 360 / PI) < 359) { - PRETTY_ADDU(statcolor + "Tracking cone: #-c", acos(uc.radar.maxcone) * 2, 2, "radians"); + PRETTY_ADDU(statcolor + "Tracking range: #-c", playerUnit->radar.GetMaxRange() / 1000, 0, "km"); + if ((acos(playerUnit->radar.GetMaxCone()) * 360 / PI) < 359) { + PRETTY_ADDU(statcolor + "Tracking cone: #-c", acos(playerUnit->radar.GetMaxCone()) * 2, 2, "radians"); text += expstatcolor + "#n# (planar angle: 2 pi means full space)#-c"; } else { text += "#n#" + prefix + statcolor + "Tracking cone: #-cOMNIDIRECTIONAL"; } - PRETTY_ADDU(statcolor + "Assisted targeting cone: #-c", acos(uc.radar.trackingcone) * 2, 2, "radians"); - PRETTY_ADDU(statcolor + "Missile locking cone: #-c", acos(uc.radar.lockcone) * 2, 2, "radians"); + PRETTY_ADDU(statcolor + "Assisted targeting cone: #-c", acos(playerUnit->radar.GetTrackingCone()) * 2, 2, "radians"); + PRETTY_ADDU(statcolor + "Missile locking cone: #-c", acos(playerUnit->radar.GetLockCone()) * 2, 2, "radians"); if (!subunitlevel) { //Always zero PRETTY_ADDU("Minimum target size: ",uc.radar.mintargetsize,2,"m"); text += "#n#" + prefix + statcolor + "ITTS (Intelligent Target Tracking System) support: #-c"; @@ -5255,10 +5255,10 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C } text += "#n#" + prefix + statcolor + "AFHH (Advanced Flag & Hostility Heuristics) support: #-c"; std::string afhh; - if (uc.radar.UseFriendFoe()) { + if (playerUnit->radar.UseFriendFoe()) { afhh += "friendly/hostile "; } - if (uc.radar.UseThreatAssessment()) { + if (playerUnit->radar.UseThreatAssessment()) { afhh += "threat "; } if (afhh.empty()) { @@ -5268,42 +5268,43 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C } text.append("#n##n##c0:1:.5#" + prefix + "[ENERGY SUBSYSTEM]#n##-c"); } else { + CRadar *radar = &playerUnit->radar; + std::string afhh; switch (replacement_mode) { case 0: //Replacement or new Module - if (MODIFIES_ALTEMPTY(replacement_mode, &uc, &buc, radar.maxrange, FLT_MAX) - || MODIFIES_ALTEMPTY(replacement_mode, &uc, &buc, radar.maxcone, VS_PI)) { - PRETTY_ADDU(statcolor + "Tracking range: #-c", uc.radar.maxrange / 1000, 0, "km"); - if ((acos(uc.radar.maxcone) * 360 / PI) < 359) { - PRETTY_ADDU(statcolor + "Tracking cone: #-c", acos(uc.radar.maxcone) * 2, 2, "radians"); - text += statcolor + " (planar angle: 2 pi means full space)#-c"; - } else { - text += "#n#" + prefix + statcolor + "Tracking cone: #-cOMNIDIRECTIONAL"; - } - PRETTY_ADDU(statcolor + "Assisted targeting cone: #-c", - acos(uc.radar.trackingcone) * 2, - 2, - "radians"); - PRETTY_ADDU(statcolor + "Missile locking cone: #-c", acos(uc.radar.lockcone) * 2, 2, "radians"); - text += "#n#" + prefix + statcolor + "ITTS (Intelligent Target Tracking System) support: #-c"; - if (uc.itts) { - text += "yes"; - } else { - text += "no"; - } - text += "#n#" + prefix + statcolor + "AFHH (Advanced Flag & Hostility Heuristics) support: #-c"; - std::string afhh; - if (uc.radar.UseFriendFoe()) { - afhh += "friendly/hostile "; - } - if (uc.radar.UseThreatAssessment()) { - afhh += "threat "; - } - if (afhh.empty()) { - afhh = "no"; - } - text += afhh; - } - break; + + PRETTY_ADDU(statcolor + "Tracking range: #-c", radar->GetMaxRange() / 1000, 0, "km"); + if ((acos(radar->GetMaxCone()) * 360 / PI) < 359) { + PRETTY_ADDU(statcolor + "Tracking cone: #-c", acos(playerUnit->radar.GetMaxCone()) * 2, 2, "radians"); + text += statcolor + " (planar angle: 2 pi means full space)#-c"; + } else { + text += "#n#" + prefix + statcolor + "Tracking cone: #-cOMNIDIRECTIONAL"; + } + PRETTY_ADDU(statcolor + "Assisted targeting cone: #-c", + acos(radar->GetTrackingCone()) * 2, + 2, + "radians"); + PRETTY_ADDU(statcolor + "Missile locking cone: #-c", acos(radar->GetLockCone()) * 2, 2, "radians"); + text += "#n#" + prefix + statcolor + "ITTS (Intelligent Target Tracking System) support: #-c"; + if (uc.itts) { + text += "yes"; + } else { + text += "no"; + } + text += "#n#" + prefix + statcolor + "AFHH (Advanced Flag & Hostility Heuristics) support: #-c"; + + if (radar->UseFriendFoe()) { + afhh += "friendly/hostile "; + } + if (radar->UseThreatAssessment()) { + afhh += "threat "; + } + if (afhh.empty()) { + afhh = "no"; + } + text += afhh; + + break; case 1: //Additive break; case 2: //multiplicative diff --git a/engine/src/cmd/computer.cpp b/engine/src/cmd/computer.cpp index 1f6b662e72..456702b82b 100644 --- a/engine/src/cmd/computer.cpp +++ b/engine/src/cmd/computer.cpp @@ -59,58 +59,4 @@ float Computer::max_ab_speed() const { return (!combat_mode) ? combat_mode_mult * max_combat_speed : max_combat_ab_speed; } -Computer::RADARLIM::RADARLIM() : - maxrange(0), - maxcone(-1), - lockcone(0), - trackingcone(0), - mintargetsize(0), - capability(Capability::IFF_NONE), - locked(false), - canlock(false), - trackingactive(true) { - maxrange = configuration()->computer_config.default_max_range; - trackingcone = configuration()->computer_config.default_tracking_cone; - lockcone = configuration()->computer_config.default_lock_cone; -} - -Computer::RADARLIM::Brand::Value Computer::RADARLIM::GetBrand() const { - switch (capability & Capability::IFF_UPPER_MASK) { - case Capability::IFF_SPHERE: - return Brand::SPHERE; - case Capability::IFF_BUBBLE: - return Brand::BUBBLE; - case Capability::IFF_PLANE: - return Brand::PLANE; - default: - assert(false); - return Brand::SPHERE; - } -} - -bool Computer::RADARLIM::UseFriendFoe() const { - // Backwardscompatibility - if (capability == 0) { - return false; - } else if ((capability == 1) || (capability == 2)) { - return true; - } - - return (capability & Capability::IFF_FRIEND_FOE); -} - -bool Computer::RADARLIM::UseObjectRecognition() const { - // Backwardscompatibility - if ((capability == 0) || (capability == 1)) { - return false; - } else if (capability == 2) { - return true; - } - - return (capability & Capability::IFF_OBJECT_RECOGNITION); -} - -bool Computer::RADARLIM::UseThreatAssessment() const { - return (capability & Capability::IFF_THREAT_ASSESSMENT); -} diff --git a/engine/src/cmd/computer.h b/engine/src/cmd/computer.h index 3ad4156c02..da2179f662 100644 --- a/engine/src/cmd/computer.h +++ b/engine/src/cmd/computer.h @@ -42,57 +42,6 @@ */ class Computer { public: - class RADARLIM { - public: - struct Brand { - enum Value { - SPHERE = 0, - BUBBLE = 1, - PLANE = 2 - }; - }; - struct Capability { - enum Value { - // For internal use - IFF_UPPER_SHIFT = 16, - IFF_LOWER_MASK = (1 << IFF_UPPER_SHIFT) - 1, - IFF_UPPER_MASK = ~IFF_LOWER_MASK, - - // The lower 16 bits - IFF_NONE = 0, - IFF_FRIEND_FOE = 1 << 0, - IFF_OBJECT_RECOGNITION = 1 << 1, - IFF_THREAT_ASSESSMENT = 1 << 2, - - // The upper 16 bits - IFF_SPHERE = Brand::SPHERE << IFF_UPPER_SHIFT, - IFF_BUBBLE = Brand::BUBBLE << IFF_UPPER_SHIFT, - IFF_PLANE = Brand::PLANE << IFF_UPPER_SHIFT - }; - }; - //the max range the radar can handle - float maxrange; - //the dot with (0,0,1) indicating the farthest to the side the radar can handle. - float maxcone; - float lockcone; - float trackingcone; - //The minimum radius of the target - float mintargetsize; - // What kind of type and capability the radar supports - int capability; - bool locked; - bool canlock; - bool trackingactive; - - Brand::Value GetBrand() const; - bool UseFriendFoe() const; - bool UseObjectRecognition() const; - bool UseThreatAssessment() const; - - RADARLIM(); - }; - - RADARLIM radar; bool ecmactive; //The nav point the unit may be heading for Vector NavPoint; diff --git a/engine/src/cmd/drawable.cpp b/engine/src/cmd/drawable.cpp index 04e20c2678..e18c0eaf0a 100644 --- a/engine/src/cmd/drawable.cpp +++ b/engine/src/cmd/drawable.cpp @@ -757,7 +757,7 @@ void Drawable::DrawSubunits(bool on_screen, Matrix wmat, Cloak cloak, float aver (isAutoTrackingMount(unit->mounts[i].size) && (unit->mounts[i].time_to_lock <= 0) && unit->TargetTracked()) ? unit->Target() : NULL, - unit->computer.radar.trackingcone); + unit->radar.GetTrackingCone()); } } diff --git a/engine/src/cmd/unit_csv.cpp b/engine/src/cmd/unit_csv.cpp index 77c69eeb90..5fcf330568 100644 --- a/engine/src/cmd/unit_csv.cpp +++ b/engine/src/cmd/unit_csv.cpp @@ -874,53 +874,8 @@ void Unit::LoadRow(std::string unit_identifier, string modification, bool saved_ computer.max_combat_ab_speed = UnitCSVFactory::GetVariable(unit_key, "Afterburner_Speed_Governor", 0.0f) * game_speed; computer.itts = UnitCSVFactory::GetVariable(unit_key, "ITTS", true); - computer.radar.canlock = UnitCSVFactory::GetVariable(unit_key, "Can_Lock", true); - - - // The Radar_Color column in the units.csv has been changed from a - // boolean value to a string. The boolean values are supported for - // backwardscompatibility. - // When we save this setting, it is simply converted from an integer - // number to a string, and we need to support this as well. - std::string iffval = UnitCSVFactory::GetVariable(unit_key, "Radar_Color", std::string()); - - if ((iffval.empty()) || (iffval == "FALSE") || (iffval == "0")) { - computer.radar.capability = Computer::RADARLIM::Capability::IFF_NONE; - } else if ((iffval == "TRUE") || (iffval == "1")) { - computer.radar.capability = Computer::RADARLIM::Capability::IFF_SPHERE - | Computer::RADARLIM::Capability::IFF_FRIEND_FOE; - } else if (iffval == "THREAT") { - computer.radar.capability = Computer::RADARLIM::Capability::IFF_SPHERE - | Computer::RADARLIM::Capability::IFF_FRIEND_FOE - | Computer::RADARLIM::Capability::IFF_THREAT_ASSESSMENT; - } else if (iffval == "BUBBLE_THREAT") { - computer.radar.capability = Computer::RADARLIM::Capability::IFF_BUBBLE - | Computer::RADARLIM::Capability::IFF_FRIEND_FOE - | Computer::RADARLIM::Capability::IFF_OBJECT_RECOGNITION - | Computer::RADARLIM::Capability::IFF_THREAT_ASSESSMENT; - } else if (iffval == "PLANE") { - computer.radar.capability = Computer::RADARLIM::Capability::IFF_PLANE - | Computer::RADARLIM::Capability::IFF_FRIEND_FOE; - } else if (iffval == "PLANE_THREAT") { - computer.radar.capability - = Computer::RADARLIM::Capability::IFF_PLANE - | Computer::RADARLIM::Capability::IFF_FRIEND_FOE - | Computer::RADARLIM::Capability::IFF_OBJECT_RECOGNITION - | Computer::RADARLIM::Capability::IFF_THREAT_ASSESSMENT; - } else { - unsigned int value = stoi(iffval, 0); - if (value == 0) { - // Unknown value - computer.radar.capability = Computer::RADARLIM::Capability::IFF_NONE; - } else { - computer.radar.capability = value; - } - } - computer.radar.maxrange = UnitCSVFactory::GetVariable(unit_key, "Radar_Range", FLT_MAX); - computer.radar.maxcone = cos(UnitCSVFactory::GetVariable(unit_key, "Max_Cone", 180.0f) * VS_PI / 180); - computer.radar.trackingcone = cos(UnitCSVFactory::GetVariable(unit_key, "Tracking_Cone", 180.0f) * VS_PI / 180); - computer.radar.lockcone = cos(UnitCSVFactory::GetVariable(unit_key, "Lock_Cone", 180.0f) * VS_PI / 180); + radar = CRadar(unit_key, &computer); cloak = Cloak(unit_key); @@ -1358,12 +1313,7 @@ string Unit::WriteUnitString() { unit["Default_Speed_Governor"] = tos(computer.max_combat_speed / game_speed); unit["Afterburner_Speed_Governor"] = tos(computer.max_combat_ab_speed / game_speed); unit["ITTS"] = tos(computer.itts); - unit["Can_Lock"] = tos(computer.radar.canlock); - unit["Radar_Color"] = tos(computer.radar.capability); - unit["Radar_Range"] = tos(computer.radar.maxrange); - unit["Tracking_Cone"] = tos(acos(computer.radar.trackingcone) * 180. / VS_PI); - unit["Max_Cone"] = tos(acos(computer.radar.maxcone) * 180. / VS_PI); - unit["Lock_Cone"] = tos(acos(computer.radar.lockcone) * 180. / VS_PI); + cloak.Save(unit); unit["Repair_Droid"] = tos(repair_droid); diff --git a/engine/src/cmd/unit_generic.cpp b/engine/src/cmd/unit_generic.cpp index b0e6691335..3a50e141ea 100644 --- a/engine/src/cmd/unit_generic.cpp +++ b/engine/src/cmd/unit_generic.cpp @@ -136,13 +136,13 @@ bool Unit::InRange(const Unit *target, double &mm, bool cone, bool cap, bool loc if (this == target || target->cloak.Cloaked()) { return false; } - if (cone && computer.radar.maxcone > -.98) { + if (cone && radar.max_cone > -.98) { QVector delta(target->Position() - Position()); mm = delta.Magnitude(); if ((!lock) || (!TargetLocked(target))) { double tempmm = mm - target->rSize(); if (tempmm > 0.0001) { - if ((ToLocalCoordinates(Vector(delta.i, delta.j, delta.k)).k / tempmm) < computer.radar.maxcone + if ((ToLocalCoordinates(Vector(delta.i, delta.j, delta.k)).k / tempmm) < radar.max_cone && cone) { return false; } @@ -152,8 +152,8 @@ bool Unit::InRange(const Unit *target, double &mm, bool cone, bool cap, bool loc mm = (target->Position() - Position()).Magnitude(); } //owner==target?! - if (((mm - rSize() - target->rSize()) > computer.radar.maxrange) - || target->rSize() < computer.radar.mintargetsize) { + if (((mm - rSize() - target->rSize()) > radar.max_range) + || target->rSize() < radar.GetMinTargetSize()) { Flightgroup *fg = target->getFlightgroup(); if ((target->rSize() < capship_size || (!cap)) && (fg == NULL ? true : fg->name != "Base")) { return target->isUnit() == Vega_UnitType::planet; @@ -1154,41 +1154,14 @@ void Unit::DamageRandSys(float dam, const Vector &vec, float randnum, float degr } else if (randnum >= .775) { computer.itts = false; //Set the computer to not have an itts } else if (randnum >= .7) { - // Gradually degrade radar capabilities - typedef Computer::RADARLIM::Capability Capability; - int &capability = computer.radar.capability; - if (capability & Capability::IFF_THREAT_ASSESSMENT) { - capability &= ~Capability::IFF_THREAT_ASSESSMENT; - } else if (capability & Capability::IFF_OBJECT_RECOGNITION) { - capability &= ~Capability::IFF_OBJECT_RECOGNITION; - } else if (capability & Capability::IFF_FRIEND_FOE) { - capability &= ~Capability::IFF_FRIEND_FOE; - } + radar.Damage(); } else if (randnum >= .5) { //THIS IS NOT YET SUPPORTED IN NETWORKING computer.target = nullptr; //set the target to NULL } else if (randnum >= .4) { limits.retro *= dam; - } else if (randnum >= .3275) { - const float maxdam = configuration()->physics_config.max_radar_cone_damage; - computer.radar.maxcone += (1 - dam); - if (computer.radar.maxcone > maxdam) { - computer.radar.maxcone = maxdam; - } - } else if (randnum >= .325) { - const float maxdam = configuration()->physics_config.max_radar_lock_cone_damage; - computer.radar.lockcone += (1 - dam); - if (computer.radar.lockcone > maxdam) { - computer.radar.lockcone = maxdam; - } - } else if (randnum >= .25) { - const float maxdam = configuration()->physics_config.max_radar_track_cone_damage; - computer.radar.trackingcone += (1 - dam); - if (computer.radar.trackingcone > maxdam) { - computer.radar.trackingcone = maxdam; - } } else if (randnum >= .175) { - computer.radar.maxrange *= dam; + radar.Damage(); } else { int which = rand() % (1 + UnitImages::NUMGAUGES + MAXVDUS); pImage->cockpit_damage[which] *= dam; @@ -1621,7 +1594,7 @@ void Unit::Target(Unit *targ) { } computer.target.SetUnit(targ); - LockTarget(false); + radar.Unlock(); } } else { if (jump.drive != -1) { @@ -3241,14 +3214,14 @@ bool Unit::UpAndDownGrade(const Unit *up, "Radar_Range|Radar_Color|ITTS|Can_Lock|Max_Cone|Lock_Cone|Tracking_Cone")) { if (!csv_cell_null_check || force_change_on_nothing || cell_has_recursive_data(upgrade_name, up->faction, "Radar_Range")) { - STDUPGRADECLAMP(computer.radar.maxrange, - up->computer.radar.maxrange, - use_template_maxrange ? templ->computer.radar.maxrange : FLT_MAX, + STDUPGRADECLAMP(radar.max_range, + up->radar.max_range, + use_template_maxrange ? templ->radar.max_range : FLT_MAX, 0); } if (!csv_cell_null_check || force_change_on_nothing || cell_has_recursive_data(upgrade_name, up->faction, "Radar_Color")) - STDUPGRADE(computer.radar.capability, up->computer.radar.capability, templ->computer.radar.capability, 0); + STDUPGRADE(radar.capabilities, up->radar.capabilities, templ->radar.capabilities, 0); if (!csv_cell_null_check || force_change_on_nothing || cell_has_recursive_data(upgrade_name, up->faction, "ITTS")) { computer.itts = UpgradeBoolval(computer.itts, @@ -3261,8 +3234,8 @@ bool Unit::UpAndDownGrade(const Unit *up, } if (!csv_cell_null_check || force_change_on_nothing || cell_has_recursive_data(upgrade_name, up->faction, "Can_Lock")) { - computer.radar.canlock = UpgradeBoolval(computer.radar.canlock, - up->computer.radar.canlock, + radar.can_lock = UpgradeBoolval(radar.can_lock, + up->radar.can_lock, touchme, downgrade, numave, @@ -3273,41 +3246,41 @@ bool Unit::UpAndDownGrade(const Unit *up, bool ccf = cancompletefully; if (!csv_cell_null_check || force_change_on_nothing || cell_has_recursive_data(upgrade_name, up->faction, "Max_Cone")) { - double myleak = 1 - computer.radar.maxcone; - double upleak = 1 - up->computer.radar.maxcone; - double templeak = 1 - (templ != NULL ? templ->computer.radar.maxcone : -1); - STDUPGRADE_SPECIFY_DEFAULTS(myleak, upleak, templeak, 0, 0, 0, false, computer.radar.maxcone); + double myleak = 1 - radar.max_cone; + double upleak = 1 - up->radar.max_cone; + double templeak = 1 - (templ != NULL ? templ->radar.max_cone : -1); + STDUPGRADE_SPECIFY_DEFAULTS(myleak, upleak, templeak, 0, 0, 0, false, radar.max_cone); if (touchme) { - computer.radar.maxcone = 1 - myleak; + radar.max_cone = 1 - myleak; } } - if (up->computer.radar.lockcone != lc) { - double myleak = 1 - computer.radar.lockcone; - double upleak = 1 - up->computer.radar.lockcone; - double templeak = 1 - (templ != NULL ? templ->computer.radar.lockcone : -1); + if (up->radar.lock_cone != lc) { + double myleak = 1 - radar.lock_cone; + double upleak = 1 - up->radar.lock_cone; + double templeak = 1 - (templ != NULL ? templ->radar.lock_cone : -1); if (templeak == 1 - lc) { templeak = 2; } if (!csv_cell_null_check || force_change_on_nothing || cell_has_recursive_data(upgrade_name, up->faction, "Lock_Cone")) { - STDUPGRADE_SPECIFY_DEFAULTS(myleak, upleak, templeak, 0, 0, 0, false, computer.radar.lockcone); + STDUPGRADE_SPECIFY_DEFAULTS(myleak, upleak, templeak, 0, 0, 0, false, radar.lock_cone); if (touchme) { - computer.radar.lockcone = 1 - myleak; + radar.lock_cone = 1 - myleak; } } } - if (up->computer.radar.trackingcone != tc) { - double myleak = 1 - computer.radar.trackingcone; - double upleak = 1 - up->computer.radar.trackingcone; - double templeak = 1 - (templ != NULL ? templ->computer.radar.trackingcone : -1); + if (up->radar.tracking_cone != tc) { + double myleak = 1 - radar.tracking_cone; + double upleak = 1 - up->radar.tracking_cone; + double templeak = 1 - (templ != NULL ? templ->radar.tracking_cone : -1); if (templeak == 1 - tc) { templeak = 2; } if (!csv_cell_null_check || force_change_on_nothing || cell_has_recursive_data(upgrade_name, up->faction, "Tracking_Cone")) { - STDUPGRADE_SPECIFY_DEFAULTS(myleak, upleak, templeak, 0, 0, 0, false, computer.radar.trackingcone); + STDUPGRADE_SPECIFY_DEFAULTS(myleak, upleak, templeak, 0, 0, 0, false, radar.tracking_cone); if (touchme) { - computer.radar.trackingcone = 1 - myleak; + radar.tracking_cone = 1 - myleak; } } } @@ -4403,7 +4376,7 @@ void Unit::UpdatePhysics3(const Transformation &trans, Vector TargetPos(InvTransform(cumulative_transformation_matrix, (target->Position())).Cast()); dist_sqr_to_target = TargetPos.MagnitudeSquared(); TargetPos.Normalize(); - if (TargetPos.k > computer.radar.lockcone) { + if (TargetPos.k > radar.lock_cone) { increase_locking = true; } } @@ -4505,23 +4478,26 @@ void Unit::UpdatePhysics3(const Transformation &trans, } if (mounts[i].type->type == WEAPON_TYPE::BEAM) { if (mounts[i].ref.gun) { - Unit *autotarg = - (isAutoTrackingMount(mounts[i].size) - && (mounts[i].time_to_lock <= 0) - && TargetTracked()) ? target : NULL; - float trackingcone = computer.radar.trackingcone; - if (CloseEnoughToAutotrack(this, target, trackingcone)) { + bool autoTrack = isAutoTrackingMount(mounts[i].size); + bool timeLocked = mounts[i].time_to_lock <= 0; + bool tracked = TargetTracked(); + Unit *autotarg = (autoTrack && timeLocked && tracked) ? target : nullptr; + + float tracking_cone = radar.tracking_cone; + // TODO: fix this or remove + /*if (CloseEnoughToAutotrack(this, target, tracking_cone)) { if (autotarg) { - if (computer.radar.trackingcone < trackingcone) { - trackingcone = computer.radar.trackingcone; + if (radar.tracking_cone < tracking_cone) { + tracking_cone = radar.tracking_cone; } } autotarg = target; - } + }*/ + mounts[i].ref.gun->UpdatePhysics(cumulative_transformation, cumulative_transformation_matrix, autotarg, - trackingcone, + tracking_cone, target, (HeatSink ? HeatSink : 1.0f) * mounts[i].functionality, this, @@ -4541,11 +4517,11 @@ void Unit::UpdatePhysics3(const Transformation &trans, && TargetTracked()) { autotrack = computer.itts ? 2 : 1; } - float trackingcone = computer.radar.trackingcone; - if (CloseEnoughToAutotrack(this, target, trackingcone)) { + float tracking_cone = radar.tracking_cone; + if (CloseEnoughToAutotrack(this, target, tracking_cone)) { if (autotrack) { - if (trackingcone > computer.radar.trackingcone) { - trackingcone = computer.radar.trackingcone; + if (tracking_cone > radar.tracking_cone) { + tracking_cone = radar.tracking_cone; } } autotrack = 2; @@ -4559,7 +4535,7 @@ void Unit::UpdatePhysics3(const Transformation &trans, } if (!mounts[i].PhysicsAlignedFire(this, t1, m1, cumulative_velocity, (!isSubUnit() || owner == NULL) ? this : owner, target, autotrack, - trackingcone, + tracking_cone, hint)) { const WeaponInfo *typ = mounts[i].type; energy += typ->energy_rate * (typ->type == WEAPON_TYPE::BEAM ? simulation_atom_var : 1); diff --git a/engine/src/cmd/unit_generic.h b/engine/src/cmd/unit_generic.h index 6cf18bda56..2147847efa 100644 --- a/engine/src/cmd/unit_generic.h +++ b/engine/src/cmd/unit_generic.h @@ -77,6 +77,7 @@ void UncheckUnit( class Unit*un ); #include "role_bitmask.h" #include "upgradeable_unit.h" #include "cloak.h" +#include "components/radar.h" #include "configuration/configuration.h" #include "configuration/game_config.h" @@ -480,6 +481,7 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p bool DoSightAndSound) override; Computer computer; + CRadar radar; void SwitchCombatFlightMode(); bool CombatMode(); diff --git a/engine/src/components/component.cpp b/engine/src/components/component.cpp new file mode 100644 index 0000000000..556bf81a7b --- /dev/null +++ b/engine/src/components/component.cpp @@ -0,0 +1,45 @@ +/* + * component.cpp + * + * Copyright (c) 2001-2002 Daniel Horn + * Copyright (c) 2002-2019 pyramid3d and other Vega Strike Contributors + * Copyright (c) 2019-2023 Stephen G. Tuggy, Benjamen R. Meyer, Roy Falk and other Vega Strike Contributors + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +// -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- + +#include "component.h" + +#include + +/*Component::Component() +{ + +}*/ + + +double random20() +{ + if(std::rand() < 0.2) { + return std::rand(); + } + + return 1.0; +} diff --git a/engine/src/components/component.h b/engine/src/components/component.h new file mode 100644 index 0000000000..58a0fd0c53 --- /dev/null +++ b/engine/src/components/component.h @@ -0,0 +1,48 @@ +/* + * component.h + * + * Copyright (c) 2001-2002 Daniel Horn + * Copyright (c) 2002-2019 pyramid3d and other Vega Strike Contributors + * Copyright (c) 2019-2023 Stephen G. Tuggy, Benjamen R. Meyer, Roy Falk and other Vega Strike Contributors + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +// -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- + +#ifndef COMPONENT_H +#define COMPONENT_H + + +/*class Component +{ +public: + Component(); + virtual ~Component() {} + + virtual void damage(); + virtual void fix(); + + +};*/ + +// These functions reduce functionality by a uniform distribution 0-1. +// The function name's number component is the chance of the damage occurring. +double random20(); + +#endif // COMPONENT_H diff --git a/engine/src/components/radar.cpp b/engine/src/components/radar.cpp new file mode 100644 index 0000000000..7d381c20db --- /dev/null +++ b/engine/src/components/radar.cpp @@ -0,0 +1,207 @@ +/* + * radar.cpp + * + * Copyright (c) 2001-2002 Daniel Horn + * Copyright (c) 2002-2019 pyramid3d and other Vega Strike Contributors + * Copyright (c) 2019-2023 Stephen G. Tuggy, Benjamen R. Meyer, Roy Falk and other Vega Strike Contributors + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +// -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- + +#include "radar.h" +#include "configuration/configuration.h" +#include "unit_generic.h" +#include "unit_util.h" +#include "unit_csv_factory.h" +#include "components/component.h" + +#include + +CRadar::CRadar(): + max_range(0), + max_cone(-1), + lock_cone(0), + tracking_cone(0), + min_target_size(0), + type(RadarType::SPHERE), + capabilities(RadarCapabilities::NONE), + locked(false), + can_lock(false), + tracking_active(true), + original(nullptr), + computer(nullptr) +{ + + max_range = configuration()->computer_config.default_max_range; + tracking_cone = configuration()->computer_config.default_tracking_cone; + lock_cone = configuration()->computer_config.default_lock_cone; +} + +CRadar::CRadar(std::string unit_key, Computer* computer) { + can_lock = UnitCSVFactory::GetVariable(unit_key, "Can_Lock", true); + + // TODO: fix this + // The Radar_Color column in the units.csv has been changed from a + // boolean value to a string. The boolean values are supported for + // backwardscompatibility. + // When we save this setting, it is simply converted from an integer + // number to a string, and we need to support this as well. + std::string iffval = UnitCSVFactory::GetVariable(unit_key, "Radar_Color", std::string()); + + if ((iffval.empty()) || (iffval == "FALSE") || (iffval == "0")) { + capabilities = RadarCapabilities::NONE; + } else if ((iffval == "TRUE") || (iffval == "1")) { + type = RadarType::SPHERE; + capabilities = RadarCapabilities::FRIEND_FOE; + } else if (iffval == "THREAT") { + type = RadarType::SPHERE; + capabilities = RadarCapabilities::FRIEND_FOE | + RadarCapabilities::THREAT_ASSESSMENT; + } else if (iffval == "BUBBLE_THREAT") { + type = RadarType::BUBBLE; + capabilities = RadarCapabilities::FRIEND_FOE | + RadarCapabilities::OBJECT_RECOGNITION | + RadarCapabilities::THREAT_ASSESSMENT; + } else if (iffval == "PLANE") { + type = RadarType::PLANE; + capabilities = RadarCapabilities::FRIEND_FOE; + } else if (iffval == "PLANE_THREAT") { + type = RadarType::PLANE; + capabilities = RadarCapabilities::FRIEND_FOE | + RadarCapabilities::OBJECT_RECOGNITION | + RadarCapabilities::THREAT_ASSESSMENT; + } else { + unsigned int value = stoi(iffval, 0); + if (value == 0) { + // Unknown value + capabilities = RadarCapabilities::NONE; + } else { + capabilities = value; + } + } + + tracking_active = true; + max_range = UnitCSVFactory::GetVariable(unit_key, "Radar_Range", FLT_MAX); + max_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Max_Cone", 180.0f) * VS_PI / 180); + tracking_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Tracking_Cone", 180.0f) * VS_PI / 180); + lock_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Lock_Cone", 180.0f) * VS_PI / 180); + original = nullptr; + this->computer = computer; +} + +void CRadar::WriteUnitString(std::map &unit) { + unit["Can_Lock"] = std::to_string(can_lock); + unit["Radar_Color"] = std::to_string(capabilities); + unit["Radar_Range"] = std::to_string(max_range); + unit["Tracking_Cone"] = std::to_string(acos(tracking_cone) * 180. / VS_PI); + unit["Max_Cone"] = std::to_string(acos(max_cone) * 180. / VS_PI); + unit["Lock_Cone"] = std::to_string(acos(lock_cone) * 180. / VS_PI); +} + +void CRadar::CRadar::Damage() +{ + std::random_device rd; // a seed source for the random number engine + std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd() + std::uniform_int_distribution<> damage_distribution(0, 6); + std::uniform_int_distribution<> size_distribution(0, 6); + + // Damage IFF capabilities + if(std::rand() < 0.2) { + // TODO: make this smarter and maybe degrade capabilities + capabilities = NONE; + } + + max_range = max_range * random20(); + max_cone = max_cone * random20(); + lock_cone = lock_cone * random20(); + tracking_cone = tracking_cone * random20(); + min_target_size = min_target_size * random20(); + + // Original cone damage + /*const float maxdam = configuration()->physics_config.max_radar_cone_damage; + radar.max_cone += (1 - dam); + if (radar.max_cone > maxdam) { + radar.max_cone = maxdam; + } + + const float maxdam = configuration()->physics_config.max_radar_lock_cone_damage; + radar.lock_cone += (1 - dam); + if (radar.lock_cone > maxdam) { + radar.lock_cone = maxdam; + } + + const float maxdam = configuration()->physics_config.max_radar_track_cone_damage; + radar.tracking_cone += (1 - dam); + if (radar.tracking_cone > maxdam) { + radar.tracking_cone = maxdam; + }*/ + +} + +void CRadar::CRadar::Repair() +{ + +} + +// This code replaces and fixes the old code in Armed::LockTarget(bool) +void CRadar::Lock() { + if(!computer) { + return; + } + + const Unit *target = computer->target.GetConstUnit(); + + if(!target) { + //std::cerr << "Target is null\n"; + return; + } + + if(!can_lock) { + std::cerr << "Can't lock\n"; + this->locked = false; + return; + } + + if(!UnitUtil::isSignificant(target)) { + std::cerr << "Target insignificant\n"; + this->locked = false; + return; + } + + std::cout << "Target locked\n"; + this->locked = true; + +} + +RadarType CRadar::GetType() const { + return type; +} + +bool CRadar::UseFriendFoe() const { + return (capabilities & RadarCapabilities::FRIEND_FOE); +} + +bool CRadar::UseObjectRecognition() const { + return (capabilities & RadarCapabilities::OBJECT_RECOGNITION); +} + +bool CRadar::UseThreatAssessment() const { + return (capabilities & RadarCapabilities::THREAT_ASSESSMENT); +} diff --git a/engine/src/components/radar.h b/engine/src/components/radar.h new file mode 100644 index 0000000000..d6ece020b7 --- /dev/null +++ b/engine/src/components/radar.h @@ -0,0 +1,117 @@ +/* + * radar.h + * + * Copyright (c) 2001-2002 Daniel Horn + * Copyright (c) 2002-2019 pyramid3d and other Vega Strike Contributors + * Copyright (c) 2019-2023 Stephen G. Tuggy, Benjamen R. Meyer, Roy Falk and other Vega Strike Contributors + * + * https://github.com/vegastrike/Vega-Strike-Engine-Source + * + * This file is part of Vega Strike. + * + * Vega Strike is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * Vega Strike is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Vega Strike. If not, see . + */ + +// -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- + +#ifndef RADAR_H +#define RADAR_H + +#include +#include +#include +#include + +#include "computer.h" + +class Unit; + +enum class RadarType { + SPHERE, + BUBBLE, + PLANE +}; + +enum RadarCapabilities { + NONE = 0, + FRIEND_FOE = 1, + OBJECT_RECOGNITION = 2, + THREAT_ASSESSMENT = 4 +}; + +// Can't call it radar because of namespace collision +class CRadar +{ + // TODO: move floats to doubles + //the max range the radar can handle + float max_range; + + //the dot with (0,0,1) indicating the farthest to the side the radar can handle. + float max_cone; + float lock_cone; + float tracking_cone; + + //The minimum radius of the target + float min_target_size; + + // What kind of type and capability the radar supports + RadarType type; + unsigned int capabilities; + bool locked; + bool can_lock; + bool tracking_active; + + std::unique_ptr original; + + Computer *computer; + + friend class Armed; + friend class Unit; +public: + CRadar(); + CRadar(std::string unit_key, Computer* computer); + + void WriteUnitString(std::map &unit); + + void Damage(); + void Repair(); + + void Lock(); + void Unlock() { + locked = false; + } + void ToggleLock() { + locked = !locked; + } + + void Track(const bool track) { tracking_active = track; } + void ToggleTracking() { tracking_active = !tracking_active; } + + RadarType GetType() const; // Formerly GetBrand + bool UseFriendFoe() const; + bool UseObjectRecognition() const; + bool UseThreatAssessment() const; + + float GetMaxRange() const { return max_range; } + float GetMaxCone() const { return max_cone; } + float GetLockCone() const { return lock_cone; } + float GetTrackingCone() const { return tracking_cone; } + float GetMinTargetSize() const { return min_target_size; } + + bool Locked() const { return locked; } + bool CanLock() const { return can_lock; } + bool Tracking() const { return tracking_active; } +}; + +#endif // RADAR_H diff --git a/engine/src/gfx/cockpit.cpp b/engine/src/gfx/cockpit.cpp index fc4dcb7694..d36a842792 100644 --- a/engine/src/gfx/cockpit.cpp +++ b/engine/src/gfx/cockpit.cpp @@ -2702,26 +2702,29 @@ void GameCockpit::OnPauseEnd() { } void GameCockpit::updateRadar(Unit *ship) { - if (ship) { - // We may have bought a new radar brand while docked, so the actual - // radar display is instantiated when we undock. - switch (ship->GetComputerData().radar.GetBrand()) { - case Computer::RADARLIM::Brand::BUBBLE: - radarDisplay = Radar::Factory(Radar::Type::BubbleDisplay); - break; + if (!ship) { + return; + } - case Computer::RADARLIM::Brand::PLANE: - radarDisplay = Radar::Factory(Radar::Type::PlaneDisplay); - break; + // We may have bought a new radar brand while docked, so the actual + // radar display is instantiated when we undock. + RadarType type = ship->radar.GetType(); + Radar::Type::Value displayType = Radar::Type::Value::NullDisplay; - default: - radarDisplay = Radar::Factory(Radar::Type::SphereDisplay); - break; - } - // Send notification that I have undocked - radarDisplay->OnDockEnd(); + if(type == RadarType::BUBBLE) { + displayType = Radar::Type::BubbleDisplay; + } else if(type == RadarType::PLANE) { + displayType = Radar::Type::PlaneDisplay; + } else if(type == RadarType::SPHERE) { + displayType = Radar::Type::SphereDisplay; + } + + if(displayType != Radar::Type::Value::NullDisplay) { + radarDisplay = Radar::Factory(displayType); } + // Send notification that I have undocked + radarDisplay->OnDockEnd(); } void GameCockpit::SetParent(Unit *unit, const char *filename, const char *unitmodname, const QVector &startloc) { diff --git a/engine/src/gfx/nav/drawsystem.cpp b/engine/src/gfx/nav/drawsystem.cpp index 13d04729fd..fd50b9626f 100644 --- a/engine/src/gfx/nav/drawsystem.cpp +++ b/engine/src/gfx/nav/drawsystem.cpp @@ -449,7 +449,7 @@ void NavigationSystem::DrawSystem() { //JUST FOR NOW, target == current selection. later it'll be used for other shit, that will then set target. if (currentselection.GetUnit()) { (UniverseUtil::getPlayerX(UniverseUtil::getCurrentPlayer()))->Target(currentselection.GetUnit()); - (UniverseUtil::getPlayerX(UniverseUtil::getCurrentPlayer()))->LockTarget(currentselection.GetUnit()); + (UniverseUtil::getPlayerX(UniverseUtil::getCurrentPlayer()))->radar.Lock(); } } } diff --git a/engine/src/gfx/radar/sensor.cpp b/engine/src/gfx/radar/sensor.cpp index dd9c874fe1..f6eb812c1a 100644 --- a/engine/src/gfx/radar/sensor.cpp +++ b/engine/src/gfx/radar/sensor.cpp @@ -51,19 +51,19 @@ Unit *Sensor::GetPlayer() const { bool Sensor::UseFriendFoe() const { assert(player); - return player->GetComputerData().radar.UseFriendFoe(); + return player->radar.UseFriendFoe(); } bool Sensor::UseObjectRecognition() const { assert(player); - return player->GetComputerData().radar.UseObjectRecognition(); + return player->radar.UseObjectRecognition(); } bool Sensor::UseThreatAssessment() const { assert(player); - return player->GetComputerData().radar.UseThreatAssessment(); + return player->radar.UseThreatAssessment(); } float Sensor::GetCloseRange() const { @@ -73,19 +73,19 @@ float Sensor::GetCloseRange() const { float Sensor::GetMaxRange() const { assert(player); - return player->GetComputerData().radar.maxrange; + return player->radar.GetMaxRange(); } float Sensor::GetMaxCone() const { assert(player); - return player->GetComputerData().radar.maxcone; + return player->radar.GetMaxCone(); } float Sensor::GetLockCone() const { assert(player); - return player->GetComputerData().radar.lockcone; + return player->radar.GetLockCone(); } Track Sensor::CreateTrack(const Unit *target) const { @@ -154,7 +154,7 @@ class CollectRadarTracks { if (!isCurrentTarget && !draw_significant_blips && (getTopLevelOwner() == target->owner) && - (distance > player->GetComputerData().radar.maxrange)) { + (distance > player->radar.GetMaxRange())) { return true; } diff --git a/engine/src/gfx/radar/sensor.h b/engine/src/gfx/radar/sensor.h index 42b7cc6641..d6c17de359 100644 --- a/engine/src/gfx/radar/sensor.h +++ b/engine/src/gfx/radar/sensor.h @@ -36,6 +36,8 @@ class Unit; struct GFXColor; // Edit from class to struct as defined in gfxlib_struct. +// TODO: this is basically a wrapper over CRadar. Remove + namespace Radar { // Sensor is a proxy for two types of information: From 7c357ba945d6341dbead9d285ad28b40c3a92da7 Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Thu, 26 Oct 2023 18:52:28 +0300 Subject: [PATCH 5/8] Fix bug in the radar where small ships are not tracked. --- engine/src/components/radar.cpp | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/engine/src/components/radar.cpp b/engine/src/components/radar.cpp index 7d381c20db..b8941a18cd 100644 --- a/engine/src/components/radar.cpp +++ b/engine/src/components/radar.cpp @@ -54,7 +54,19 @@ CRadar::CRadar(): lock_cone = configuration()->computer_config.default_lock_cone; } -CRadar::CRadar(std::string unit_key, Computer* computer) { +CRadar::CRadar(std::string unit_key, Computer* computer): + max_range(0), + max_cone(-1), + lock_cone(0), + tracking_cone(0), + min_target_size(0), + type(RadarType::SPHERE), + capabilities(RadarCapabilities::NONE), + locked(false), + can_lock(false), + tracking_active(true), + original(nullptr), + computer(nullptr) { can_lock = UnitCSVFactory::GetVariable(unit_key, "Can_Lock", true); // TODO: fix this @@ -99,9 +111,9 @@ CRadar::CRadar(std::string unit_key, Computer* computer) { tracking_active = true; max_range = UnitCSVFactory::GetVariable(unit_key, "Radar_Range", FLT_MAX); - max_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Max_Cone", 180.0f) * VS_PI / 180); + max_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Max_Cone", 180.0) * VS_PI / 180); tracking_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Tracking_Cone", 180.0f) * VS_PI / 180); - lock_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Lock_Cone", 180.0f) * VS_PI / 180); + lock_cone = cos(UnitCSVFactory::GetVariable(unit_key, "Lock_Cone", 180.0) * VS_PI / 180); original = nullptr; this->computer = computer; } @@ -115,8 +127,9 @@ void CRadar::WriteUnitString(std::map &unit) { unit["Lock_Cone"] = std::to_string(acos(lock_cone) * 180. / VS_PI); } -void CRadar::CRadar::Damage() +void CRadar::Damage() { + return; std::random_device rd; // a seed source for the random number engine std::mt19937 gen(rd()); // mersenne_twister_engine seeded with rd() std::uniform_int_distribution<> damage_distribution(0, 6); @@ -155,7 +168,7 @@ void CRadar::CRadar::Damage() } -void CRadar::CRadar::Repair() +void CRadar::Repair() { } @@ -179,11 +192,11 @@ void CRadar::Lock() { return; } - if(!UnitUtil::isSignificant(target)) { + /*if(!UnitUtil::isSignificant(target)) { std::cerr << "Target insignificant\n"; this->locked = false; return; - } + }*/ std::cout << "Target locked\n"; this->locked = true; From b8d3006108aff7b5a4e41104de5cc96bf6776eea Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Wed, 5 Feb 2025 22:52:48 +0200 Subject: [PATCH 6/8] Restore isSignificant Disable radar energy draw for now - game doesn't support it yet. --- engine/src/cmd/ai/fire.cpp | 3 ++- engine/src/cmd/ai/firekeyboard.cpp | 5 +++-- engine/src/components/radar.cpp | 26 ++++++++++++++++---------- engine/src/components/radar.h | 11 ++++------- engine/src/gfx/nav/drawsystem.cpp | 6 ++++-- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/engine/src/cmd/ai/fire.cpp b/engine/src/cmd/ai/fire.cpp index 2f9a6ee973..53e247027b 100644 --- a/engine/src/cmd/ai/fire.cpp +++ b/engine/src/cmd/ai/fire.cpp @@ -39,6 +39,7 @@ #include "lin_time.h" //DEBUG ONLY #include "cmd/pilot.h" #include "universe.h" +#include "unit_util.h" extern int numprocessed; extern double targetpick; @@ -657,7 +658,7 @@ void FireAt::ChooseTargets(int numtargs, bool force) { } } parent->Target(mytarg); - parent->radar.Lock(); + parent->radar.Lock(UnitUtil::isSignificant(parent)); SignalChosenTarget(); } diff --git a/engine/src/cmd/ai/firekeyboard.cpp b/engine/src/cmd/ai/firekeyboard.cpp index 5762b79201..c54a2e67fa 100644 --- a/engine/src/cmd/ai/firekeyboard.cpp +++ b/engine/src/cmd/ai/firekeyboard.cpp @@ -58,6 +58,7 @@ #include "mount_size.h" #include "weapon_info.h" #include "vs_logging.h" +#include "unit_util.h" extern bool toggle_pause(); @@ -1814,7 +1815,7 @@ void FireKeyboard::Execute() { f().targetskey = DOWN; ChooseTargets(parent, TargSig, false); refresh_target = true; - parent->radar.Lock(); + parent->radar.Lock(UnitUtil::isSignificant(parent)); } if (f().targetukey == PRESS) { f().targetukey = DOWN; @@ -1895,7 +1896,7 @@ void FireKeyboard::Execute() { f().rtargetskey = DOWN; ChooseTargets(parent, TargSig, true); refresh_target = true; - parent->radar.Lock(); + parent->radar.Lock(UnitUtil::isSignificant(parent)); } if (f().rtargetukey == PRESS) { f().rtargetukey = DOWN; diff --git a/engine/src/components/radar.cpp b/engine/src/components/radar.cpp index 69414adb3f..051f3c07a0 100644 --- a/engine/src/components/radar.cpp +++ b/engine/src/components/radar.cpp @@ -55,8 +55,8 @@ void CRadar::Load(std::string unit_key) { Component::Load(unit_key); // Consumer - double energy = UnitCSVFactory::GetVariable(unit_key, "Warp_Usage_Cost", 0.0f); - SetConsumption(energy * configuration()->fuel.ftl_drive_factor); + // TODO: energy + SetConsumption(0); // Radar can_lock = UnitCSVFactory::GetVariable(unit_key, "Can_Lock", true); @@ -184,20 +184,26 @@ void CRadar::Destroy() { // Radar Code // This code replaces and fixes the old code in Armed::LockTarget(bool) -void CRadar::Lock() { - if(!can_lock) { +void CRadar::Lock(bool always_lock) { + if(!can_lock && !always_lock) { this->locked = false; return; } - // TODO: re-enable - /*if(!UnitUtil::isSignificant(target)) { - std::cerr << "Target insignificant\n"; - this->locked = false; + this->locked = true; +} + +void CRadar::Unlock() { + locked = false; +} + +void CRadar::ToggleLock(bool always_lock) { + if(locked) { + locked = false; return; - }*/ + } - this->locked = true; + Lock(always_lock); } RadarType CRadar::GetType() const { diff --git a/engine/src/components/radar.h b/engine/src/components/radar.h index 69007ab930..0e9581afc3 100644 --- a/engine/src/components/radar.h +++ b/engine/src/components/radar.h @@ -96,13 +96,10 @@ class CRadar : public Component, public EnergyConsumer { // Radar Methods - void Lock(); - void Unlock() { - locked = false; - } - void ToggleLock() { - locked = !locked; - } + // always_lock - override some checks for targets such as planets + void Lock(bool always_lock = false); + void Unlock(); + void ToggleLock(bool always_lock = false); void Track(const bool track) { tracking_active = track; } void ToggleTracking() { tracking_active = !tracking_active; } diff --git a/engine/src/gfx/nav/drawsystem.cpp b/engine/src/gfx/nav/drawsystem.cpp index 52d1850a70..bc42afc615 100644 --- a/engine/src/gfx/nav/drawsystem.cpp +++ b/engine/src/gfx/nav/drawsystem.cpp @@ -60,6 +60,7 @@ #include "navscreen.h" #include "gfx/masks.h" #include "galaxy_gen.h" +#include "unit_util.h" //********************************** //Main function for drawing a CURRENT system @@ -438,6 +439,7 @@ void NavigationSystem::DrawSystem() { //give back the selected tail IF there is one //IF given back, undo the selection state //********************************** + Unit *current_player = UniverseUtil::getPlayerX(UniverseUtil::getCurrentPlayer()); if (1 || checkbit(buttonstates, 1)) { //button #2 is down, wanting a (selection) if (mouselist.get_n_contents() > 0) { @@ -448,8 +450,8 @@ void NavigationSystem::DrawSystem() { unsetbit(buttonstates, 1); //JUST FOR NOW, target == current selection. later it'll be used for other shit, that will then set target. if (currentselection.GetUnit()) { - (UniverseUtil::getPlayerX(UniverseUtil::getCurrentPlayer()))->Target(currentselection.GetUnit()); - (UniverseUtil::getPlayerX(UniverseUtil::getCurrentPlayer()))->radar.Lock(); + current_player->Target(currentselection.GetUnit()); + current_player->radar.Lock(UnitUtil::isSignificant(current_player)); } } } From 1edadb40f5c758faa0280fe905c9ae9fbd2cf960 Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Thu, 6 Feb 2025 10:00:24 +0200 Subject: [PATCH 7/8] Fix bug where max cone was incorrectly calculated. Cones are in radian and aren't linear. They can't be stores in Resource. --- engine/src/components/radar.cpp | 46 ++++++++++++++------------------- engine/src/components/radar.h | 7 ++--- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/engine/src/components/radar.cpp b/engine/src/components/radar.cpp index 051f3c07a0..121a231693 100644 --- a/engine/src/components/radar.cpp +++ b/engine/src/components/radar.cpp @@ -116,13 +116,13 @@ void CRadar::SaveToCSV(std::map& unit) const { unit["Radar_Range"] = max_range.Serialize(); // TODO: can't serialize if also doing acos on it - const double modifier = M_PI / 180; - unit["Tracking_Cone"] = std::to_string(acos(tracking_cone.Value()) * 180. / M_PI); - unit["Max_Cone"] = std::to_string(acos(max_cone.Value()) * 180. / M_PI); - unit["Lock_Cone"] = std::to_string(acos(lock_cone.Value()) * 180. / M_PI); + // Also, can't use Resource because games stores in radian + // and these can be minus. + unit["Tracking_Cone"] = std::to_string(acos(tracking_cone) * 180. / M_PI); + unit["Max_Cone"] = std::to_string(acos(max_cone) * 180. / M_PI); + unit["Lock_Cone"] = std::to_string(acos(lock_cone) * 180. / M_PI); } -// FTL drive is integrated and so cannot be upgraded/downgraded bool CRadar::CanDowngrade() const { return false; } @@ -141,43 +141,37 @@ bool CRadar::Upgrade(const std::string upgrade_key) { void CRadar::Damage() { max_range.RandomDamage(); - max_cone.RandomDamage(); - lock_cone.RandomDamage(); - tracking_cone.RandomDamage(); + // max_cone.RandomDamage(); + // lock_cone.RandomDamage(); + // tracking_cone.RandomDamage(); // We calculate percent operational as a simple average - operational = (max_range.Percent() + max_cone.Percent() + lock_cone.Percent() + - tracking_cone.Percent()) / 4 * 100; + operational = max_range.Percent() * 100; + + // Leaving this code here when we move to Resource for max, lock and tracking cones. + // operational = (max_range.Percent() + max_cone.Percent() + lock_cone.Percent() + + // tracking_cone.Percent()) / 4 * 100; } void CRadar::DamageByPercent(double percent) { max_range.DamageByPercent(percent); - max_cone.DamageByPercent(percent); - lock_cone.DamageByPercent(percent); - tracking_cone.DamageByPercent(percent); + // max_cone.DamageByPercent(percent); + // lock_cone.DamageByPercent(percent); + // tracking_cone.DamageByPercent(percent); // We calculate percent operational as a simple average - operational = (max_range.Percent() + max_cone.Percent() + lock_cone.Percent() + - tracking_cone.Percent()) / 4 * 100; + operational = max_range.Percent() * 100; } void CRadar::Repair() { max_range.RepairFully(); - max_cone.RepairFully(); - lock_cone.RepairFully(); - tracking_cone.RepairFully(); operational.RepairFully(); } void CRadar::Destroy() { max_range.Destroy(); - max_cone.Destroy(); - lock_cone.Destroy(); - tracking_cone.Destroy(); - operational = 0; - } @@ -227,15 +221,15 @@ float CRadar::GetMaxRange() const { } float CRadar::GetMaxCone() const { - return max_cone.Value(); + return max_cone; } float CRadar::GetLockCone() const { - return lock_cone.Value(); + return lock_cone; } float CRadar::GetTrackingCone() const { - return tracking_cone.Value(); + return tracking_cone; } float CRadar::GetMinTargetSize() const { diff --git a/engine/src/components/radar.h b/engine/src/components/radar.h index 0e9581afc3..482a162489 100644 --- a/engine/src/components/radar.h +++ b/engine/src/components/radar.h @@ -57,9 +57,10 @@ class CRadar : public Component, public EnergyConsumer { Resource max_range; //the dot with (0,0,1) indicating the farthest to the side the radar can handle. - Resource max_cone; - Resource lock_cone; - Resource tracking_cone; + // TODO: make this a resource when we move from radian to degrees + double max_cone; + double lock_cone; + double tracking_cone; //The minimum radius of the target double min_target_size; From a7f8222b02de9bb147fbed52ef79be942adfb551 Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Thu, 6 Feb 2025 10:07:22 +0200 Subject: [PATCH 8/8] Fix unit test Afterburner.sanity --- engine/src/components/tests/afterburner_tests.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/engine/src/components/tests/afterburner_tests.cpp b/engine/src/components/tests/afterburner_tests.cpp index d7a7ba2ad1..f799f00c97 100644 --- a/engine/src/components/tests/afterburner_tests.cpp +++ b/engine/src/components/tests/afterburner_tests.cpp @@ -65,10 +65,11 @@ TEST(Afterburner, Sanity) { EXPECT_EQ(afterburner.speed.MaxValue(), 100.0); EXPECT_EQ(afterburner.GetConsumption(), 2.0); + // Disabled. Afterburner_Upgrade does not get saved to file. //EXPECT_EQ(upgrade.GetMass(), 5.0); - EXPECT_EQ(upgrade.thrust, 1.5); - EXPECT_EQ(upgrade.speed, 1.5); - EXPECT_EQ(upgrade.consumption, 1.5); + // EXPECT_EQ(upgrade.thrust, 1.5); + // EXPECT_EQ(upgrade.speed, 1.5); + // EXPECT_EQ(upgrade.consumption, 1.5); } TEST(Afterburner, UpgradeDowngrade) {