From cbcae9da77ab28073e65fdbd97746c427abf2bf8 Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Sun, 1 Sep 2024 18:05:27 +0300 Subject: [PATCH] Implement cloak as a component (#872) - move cloak class to component folder - move some python functions from energetic to unit class in preparation to delete it - other callers to use the component functions --- engine/CMakeLists.txt | 3 +- engine/src/cmd/ai/firekeyboard.cpp | 2 +- engine/src/cmd/basecomputer.cpp | 28 ++--- engine/src/cmd/energetic.cpp | 24 +--- engine/src/cmd/energetic.h | 6 +- engine/src/cmd/movable.cpp | 28 ++--- engine/src/cmd/unit_csv.cpp | 5 +- engine/src/cmd/unit_generic.cpp | 29 +++-- engine/src/cmd/unit_generic.h | 7 +- engine/src/cmd/unit_util_generic.cpp | 4 + engine/src/cmd/upgradeable_unit.cpp | 14 ++- engine/src/{cmd => components}/cloak.cpp | 154 +++++++++++++++++------ engine/src/{cmd => components}/cloak.h | 54 ++++---- engine/src/components/component.h | 4 +- 14 files changed, 218 insertions(+), 144 deletions(-) rename engine/src/{cmd => components}/cloak.cpp (55%) rename engine/src/{cmd => components}/cloak.h (78%) diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 63f3fb91de..a0407d0c37 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -722,6 +722,8 @@ SET(LIBCOMPONENT src/components/energy_consumer.cpp src/components/energy_container.cpp src/components/reactor.cpp + + src/components/cloak.cpp ) SET(LIBGUI_SOURCES @@ -900,7 +902,6 @@ 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/firekeyboard.cpp b/engine/src/cmd/ai/firekeyboard.cpp index f792b8a85d..832d47aadb 100644 --- a/engine/src/cmd/ai/firekeyboard.cpp +++ b/engine/src/cmd/ai/firekeyboard.cpp @@ -2178,7 +2178,7 @@ void FireKeyboard::Execute() { } //use specialized ejectdock in the future } static bool actually_arrest = XMLSupport::parse_bool(vs_config->getVariable("AI", "arrest_energy_zero", "false")); - if (actually_arrest && parent->energyRechargeData() == 0) { + if (actually_arrest && parent->reactor.Capacity() == 0) { Arrested(parent); } } diff --git a/engine/src/cmd/basecomputer.cpp b/engine/src/cmd/basecomputer.cpp index 138547e734..d217ba348f 100644 --- a/engine/src/cmd/basecomputer.cpp +++ b/engine/src/cmd/basecomputer.cpp @@ -5184,7 +5184,7 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C if (shields_require_power) { maxshield = 0; } - PRETTY_ADDU(statcolor + "Recharge: #-c", playerUnit->energyRechargeData() * RSconverter, 0, "MJ/s"); + PRETTY_ADDU(statcolor + "Recharge: #-c", playerUnit->reactor.Capacity() * RSconverter, 0, "MJ/s"); PRETTY_ADDU(statcolor + "Weapon capacitor bank storage: #-c", ((playerUnit->maxEnergyData() - maxshield) * RSconverter), 0, "MJ"); //note: I found no function to get max warp energy, but since we're docked they are the same @@ -5223,9 +5223,9 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C } else { switch (replacement_mode) { case 0: //Replacement or new Module - if (MODIFIES(replacement_mode, playerUnit, blankUnit, energyRechargeData())) + if (MODIFIES(replacement_mode, playerUnit, blankUnit, reactor.Capacity())) PRETTY_ADDU(statcolor + "Installs reactor with recharge rate: #-c", - playerUnit->energyRechargeData() * RSconverter, 0, "MJ/s"); + playerUnit->reactor.Capacity() * RSconverter, 0, "MJ/s"); if (MODIFIES(replacement_mode, playerUnit, blankUnit, maxEnergyData())) PRETTY_ADDU(statcolor + "Installs main capacitor bank with storage capacity: #-c", (playerUnit->maxEnergyData() * RSconverter), 0, "MJ"); @@ -5238,9 +5238,9 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C } break; case 1: //Additive - if (MODIFIES(replacement_mode, playerUnit, blankUnit, energyRechargeData())) + if (MODIFIES(replacement_mode, playerUnit, blankUnit, reactor.Capacity())) PRETTY_ADDU(statcolor + "Increases recharge rate by #-c", - playerUnit->energyRechargeData() * RSconverter, 0, "MJ/s"); + playerUnit->reactor.Capacity() * RSconverter, 0, "MJ/s"); if (MODIFIES(replacement_mode, playerUnit, blankUnit, maxEnergyData())) PRETTY_ADDU(statcolor + "Adds #-c", (playerUnit->maxEnergyData() * RSconverter), @@ -5253,9 +5253,9 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C "MJ of storage to warp capacitor bank"); break; case 2: //multiplicative - if (MODIFIES(replacement_mode, playerUnit, blankUnit, energyRechargeData())) + if (MODIFIES(replacement_mode, playerUnit, blankUnit, reactor.Capacity())) PRETTY_ADDU(statcolor + "Increases reactor recharge rate by #-c", - 100.0 * (playerUnit->energyRechargeData() - 1), 0, "%"); + 100.0 * (playerUnit->reactor.Capacity() - 1), 0, "%"); if (MODIFIES(replacement_mode, playerUnit, blankUnit, maxEnergyData())) PRETTY_ADDU(statcolor + "Increases main capacitor bank storage by #-c", 100.0 * (playerUnit->maxEnergyData() - 1), 0, "%"); @@ -5432,14 +5432,14 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C if (playerUnit->cloak.Capable()) { if (!mode) { PRETTY_ADDU(statcolor + "Cloaking device available, energy usage: #-c", - playerUnit->cloak.Energy() * RSconverter * Wconv, + playerUnit->cloak.GetConsumption() * 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->cloak.Energy() * RSconverter * Wconv, + playerUnit->cloak.GetConsumption() * RSconverter * Wconv, 0, "MJ/s"); break; @@ -5616,7 +5616,7 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C float overhead = (shields_require_power) ? (regeneration / shieldenergycap * shield_maintenance_cost * num_shields * VSDM) : 0; - float nrt = avail / (playerUnit->energyRechargeData() * RSconverter); // TODO -overhead); + float nrt = avail / (playerUnit->reactor.Capacity() * RSconverter); // TODO -overhead); PRETTY_ADDU(statcolor + "Reactor nominal replenish time: #-c", nrt, 2, "seconds"); //shield related stuff //code taken from RegenShields in unit_generic.cpp, so we're sure what we say here is correct. @@ -5634,7 +5634,7 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C } if (num_shields) { - if (regeneration * num_shields * VSDM / shieldenergycap > playerUnit->energyRechargeData() + if (regeneration * num_shields * VSDM / shieldenergycap > playerUnit->reactor.Capacity() * RSconverter) { text += "#n##c1:1:.1#" + prefix + "WARNING: reactor recharge rate is less than combined shield recharge rate.#n#"; @@ -5643,7 +5643,7 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C if (shields_require_power) { text += "#n#" + prefix + statcolor + "Reactor recharge slowdown caused by shield maintenance: #-c"; float maint_draw_percent = regeneration * VSDM * 100.0 / shieldenergycap * shield_maintenance_cost - * num_shields / (playerUnit->energyRechargeData() * RSconverter); + * num_shields / (playerUnit->reactor.Capacity() * RSconverter); text += (boost::format("%1$.2f") % maint_draw_percent).str(); text += " %."; if (maint_draw_percent > 60) { @@ -5662,14 +5662,14 @@ void showUnitStats(Unit *playerUnit, string &text, int subunitlevel, int mode, C float maint_draw = (shields_require_power && num_shields) ? (regeneration * VSDM / shieldenergycap * shield_maintenance_cost * num_shields) : 0; - if (totalWeaponEnergyUsage < (playerUnit->energyRechargeData() * RSconverter - maint_draw)) { + if (totalWeaponEnergyUsage < (playerUnit->reactor.Capacity() * RSconverter - maint_draw)) { //waouh, impressive... text += "#n##c0:1:.2#" + prefix + "Your reactor produces more energy than your weapons can use!#-c"; } else { PRETTY_ADDU(statcolor + "Reactor energy depletion time if weapons in continuous use: #-c", (playerUnit->maxEnergyData() * RSconverter) / (totalWeaponEnergyUsage - - ((playerUnit->energyRechargeData() * RSconverter - maint_draw))), + - ((playerUnit->reactor.Capacity() * RSconverter - maint_draw))), 2, "seconds"); } diff --git a/engine/src/cmd/energetic.cpp b/engine/src/cmd/energetic.cpp index 4f94ebca12..4744d5f1cd 100644 --- a/engine/src/cmd/energetic.cpp +++ b/engine/src/cmd/energetic.cpp @@ -87,29 +87,7 @@ void Energetic::DecreaseWarpEnergyInWarp() { } } -float Energetic::energyData() const { - const Unit *unit = vega_dynamic_cast_ptr(this); - float capacitance = const_cast(this)->totalShieldEnergyCapacitance(); - - if (configuration()->physics_config.max_shield_lowers_capacitance) { - if (unit->energy.MaxLevel() <= capacitance) { - return 0; - } - return (unit->energy.Level()) / (unit->energy.MaxLevel() - capacitance); - } else { - return unit->energy.Percent(); - } -} -float Energetic::energyRechargeData() const { - const Unit *unit = vega_dynamic_cast_ptr(this); - return unit->reactor.Capacity(); -} - -float Energetic::fuelData() const { - const Unit *unit = vega_dynamic_cast_ptr(this); - return unit->fuel.Level(); -} float Energetic::getFuelUsage(bool afterburner) { if (afterburner) { @@ -236,7 +214,7 @@ float Energetic::warpEnergyData() const { } // Basically max or current shield x 0.2 -float Energetic::totalShieldEnergyCapacitance() { +float Energetic::totalShieldEnergyCapacitance() const { const Unit *unit = vega_dynamic_cast_ptr(this); DamageableLayer *shield = unit->shield; diff --git a/engine/src/cmd/energetic.h b/engine/src/cmd/energetic.h index e951a735dc..d767d41f70 100644 --- a/engine/src/cmd/energetic.h +++ b/engine/src/cmd/energetic.h @@ -36,10 +36,6 @@ class Energetic { void decreaseWarpEnergy(bool insys, double time); void DecreaseWarpEnergyInWarp(); - float energyData() const; - float energyRechargeData() const; - - float fuelData() const; static float getFuelUsage(bool afterburner); void WCWarpIsFuelHack(bool transfer_warp_to_fuel); @@ -65,7 +61,7 @@ class Energetic { void setAfterburnerEnergy(float aft); void setEnergyRecharge(float enrech); - float totalShieldEnergyCapacitance(); + float totalShieldEnergyCapacitance() const; static float VSDPercent(); diff --git a/engine/src/cmd/movable.cpp b/engine/src/cmd/movable.cpp index c737134ef9..d7acbde776 100644 --- a/engine/src/cmd/movable.cpp +++ b/engine/src/cmd/movable.cpp @@ -179,7 +179,7 @@ void Movable::UpdatePhysics(const Transformation &trans, } void Movable::AddVelocity(float difficulty) { - Unit *unit = static_cast(this); + const Unit *unit = vega_dynamic_const_cast_ptr(this); float lastWarpField = graphicOptions.WarpFieldStrength; bool playa = isPlayerShip(); @@ -474,8 +474,8 @@ double Movable::GetMaxWarpFieldStrength(float rampmult) const { void Movable::FireEngines(const Vector &Direction /*unit vector... might default to "r"*/, float FuelSpeed, float FMass) { - Energetic *energetic = dynamic_cast(this); - FMass = energetic->ExpendFuel(FMass); + Unit *unit = vega_dynamic_cast_ptr(this); + FMass = unit->ExpendFuel(FMass); NetForce += Direction * ((double)FuelSpeed * (double)FMass / GetElapsedTime()); } @@ -533,12 +533,12 @@ Vector Movable::MaxTorque(const Vector &torque) { } Vector Movable::ClampTorque(const Vector &amt1) { - Energetic *energetic = dynamic_cast(this); + Unit *unit = vega_dynamic_cast_ptr(this); Vector Res = amt1; - energetic->WCWarpIsFuelHack(true); + unit->WCWarpIsFuelHack(true); - float fuelclamp = (energetic->fuelData() <= 0) ? configuration()->fuel.no_fuel_thrust : 1; + float fuelclamp = (unit->fuel.Level() <= 0) ? configuration()->fuel.no_fuel_thrust : 1; if (fabs(amt1.i) > fuelclamp * limits.pitch) { Res.i = copysign(fuelclamp * limits.pitch, amt1.i); } @@ -550,18 +550,18 @@ Vector Movable::ClampTorque(const Vector &amt1) { } //1/5,000,000 m/s - energetic->ExpendMomentaryFuelUsage(Res.Magnitude()); - energetic->WCWarpIsFuelHack(false); + unit->ExpendMomentaryFuelUsage(Res.Magnitude()); + unit->WCWarpIsFuelHack(false); return Res; } Vector Movable::ClampVelocity(const Vector &velocity, const bool afterburn) { - Energetic *energetic = dynamic_cast(this); - Unit *unit = static_cast(this); + const Unit *unit = vega_dynamic_const_cast_ptr(this); + + float fuelclamp = (unit->fuel.Level() <= 0) ? configuration()->fuel.no_fuel_thrust : 1; + float abfuelclamp = (unit->fuel.Level() <= 0 || (unit->energy.Level() < unit->afterburnenergy * static_cast(simulation_atom_var))) ? configuration()->fuel.no_fuel_afterburn : 1; - float fuelclamp = (energetic->fuelData() <= 0) ? configuration()->fuel.no_fuel_thrust : 1; - float abfuelclamp = (energetic->fuelData() <= 0 || (unit->energy.Level() < unit->afterburnenergy * static_cast(simulation_atom_var))) ? configuration()->fuel.no_fuel_afterburn : 1; float limit = afterburn ? (abfuelclamp * (unit->computer.max_ab_speed() @@ -576,7 +576,7 @@ Vector Movable::ClampVelocity(const Vector &velocity, const bool afterburn) { Vector Movable::ClampAngVel(const Vector &velocity) { - Unit *unit = static_cast(this); + const Unit *unit = vega_dynamic_const_cast_ptr(this); Vector res(velocity); if (res.i >= 0) { @@ -769,7 +769,7 @@ void Movable::RollTorque(float amt) { } void Movable::Thrust(const Vector &amt1, bool afterburn) { - Unit *unit = static_cast(this); + Unit *unit = vega_dynamic_cast_ptr(this); if (unit->afterburntype == 0) { afterburn = afterburn && unit->energy.Level() > unit->afterburnenergy * static_cast(simulation_atom_var); diff --git a/engine/src/cmd/unit_csv.cpp b/engine/src/cmd/unit_csv.cpp index 307629808c..6a2b9f873e 100644 --- a/engine/src/cmd/unit_csv.cpp +++ b/engine/src/cmd/unit_csv.cpp @@ -932,7 +932,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); - cloak = Cloak(unit_key); + const static bool warp_energy_for_cloak = configuration()->warp_config.use_warp_energy_for_cloak; + cloak = Cloak(unit_key, (warp_energy_for_cloak ? &ftl_energy : &energy)); repair_droid = UnitCSVFactory::GetVariable(unit_key, "Repair_Droid", 0); ecm = UnitCSVFactory::GetVariable(unit_key, "ECM_Rating", 0); @@ -1375,7 +1376,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); - cloak.Save(unit); + cloak.SaveToCSV(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 73ed76c7a0..e93efabdf7 100644 --- a/engine/src/cmd/unit_generic.cpp +++ b/engine/src/cmd/unit_generic.cpp @@ -3384,19 +3384,7 @@ bool Unit::UpAndDownGrade(const Unit *up, } } } - if ((!cloak.Capable() && up->cloak.Capable()) || force_change_on_nothing) { - if (touchme) { - 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 (cloak.Capable() && up->cloak.Capable()) { - cancompletefully = false; - } + //NOTE: Afterburner type 2 (jmp) //NOTE: Afterburner type 1 (gas) //NOTE: Afterburner type 0 (pwr) @@ -4862,3 +4850,18 @@ bool Unit::TransferUnitToSystem(unsigned int kk, StarSystem *&savedStarSystem, b } return ret; } + +// TODO: move this to energy or just simplify +// Why single out shields from other constant drains? +float Unit::energyData() const { + float capacitance = totalShieldEnergyCapacitance(); + + if (configuration()->physics_config.max_shield_lowers_capacitance) { + if (energy.MaxLevel() <= capacitance) { + return 0; + } + return (energy.Level()) / (energy.MaxLevel() - capacitance); + } else { + return energy.Percent(); + } +} \ No newline at end of file diff --git a/engine/src/cmd/unit_generic.h b/engine/src/cmd/unit_generic.h index 7894a672ae..088b887e71 100644 --- a/engine/src/cmd/unit_generic.h +++ b/engine/src/cmd/unit_generic.h @@ -76,7 +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" @@ -84,6 +84,7 @@ void UncheckUnit( class Unit*un ); #include "cargo_color.h" // Components +#include "components/cloak.h" #include "components/energy_container.h" #include "components/reactor.h" @@ -997,6 +998,10 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p // object_a->field_a = object_b->field_b; float temporary_upgrade_float_variable; + + // Python Interfaces + float fuelData() const { return fuel.Level(); } + float energyData() const; }; Unit *findUnitInStarsystem(const void *unitDoNotDereference); diff --git a/engine/src/cmd/unit_util_generic.cpp b/engine/src/cmd/unit_util_generic.cpp index b508b2bfc0..09131f7fad 100644 --- a/engine/src/cmd/unit_util_generic.cpp +++ b/engine/src/cmd/unit_util_generic.cpp @@ -921,6 +921,10 @@ float PercentOperational(Unit *un, std::string name, std::string category, bool return un->reactor.Damaged() ? 0.5 : 1.0; } + if(upgrade_category == "Cloak") { + return un->cloak.Damaged() ? 0.5 : 1.0; + } + // Old Code if (category.find(DamagedCategory) == 0) { diff --git a/engine/src/cmd/upgradeable_unit.cpp b/engine/src/cmd/upgradeable_unit.cpp index 4888be8b5e..10252c1161 100644 --- a/engine/src/cmd/upgradeable_unit.cpp +++ b/engine/src/cmd/upgradeable_unit.cpp @@ -113,6 +113,10 @@ UpgradeType GetUpgradeType(const std::string upgrade_key) { return UpgradeType::Capacitor; } + if(upgrade_type_string == "Cloak") { + return UpgradeType::Cloak; + } + if(upgrade_type_string == "Jump_Drive") { return UpgradeType::Jump_Drive; } @@ -154,7 +158,10 @@ UpgradeOperationResult UpgradeableUnit::UpgradeUnit(const std::string upgrade_na result.upgradeable = true; result.success = unit->reactor.CanWillUpDowngrade(upgrade_key, upgrade, apply); break; - + case UpgradeType::Cloak: + result.upgradeable = true; + result.success = unit->cloak.CanWillUpDowngrade(upgrade_key, upgrade, apply); + break; /*case UpgradeType::Afterburner: result.upgradeable = true; result.success = unit->afterburner.CanWillUpDowngrade(upgrade_key, upgrade, apply); @@ -169,10 +176,7 @@ UpgradeOperationResult UpgradeableUnit::UpgradeUnit(const std::string upgrade_na result.success = unit->jump_drive.CanWillUpDowngrade(upgrade_key, upgrade, apply); break; - case UpgradeType::Cloak: - result.upgradeable = true; - result.success = unit->cloak.CanWillUpDowngrade(upgrade_key, upgrade, apply); - break; + /*case UpgradeType::ECM: result.upgradeable = true; result.success = unit->ecm.CanWillUpDowngrade(upgrade_key, upgrade, apply); diff --git a/engine/src/cmd/cloak.cpp b/engine/src/components/cloak.cpp similarity index 55% rename from engine/src/cmd/cloak.cpp rename to engine/src/components/cloak.cpp index f74cc0c2f6..7a7b451ad5 100644 --- a/engine/src/cmd/cloak.cpp +++ b/engine/src/components/cloak.cpp @@ -28,42 +28,95 @@ #include "configuration/configuration.h" #include "unit_generic.h" -Cloak::Cloak() +Cloak::Cloak() : + Component(), + EnergyConsumer(nullptr, 0, false) { + _Downgrade(); +} + +Cloak::Cloak(std::string unit_key, EnergyContainer* capacitor) : + Component(), + EnergyConsumer(capacitor, + UnitCSVFactory::GetVariable(unit_key, "Cloak_Energy", 0.0), + false) +{ + _Upgrade(unit_key); +} + +// Component Overrides +void Cloak::SaveToCSV(std::map& unit) const { + 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(consumption); + unit["Cloak_Glass"] = std::to_string(glass); +} + +std::string Cloak::Describe() const { + return std::string(); +} + +bool Cloak::CanDowngrade() const { + return true; +} + +bool Cloak::Downgrade() { + Component::Downgrade(); + SetConsumption(0); + status = CloakingStatus::disabled; - energy = 0; rate = 100; glass = false; current = 0; minimum = 0; + + return true; } -Cloak::Cloak(std::string unit_key) -{ - if(UnitCSVFactory::GetVariable(unit_key, "Can_Cloak", false)) { +bool Cloak::CanUpgrade(const std::string upgrade_key) const { + return true; +} + +bool Cloak::Upgrade(const std::string upgrade_key) { + _Upgrade(upgrade_key); + + return true; +} + + +// TODO: more granular damage +// TODO: damageable component +void Cloak::Damage() { + status = CloakingStatus::damaged; + current = 0; +} + +void Cloak::DamageByPercent(double percent) { + // TODO: implement + Damage(); +} + +void Cloak::Repair() { + if(status == CloakingStatus::damaged) { status = CloakingStatus::ready; - } else { - status = CloakingStatus::disabled; + current = 0; } +} - 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; +bool Cloak::Damaged() const { + return status == CloakingStatus::damaged; } -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); +bool Cloak::Installed() const { + return status != CloakingStatus::disabled; } + + +// Cloak Methods + void Cloak::Update(Unit *unit) { // Unit is not capable of cloaking or damaged or just not cloaking @@ -73,22 +126,21 @@ void Cloak::Update(Unit *unit) 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 ? unit->ftl_energy.Level() : unit->energy.Level(); + double actual_available_energy = Consume(); + if(actual_available_energy < 1.0) { + // Insufficient energy to cloak ship + status = CloakingStatus::decloaking; + } + // TODO: Use warp power for cloaking (SPEC capacitor) + //const static bool warp_energy_for_cloak = configuration()->warp_config.use_warp_energy_for_cloak; + - // Insufficient energy to cloak ship - if(available_energy < this->energy) { - status = CloakingStatus::decloaking; - } else { - // Subtract the energy used - if (warp_energy_for_cloak) { - unit->ftl_energy.Deplete(true, simulation_atom_var * energy); - } else { - unit->energy.Deplete(true, simulation_atom_var * energy); - } - } + + + // TODO: deplete has a more elegant solution for this code. + // Also use a pointer to which is used instead of ifs + if(status == CloakingStatus::decloaking) { current = std::max(0.0, current - rate * simulation_atom_var); @@ -105,8 +157,6 @@ void Cloak::Update(Unit *unit) status = CloakingStatus::cloaked; } } - - } void Cloak::Toggle() { @@ -143,3 +193,35 @@ void Cloak::Deactivate() { // Start decloaking status = CloakingStatus::decloaking; } + +void Cloak::_Downgrade() { + Component::Downgrade(); + SetConsumption(0); + + status = CloakingStatus::disabled; + + rate = 100; + glass = false; + current = 0; + minimum = 0; + + +} + +void Cloak::_Upgrade(const std::string upgrade_key) { + Component::Upgrade(upgrade_key); + + SetConsumption(UnitCSVFactory::GetVariable(upgrade_key, "Cloak_Energy", 0.0)); + + if(UnitCSVFactory::GetVariable(upgrade_key, "Can_Cloak", false)) { + status = CloakingStatus::ready; + } else { + status = CloakingStatus::disabled; + } + + glass = UnitCSVFactory::GetVariable(upgrade_key, "Cloak_Glass", false); + rate = UnitCSVFactory::GetVariable(upgrade_key, "Cloak_Rate", 0.0); + minimum = UnitCSVFactory::GetVariable(upgrade_key, "Cloak_Min", 0.0); + minimum = std::min(1.0, std::max(0.0, minimum)); + current = 0; +} \ No newline at end of file diff --git a/engine/src/cmd/cloak.h b/engine/src/components/cloak.h similarity index 78% rename from engine/src/cmd/cloak.h rename to engine/src/components/cloak.h index 2a63e76b44..460bcc6f9a 100644 --- a/engine/src/cmd/cloak.h +++ b/engine/src/components/cloak.h @@ -30,6 +30,8 @@ #include "energetic.h" #include "damageable_layer.h" +#include "energy_container.h" +#include "energy_consumer.h" // TODO: remove dependency on unit class Unit; @@ -43,15 +45,12 @@ enum class CloakingStatus { decloaking }; -class Cloak +class Cloak : public Component, public EnergyConsumer { friend class Unit; CloakingStatus status; - // How much energy cloaking takes per frame - double energy; - // How fast does this starship cloak/decloak double rate; @@ -67,8 +66,25 @@ class Cloak public: Cloak(); - Cloak(std::string unit_key); - void Save(std::map& unit); + Cloak(std::string unit_key, EnergyContainer* capacitor); + + virtual void SaveToCSV(std::map& unit) const; + virtual std::string Describe() const; + + virtual bool CanDowngrade() const; + + virtual bool Downgrade(); + + virtual bool CanUpgrade(const std::string upgrade_key) const; + + virtual bool Upgrade(const std::string upgrade_key); + + virtual void Damage(); + virtual void DamageByPercent(double percent); + virtual void Repair(); + + virtual bool Damaged() const; + virtual bool Installed() const; void Update(Unit *unit); void Toggle(); // Toggle cloak on/off @@ -92,10 +108,6 @@ class Cloak status == CloakingStatus::decloaking); } - bool Damaged() { - return (status == CloakingStatus::damaged); - } - bool Ready() { return (status == CloakingStatus::ready); } @@ -104,9 +116,7 @@ class Cloak return glass; } - double Energy() { - return energy; - } + // Is the ship visible bool Visible() { @@ -122,20 +132,6 @@ class Cloak 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; @@ -148,6 +144,10 @@ class Cloak void Activate(); void Deactivate(); + +private: + void _Downgrade(); + void _Upgrade(const std::string upgrade_key); }; #endif // CLOAK_H diff --git a/engine/src/components/component.h b/engine/src/components/component.h index 7539578b71..2288e417a2 100644 --- a/engine/src/components/component.h +++ b/engine/src/components/component.h @@ -59,8 +59,8 @@ class Component bool integral = false; // Part of the ship. Can't be upgraded/downgraded public: - Component(double mass, - double volume, bool integral); + Component(double mass = 0, + double volume = 0, bool integral = false); // Load from units dictionary virtual void Load(std::string upgrade_key, std::string unit_key);