From b75fde92723910a985014d5a3516e78d99ab1b83 Mon Sep 17 00:00:00 2001 From: Roy Falk Date: Mon, 20 Feb 2023 21:58:21 +0200 Subject: [PATCH] Split master_part_list to multiple files Make ship into a separate superclass of unit Move additional methods to movable --- engine/CMakeLists.txt | 1 + engine/src/cmd/audible.h | 3 +- engine/src/cmd/carrier.cpp | 53 +++-- engine/src/cmd/energetic.h | 2 +- engine/src/cmd/movable.cpp | 363 ++++++++++++++++++++++++++++++++ engine/src/cmd/movable.h | 50 +++++ engine/src/cmd/ship.cpp | 41 ++++ engine/src/cmd/ship.h | 43 ++++ engine/src/cmd/unit_generic.cpp | 346 +----------------------------- engine/src/cmd/unit_generic.h | 67 ++---- 10 files changed, 557 insertions(+), 412 deletions(-) create mode 100644 engine/src/cmd/ship.cpp create mode 100644 engine/src/cmd/ship.h diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index d7d24ae005..4b9e6aca1e 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -1104,6 +1104,7 @@ SET(VEGASTRIKE_SOURCES src/cmd/music.cpp src/cmd/nebula.cpp src/cmd/planet.cpp + src/cmd/ship.cpp src/cmd/script/c_alike/c_alike.tab.cpp src/cmd/script/c_alike/lex.yy.cpp src/cmd/script/director.cpp diff --git a/engine/src/cmd/audible.h b/engine/src/cmd/audible.h index 3b26032d1e..c640565a77 100644 --- a/engine/src/cmd/audible.h +++ b/engine/src/cmd/audible.h @@ -52,10 +52,11 @@ class Audible { void playShieldDamageSound(const Vector &pnt); void playArmorDamageSound(const Vector &pnt); void playHullDamageSound(const Vector &pnt); + void playEngineSound(); protected: void playExplosionDamageSound(); - void playEngineSound(); + // TODO: make into a proper destructor void killSounds(); diff --git a/engine/src/cmd/carrier.cpp b/engine/src/cmd/carrier.cpp index 66036a4023..e1be6243bd 100644 --- a/engine/src/cmd/carrier.cpp +++ b/engine/src/cmd/carrier.cpp @@ -26,6 +26,7 @@ #include "carrier.h" #include "unit_generic.h" +#include "ship.h" #include "universe.h" #include "universe_util.h" @@ -228,7 +229,7 @@ void Carrier::EjectCargo(unsigned int index) { ++(fg->nr_ships); ++(fg->nr_ships_left); } - cargo = new Unit(ans.c_str(), false, unit->faction, "", fg, fgsnumber); + cargo = new Ship(ans.c_str(), false, unit->faction, "", fg, fgsnumber); cargo->PrimeOrders(); cargo->SetAI(new Orders::AggressiveAI("default.agg.xml")); cargo->SetTurretAI(); @@ -551,28 +552,38 @@ Unit *Carrier::makeMasterPartList() { Unit *ret = new Unit(); ret->name = "master_part_list"; - static std::string json_filename = "master_part_list.json"; //vs_config->getVariable("data", "master_part_list", "master_part_list"); - std::ifstream ifs(json_filename, std::ifstream::in); - std::stringstream buffer; - buffer << ifs.rdbuf(); - - const std::string json_text = buffer.str(); - - std::vector parts = json::parsing::parse_array(json_text.c_str()); - for (const std::string &part_text : parts) { - json::jobject part = json::jobject::parse(part_text); - Cargo carg; - - carg.name = getJSONValue(part, "file", ""); - carg.SetCategory(getJSONValue(part, "categoryname", "")); - carg.SetVolume(std::stof(getJSONValue(part, "volume", ""))); - carg.SetMass(std::stof(getJSONValue(part, "mass", ""))); - carg.quantity = 1; - carg.price = std::stoi(getJSONValue(part, "price", "")); - carg.SetDescription(getJSONValue(part, "description", "")); - ret->cargo.push_back(carg); + //vs_config->getVariable("data", "master_part_list", "master_part_list"); + static std::string json_filenames[] = { + "master_part_list.json", + "master_ship_list.json", + "master_component_list.json", + "master_asteroid_list.json", + }; + + for(const std::string& json_filename : json_filenames) { + std::ifstream ifs(json_filename, std::ifstream::in); + std::stringstream buffer; + buffer << ifs.rdbuf(); + + const std::string json_text = buffer.str(); + + std::vector parts = json::parsing::parse_array(json_text.c_str()); + for (const std::string &part_text : parts) { + json::jobject part = json::jobject::parse(part_text); + Cargo carg; + + carg.name = getJSONValue(part, "file", ""); + carg.SetCategory(getJSONValue(part, "categoryname", "")); + carg.SetVolume(std::stof(getJSONValue(part, "volume", ""))); + carg.SetMass(std::stof(getJSONValue(part, "mass", ""))); + carg.quantity = 1; + carg.price = std::stoi(getJSONValue(part, "price", "")); + carg.SetDescription(getJSONValue(part, "description", "")); + ret->cargo.push_back(carg); + } } + UpdateMasterPartList(ret); if (!ret->GetCargo("Pilot", i)) { //required items ret->AddCargo(Cargo("Pilot", "Contraband", 800, 1, .01, 1, 1.0, 1.0), true); diff --git a/engine/src/cmd/energetic.h b/engine/src/cmd/energetic.h index 15f7ed9690..7f3870c0fd 100644 --- a/engine/src/cmd/energetic.h +++ b/engine/src/cmd/energetic.h @@ -100,7 +100,7 @@ class Energetic { float warpenergy; //short fix float constrained_charge_to_shields; bool sufficient_energy_to_recharge_shields; -protected: +public: //fuel of this unit float fuel; diff --git a/engine/src/cmd/movable.cpp b/engine/src/cmd/movable.cpp index 8ab55a3163..7682b96a82 100644 --- a/engine/src/cmd/movable.cpp +++ b/engine/src/cmd/movable.cpp @@ -30,10 +30,14 @@ #include "universe.h" #include "configuration/game_config.h" #include "vs_logging.h" +#include "audiolib.h" +#include "audible.h" + #include #include #include +#include float accelStarHandler(float &input) { return input / (configuration()->physics_config.game_speed * configuration()->physics_config.game_accel); @@ -466,3 +470,362 @@ double Movable::GetMaxWarpFieldStrength(float rampmult) const { return minimum_multiplier; } + +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); + NetForce += Direction * (FuelSpeed * FMass / GetElapsedTime()); +} + +//applies a force for the whole gameturn upon the center of mass +void Movable::ApplyForce(const Vector &Vforce) { + if (FINITE(Vforce.i) && FINITE(Vforce.j) && FINITE(Vforce.k)) { + NetForce += Vforce; + } else { + VS_LOG(error, "fatal force"); + } +} + +//applies a force for the whole gameturn upon the center of mass +void Movable::ApplyLocalForce(const Vector &Vforce) { + if (FINITE(Vforce.i) && FINITE(Vforce.j) && FINITE(Vforce.k)) { + NetLocalForce += Vforce; + } else { + VS_LOG(error, "fatal local force"); + } +} + +void Movable::Accelerate(const Vector &Vforce) { + if (FINITE(Vforce.i) && FINITE(Vforce.j) && FINITE(Vforce.k)) { + NetForce += Vforce * Mass; + } else { + VS_LOG(error, "fatal force"); + } +} + +void Movable::ApplyTorque(const Vector &Vforce, const QVector &Location) { + //Not completely correct + NetForce += Vforce; + NetTorque += Vforce.Cross((Location - curr_physical_state.position).Cast()); +} + +void Movable::ApplyLocalTorque(const Vector &Vforce, const Vector &Location) { + NetForce += Vforce; + NetTorque += Vforce.Cross(Location); +} + +//usually from thrusters remember if I have 2 balanced thrusters I should multiply their effect by 2 :) +void Movable::ApplyBalancedLocalTorque(const Vector &Vforce, const Vector &Location) { + NetTorque += Vforce.Cross(Location); +} + +void Movable::ApplyLocalTorque(const Vector &torque) { + NetLocalTorque += ClampTorque(torque); +} + +Vector Movable::MaxTorque(const Vector &torque) { + //torque is a normal + return torque * (Vector(copysign(limits.pitch, torque.i), + copysign(limits.yaw, torque.j), + copysign(limits.roll, torque.k)) * torque); +} + +Vector Movable::ClampTorque(const Vector &amt1) { + Energetic *energetic = dynamic_cast(this); + Vector Res = amt1; + + energetic->WCWarpIsFuelHack(true); + + float fuelclamp = (energetic->fuelData() <= 0) ? configuration()->fuel.no_fuel_thrust : 1; + if (fabs(amt1.i) > fuelclamp * limits.pitch) { + Res.i = copysign(fuelclamp * limits.pitch, amt1.i); + } + if (fabs(amt1.j) > fuelclamp * limits.yaw) { + Res.j = copysign(fuelclamp * limits.yaw, amt1.j); + } + if (fabs(amt1.k) > fuelclamp * limits.roll) { + Res.k = copysign(fuelclamp * limits.roll, amt1.k); + } + //1/5,000,000 m/s + + energetic->ExpendMomentaryFuelUsage(Res.Magnitude()); + energetic->WCWarpIsFuelHack(false); + return Res; +} + + +Vector Movable::ClampVelocity(const Vector &velocity, const bool afterburn) { + Energetic *energetic = dynamic_cast(this); + Unit *unit = static_cast(this); + + float fuelclamp = (energetic->fuelData() <= 0) ? configuration()->fuel.no_fuel_thrust : 1; + float abfuelclamp = (energetic->fuelData() <= 0 || (energetic->energy < unit->afterburnenergy * simulation_atom_var)) ? configuration()->fuel.no_fuel_afterburn : 1; + float limit = + afterburn ? (abfuelclamp + * (unit->computer.max_ab_speed() + - unit->computer.max_speed()) + (fuelclamp * unit->computer.max_speed())) : fuelclamp + * unit->computer.max_speed(); + float tmp = velocity.Magnitude(); + if (tmp > fabs(limit)) { + return velocity * (limit / tmp); + } + return velocity; +} + + +Vector Movable::ClampAngVel(const Vector &velocity) { + Unit *unit = static_cast(this); + + Vector res(velocity); + if (res.i >= 0) { + if (res.i > unit->computer.max_pitch_down) { + res.i = unit->computer.max_pitch_down; + } + } else if (-res.i > unit->computer.max_pitch_up) { + res.i = -unit->computer.max_pitch_up; + } + if (res.j >= 0) { + if (res.j > unit->computer.max_yaw_left) { + res.j = unit->computer.max_yaw_left; + } + } else if (-res.j > unit->computer.max_yaw_right) { + res.j = -unit->computer.max_yaw_right; + } + if (res.k >= 0) { + if (res.k > unit->computer.max_roll_left) { + res.k = unit->computer.max_roll_left; + } + } else if (-res.k > unit->computer.max_roll_right) { + res.k = -unit->computer.max_roll_right; + } + return res; +} + +Vector Movable::MaxThrust(const Vector &amt1) { + //amt1 is a normal + return amt1 * (Vector(copysign(limits.lateral, amt1.i), + copysign(limits.vertical, amt1.j), + amt1.k > 0 ? limits.forward : -limits.retro) * amt1); +} + +//CMD_FLYBYWIRE depends on new version of Clampthrust... don't change without resolving it +// TODO: refactor soon. Especially access to the fuel variable +Vector Movable::ClampThrust(const Vector &amt1, bool afterburn) { + Unit *unit = static_cast(this); + + const bool WCfuelhack = configuration()->fuel.fuel_equals_warp; + const bool finegrainedFuelEfficiency = configuration()->fuel.variable_fuel_consumption; + if (WCfuelhack) { + if (unit->fuel > unit->warpenergy) { + unit->fuel = unit->warpenergy; + } + if (unit->fuel < unit->warpenergy) { + unit->warpenergy = unit->fuel; + } + } + float instantenergy = unit->afterburnenergy * simulation_atom_var; + if ((unit->afterburntype == 0) && unit->energy < instantenergy) { + afterburn = false; + } + if ((unit->afterburntype == 1) && unit->fuel < 0) { + unit->fuel = 0; + afterburn = false; + } + if ((unit->afterburntype == 2) && unit->warpenergy < 0) { + unit->warpenergy = 0; + afterburn = false; + } + if (3 == unit->afterburntype) { //no afterburner -- we should really make these types an enum :-/ + afterburn = false; + } + Vector Res = amt1; + + float fuelclamp = (unit->fuel <= 0) ? configuration()->fuel.no_fuel_thrust : 1; + float abfuelclamp = (unit->fuel <= 0) ? configuration()->fuel.no_fuel_afterburn : 1; + if (fabs(amt1.i) > fabs(fuelclamp * limits.lateral)) { + Res.i = copysign(fuelclamp * limits.lateral, amt1.i); + } + if (fabs(amt1.j) > fabs(fuelclamp * limits.vertical)) { + Res.j = copysign(fuelclamp * limits.vertical, amt1.j); + } + float ablimit = + afterburn + ? ((limits.afterburn - limits.forward) * abfuelclamp + limits.forward * fuelclamp) + : limits.forward; + if (amt1.k > ablimit) { + Res.k = ablimit; + } + if (amt1.k < -limits.retro) { + Res.k = -limits.retro; + } + const float Lithium6constant = configuration()->fuel.deuterium_relative_efficiency_lithium; + //1/5,000,000 m/s + const float FMEC_exit_vel_inverse = configuration()->fuel.fmec_exit_velocity_inverse; + if (unit->afterburntype == 2) { + //Energy-consuming afterburner + //HACK this forces the reaction to be Li-6+Li-6 fusion with efficiency governed by the getFuelUsage function + unit->warpenergy -= unit->afterburnenergy * Energetic::getFuelUsage(afterburn) * simulation_atom_var * Res.Magnitude() + * FMEC_exit_vel_inverse + / Lithium6constant; + } + if (3 == unit->afterburntype || unit->afterburntype == 1) { + //fuel-burning overdrive - uses afterburner efficiency. In NO_AFTERBURNER case, "afterburn" will always be false, so can reuse code. + //HACK this forces the reaction to be Li-6+Li-6 fusion with efficiency governed by the getFuelUsage function + unit->fuel -= + ((afterburn + && finegrainedFuelEfficiency) ? unit->afterburnenergy : Energetic::getFuelUsage(afterburn)) + * simulation_atom_var * Res.Magnitude() + * FMEC_exit_vel_inverse / Lithium6constant; +#ifndef __APPLE__ + if (ISNAN(unit->fuel)) { + VS_LOG(error, "Fuel is NAN A"); + unit->fuel = 0; + } +#endif + } + if (unit->afterburntype == 0) { + //fuel-burning afterburner - uses default efficiency - appears to check for available energy? FIXME + //HACK this forces the reaction to be Li-6+Li-6 fusion with efficiency governed by the getFuelUsage function + unit->fuel -= unit->getFuelUsage(false) * simulation_atom_var * Res.Magnitude() * FMEC_exit_vel_inverse / Lithium6constant; +#ifndef __APPLE__ + if (ISNAN(unit->fuel)) { + VS_LOG(error, "Fuel is NAN B"); + unit->fuel = 0; + } +#endif + } + if ((afterburn) && (unit->afterburntype == 0)) { + unit->energy -= instantenergy; + } + if (WCfuelhack) { + if (unit->fuel > unit->warpenergy) { + unit->fuel = unit->warpenergy; + } + if (unit->fuel < unit->warpenergy) { + unit->warpenergy = unit->fuel; + } + } + return Res; +} + +void Movable::LateralThrust(float amt) { + if (amt > 1.0) { + amt = 1.0; + } + if (amt < -1.0) { + amt = -1.0; + } + ApplyLocalForce(amt * limits.lateral * Vector(1, 0, 0)); +} + +void Movable::VerticalThrust(float amt) { + if (amt > 1.0) { + amt = 1.0; + } + if (amt < -1.0) { + amt = -1.0; + } + ApplyLocalForce(amt * limits.vertical * Vector(0, 1, 0)); +} + +void Movable::LongitudinalThrust(float amt) { + if (amt > 1.0) { + amt = 1.0; + } + if (amt < -1.0) { + amt = -1.0; + } + ApplyLocalForce(amt * limits.forward * Vector(0, 0, 1)); +} + +void Movable::YawTorque(float amt) { + if (amt > limits.yaw) { + amt = limits.yaw; + } else if (amt < -limits.yaw) { + amt = -limits.yaw; + } + ApplyLocalTorque(amt * Vector(0, 1, 0)); +} + +void Movable::PitchTorque(float amt) { + if (amt > limits.pitch) { + amt = limits.pitch; + } else if (amt < -limits.pitch) { + amt = -limits.pitch; + } + ApplyLocalTorque(amt * Vector(1, 0, 0)); +} + +void Movable::RollTorque(float amt) { + if (amt > limits.roll) { + amt = limits.roll; + } else if (amt < -limits.roll) { + amt = -limits.roll; + } + ApplyLocalTorque(amt * Vector(0, 0, 1)); +} + +void Movable::Thrust(const Vector &amt1, bool afterburn) { + Unit *unit = static_cast(this); + + if (unit->afterburntype == 0) { + afterburn = afterburn && unit->energy > unit->afterburnenergy * simulation_atom_var; + } //SIMULATION_ATOM; ? + if (unit->afterburntype == 1) { + afterburn = afterburn && unit->fuel > 0; + } + if (unit->afterburntype == 2) { + afterburn = afterburn && unit->warpenergy > 0; + } + + + //Unit::Thrust( amt1, afterburn ); + { + Vector amt = ClampThrust(amt1, afterburn); + ApplyLocalForce(amt); + } + + static bool must_afterburn_to_buzz = + XMLSupport::parse_bool(vs_config->getVariable("audio", "buzzing_needs_afterburner", "false")); + if (_Universe->isPlayerStarship(unit) != NULL) { + static int playerengine = AUDCreateSound(vs_config->getVariable("unitaudio", + "player_afterburner", + "sfx10.wav"), true); + static float enginegain = XMLSupport::parse_float(vs_config->getVariable("audio", "afterburner_gain", ".5")); + if (afterburn != AUDIsPlaying(playerengine)) { + if (afterburn) { + AUDPlay(playerengine, QVector(0, 0, 0), Vector(0, 0, 0), enginegain); + } else { + AUDStopPlaying(playerengine); + } + } + } else if (afterburn || !must_afterburn_to_buzz) { + static float buzzingtime = XMLSupport::parse_float(vs_config->getVariable("audio", "buzzing_time", "5")); + static float + buzzingdistance = XMLSupport::parse_float(vs_config->getVariable("audio", "buzzing_distance", "5")); + static float lastbuzz = getNewTime(); + Unit *playa = _Universe->AccessCockpit()->GetParent(); + if (playa) { + if (UnitUtil::getDistance(unit, + playa) < buzzingdistance && playa->owner != this && unit->owner != playa + && unit->owner != playa->owner) { + float ttime = getNewTime(); + if (ttime - lastbuzz > buzzingtime) { + Vector pvel = playa->GetVelocity(); + Vector vel = this->GetVelocity(); + pvel.Normalize(); + vel.Normalize(); + float dotprod = vel.Dot(pvel); + if (dotprod < .86) { + lastbuzz = ttime; + //AUDPlay( this->sound->engine, this->Position(), this->GetVelocity(), 1 ); + unit->playEngineSound(); + } else { + } + } + } + } + } +} diff --git a/engine/src/cmd/movable.h b/engine/src/cmd/movable.h index 681bbe4f79..a4e68445b2 100644 --- a/engine/src/cmd/movable.h +++ b/engine/src/cmd/movable.h @@ -247,6 +247,56 @@ class Movable { bool lastframe, UnitCollection *uc, Unit *superunit) = 0; + + /** + * Fire engine takes a unit vector for direction + * and how fast the fuel speed and mass coming out are + */ + /*unit vector... might default to "r"*/ + void FireEngines(const Vector &Direction, float FuelSpeed, float FMass); + //applies a force for the whole gameturn upon the center of mass + void ApplyForce(const Vector &Vforce); + //applies a force for the whole gameturn upon the center of mass, using local coordinates + void ApplyLocalForce(const Vector &Vforce); + //applies a force that is multipled by the mass of the ship + void Accelerate(const Vector &Vforce); + //Apply a torque in world level coords + void ApplyTorque(const Vector &Vforce, const QVector &Location); + //Applies a torque in local level coordinates + void ApplyLocalTorque(const Vector &Vforce, const Vector &Location); + //usually from thrusters remember if I have 2 balanced thrusters I should multiply their effect by 2 :) + void ApplyBalancedLocalTorque(const Vector &Vforce, const Vector &Location); + + //convenient shortcut to applying torques with vector and position + void ApplyLocalTorque(const Vector &torque); + + + //Clamps thrust to the limits struct + Vector ClampThrust(const Vector &thrust, bool afterburn); + //Takes a unit vector for direction of thrust and scales to limits + Vector MaxThrust(const Vector &thrust); + //Thrusts by ammt and clamps accordingly (afterburn or not) + virtual void Thrust(const Vector &amt, bool afterburn = false); + //Applies lateral thrust + void LateralThrust(float amt); + //Applies vertical thrust + void VerticalThrust(float amt); + //Applies forward thrust + void LongitudinalThrust(float amt); + //Clamps desired velocity to computer set limits + Vector ClampVelocity(const Vector &velocity, const bool afterburn); + //Clamps desired angular velocity to computer set limits + Vector ClampAngVel(const Vector &vel); + //Clamps desired torque to computer set limits of thrusters + Vector ClampTorque(const Vector &torque); + //scales unit size torque to limits in that direction + Vector MaxTorque(const Vector &torque); + //Applies a yaw of amt + void YawTorque(float amt); + //Applies a pitch of amt + void PitchTorque(float amt); + //Applies a roll of amt + void RollTorque(float amt); }; #endif // MOVABLE_H diff --git a/engine/src/cmd/ship.cpp b/engine/src/cmd/ship.cpp new file mode 100644 index 0000000000..29ff18061d --- /dev/null +++ b/engine/src/cmd/ship.cpp @@ -0,0 +1,41 @@ +/* + * ship.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 . + */ + +// -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- + +#include "ship.h" + +Ship::Ship() +{ + +} + +Ship::Ship(const char *filename, + bool SubU, + int faction, + std::string unitModifications, + Flightgroup *flightgrp, + int fg_subnumber) + : Unit(filename, SubU, faction, unitModifications, flightgrp, fg_subnumber) +{} diff --git a/engine/src/cmd/ship.h b/engine/src/cmd/ship.h new file mode 100644 index 0000000000..bf67db9087 --- /dev/null +++ b/engine/src/cmd/ship.h @@ -0,0 +1,43 @@ +/* + * ship.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 . + */ + +// -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- + +#ifndef SHIP_H +#define SHIP_H + +#include + +#include "unit_generic.h" + + +class Ship : public Unit +{ +public: + Ship(); + Ship(const char *filename, bool SubUnit, int faction, std::string customizedUnit = std::string( + ""), Flightgroup *flightgroup = NULL, int fg_subnumber = 0); +}; + +#endif // SHIP_H diff --git a/engine/src/cmd/unit_generic.cpp b/engine/src/cmd/unit_generic.cpp index de6dc45a03..410f02f861 100644 --- a/engine/src/cmd/unit_generic.cpp +++ b/engine/src/cmd/unit_generic.cpp @@ -272,7 +272,8 @@ char *GetUnitDir(const char *filename) { **** UNIT STUFF ********************************************************************************** */ -Unit::Unit(int /*dummy*/) : Drawable(), Damageable(), Movable() { +// Called by Planet +Unit::Unit(int dummy) : Drawable(), Damageable(), Movable() { pImage = (new UnitImages); pImage->cockpit_damage = NULL; pilot = new Pilot(FactionUtil::GetNeutralFaction()); @@ -280,6 +281,7 @@ Unit::Unit(int /*dummy*/) : Drawable(), Damageable(), Movable() { Init(); } + Unit::Unit() : Drawable(), Damageable(), Movable() //: cumulative_transformation_matrix( identity_matrix ) { pImage = (new UnitImages); @@ -289,6 +291,7 @@ Unit::Unit() : Drawable(), Damageable(), Movable() //: cumulative_transformation Init(); } +// Called by Missile Unit::Unit(std::vector &meshes, bool SubU, int fact) : Drawable(), Damageable(), Movable() //: cumulative_transformation_matrix( identity_matrix ) { @@ -309,6 +312,7 @@ Unit::Unit(std::vector &meshes, bool SubU, int fact) extern void update_ani_cache(); +// Called by Carrier and Mount Unit::Unit(const char *filename, bool SubU, int faction, @@ -1059,87 +1063,7 @@ Cockpit *Unit::GetVelocityDifficultyMult(float &difficulty) const { return player_cockpit; } -void Unit::FireEngines(const Vector &Direction /*unit vector... might default to "r"*/, - float FuelSpeed, - float FMass) { - FMass = ExpendFuel(FMass); - NetForce += Direction * (FuelSpeed * FMass / GetElapsedTime()); -} - -//applies a force for the whole gameturn upon the center of mass -void Unit::ApplyForce(const Vector &Vforce) { - if (FINITE(Vforce.i) && FINITE(Vforce.j) && FINITE(Vforce.k)) { - NetForce += Vforce; - } else { - VS_LOG(error, "fatal force"); - } -} - -//applies a force for the whole gameturn upon the center of mass -void Unit::ApplyLocalForce(const Vector &Vforce) { - if (FINITE(Vforce.i) && FINITE(Vforce.j) && FINITE(Vforce.k)) { - NetLocalForce += Vforce; - } else { - VS_LOG(error, "fatal local force"); - } -} - -void Unit::Accelerate(const Vector &Vforce) { - if (FINITE(Vforce.i) && FINITE(Vforce.j) && FINITE(Vforce.k)) { - NetForce += Vforce * Mass; - } else { - VS_LOG(error, "fatal force"); - } -} - -void Unit::ApplyTorque(const Vector &Vforce, const QVector &Location) { - //Not completely correct - NetForce += Vforce; - NetTorque += Vforce.Cross((Location - curr_physical_state.position).Cast()); -} - -void Unit::ApplyLocalTorque(const Vector &Vforce, const Vector &Location) { - NetForce += Vforce; - NetTorque += Vforce.Cross(Location); -} - -//usually from thrusters remember if I have 2 balanced thrusters I should multiply their effect by 2 :) -void Unit::ApplyBalancedLocalTorque(const Vector &Vforce, const Vector &Location) { - NetTorque += Vforce.Cross(Location); -} - -void Unit::ApplyLocalTorque(const Vector &torque) { - NetLocalTorque += ClampTorque(torque); -} - -Vector Unit::MaxTorque(const Vector &torque) { - //torque is a normal - return torque * (Vector(copysign(limits.pitch, torque.i), - copysign(limits.yaw, torque.j), - copysign(limits.roll, torque.k)) * torque); -} - -Vector Unit::ClampTorque(const Vector &amt1) { - Vector Res = amt1; - - WCWarpIsFuelHack(true); - - float fuelclamp = (fuel <= 0) ? configuration()->fuel.no_fuel_thrust : 1; - if (fabs(amt1.i) > fuelclamp * limits.pitch) { - Res.i = copysign(fuelclamp * limits.pitch, amt1.i); - } - if (fabs(amt1.j) > fuelclamp * limits.yaw) { - Res.j = copysign(fuelclamp * limits.yaw, amt1.j); - } - if (fabs(amt1.k) > fuelclamp * limits.roll) { - Res.k = copysign(fuelclamp * limits.roll, amt1.k); - } - //1/5,000,000 m/s - ExpendMomentaryFuelUsage(Res.Magnitude()); - WCWarpIsFuelHack(false); - return Res; -} void Unit::SwitchCombatFlightMode() { if (computer.combat_mode) { @@ -1153,20 +1077,7 @@ bool Unit::CombatMode() { return computer.combat_mode; } -Vector Unit::ClampVelocity(const Vector &velocity, const bool afterburn) { - float fuelclamp = (fuel <= 0) ? configuration()->fuel.no_fuel_thrust : 1; - float abfuelclamp = (fuel <= 0 || (energy < afterburnenergy * simulation_atom_var)) ? configuration()->fuel.no_fuel_afterburn : 1; - float limit = - afterburn ? (abfuelclamp - * (computer.max_ab_speed() - - computer.max_speed()) + (fuelclamp * computer.max_speed())) : fuelclamp - * computer.max_speed(); - float tmp = velocity.Magnitude(); - if (tmp > fabs(limit)) { - return velocity * (limit / tmp); - } - return velocity; -} + void Unit::ClearMounts() { for (unsigned int j = 0; j < mounts.size(); ++j) { @@ -1185,193 +1096,7 @@ void Unit::ClearMounts() { } } -Vector Unit::ClampAngVel(const Vector &velocity) { - Vector res(velocity); - if (res.i >= 0) { - if (res.i > computer.max_pitch_down) { - res.i = computer.max_pitch_down; - } - } else if (-res.i > computer.max_pitch_up) { - res.i = -computer.max_pitch_up; - } - if (res.j >= 0) { - if (res.j > computer.max_yaw_left) { - res.j = computer.max_yaw_left; - } - } else if (-res.j > computer.max_yaw_right) { - res.j = -computer.max_yaw_right; - } - if (res.k >= 0) { - if (res.k > computer.max_roll_left) { - res.k = computer.max_roll_left; - } - } else if (-res.k > computer.max_roll_right) { - res.k = -computer.max_roll_right; - } - return res; -} - -Vector Unit::MaxThrust(const Vector &amt1) { - //amt1 is a normal - return amt1 * (Vector(copysign(limits.lateral, amt1.i), - copysign(limits.vertical, amt1.j), - amt1.k > 0 ? limits.forward : -limits.retro) * amt1); -} - -//CMD_FLYBYWIRE depends on new version of Clampthrust... don't change without resolving it -// TODO: refactor soon. Especially access to the fuel variable -Vector Unit::ClampThrust(const Vector &amt1, bool afterburn) { - const bool WCfuelhack = configuration()->fuel.fuel_equals_warp; - const bool finegrainedFuelEfficiency = configuration()->fuel.variable_fuel_consumption; - if (WCfuelhack) { - if (fuel > warpenergy) { - fuel = warpenergy; - } - if (fuel < warpenergy) { - warpenergy = fuel; - } - } - float instantenergy = afterburnenergy * simulation_atom_var; - if ((afterburntype == 0) && energy < instantenergy) { - afterburn = false; - } - if ((afterburntype == 1) && fuel < 0) { - fuel = 0; - afterburn = false; - } - if ((afterburntype == 2) && warpenergy < 0) { - warpenergy = 0; - afterburn = false; - } - if (3 == afterburntype) { //no afterburner -- we should really make these types an enum :-/ - afterburn = false; - } - Vector Res = amt1; - - float fuelclamp = (fuel <= 0) ? configuration()->fuel.no_fuel_thrust : 1; - float abfuelclamp = (fuel <= 0) ? configuration()->fuel.no_fuel_afterburn : 1; - if (fabs(amt1.i) > fabs(fuelclamp * limits.lateral)) { - Res.i = copysign(fuelclamp * limits.lateral, amt1.i); - } - if (fabs(amt1.j) > fabs(fuelclamp * limits.vertical)) { - Res.j = copysign(fuelclamp * limits.vertical, amt1.j); - } - float ablimit = - afterburn - ? ((limits.afterburn - limits.forward) * abfuelclamp + limits.forward * fuelclamp) - : limits.forward; - if (amt1.k > ablimit) { - Res.k = ablimit; - } - if (amt1.k < -limits.retro) { - Res.k = -limits.retro; - } - const float Lithium6constant = configuration()->fuel.deuterium_relative_efficiency_lithium; - //1/5,000,000 m/s - const float FMEC_exit_vel_inverse = configuration()->fuel.fmec_exit_velocity_inverse; - if (afterburntype == 2) { - //Energy-consuming afterburner - //HACK this forces the reaction to be Li-6+Li-6 fusion with efficiency governed by the getFuelUsage function - warpenergy -= afterburnenergy * Energetic::getFuelUsage(afterburn) * simulation_atom_var * Res.Magnitude() - * FMEC_exit_vel_inverse - / Lithium6constant; - } - if (3 == afterburntype || afterburntype == 1) { - //fuel-burning overdrive - uses afterburner efficiency. In NO_AFTERBURNER case, "afterburn" will always be false, so can reuse code. - //HACK this forces the reaction to be Li-6+Li-6 fusion with efficiency governed by the getFuelUsage function - fuel -= - ((afterburn - && finegrainedFuelEfficiency) ? afterburnenergy : Energetic::getFuelUsage(afterburn)) - * simulation_atom_var * Res.Magnitude() - * FMEC_exit_vel_inverse / Lithium6constant; -#ifndef __APPLE__ - if (ISNAN(fuel)) { - VS_LOG(error, "Fuel is NAN A"); - fuel = 0; - } -#endif - } - if (afterburntype == 0) { - //fuel-burning afterburner - uses default efficiency - appears to check for available energy? FIXME - //HACK this forces the reaction to be Li-6+Li-6 fusion with efficiency governed by the getFuelUsage function - fuel -= getFuelUsage(false) * simulation_atom_var * Res.Magnitude() * FMEC_exit_vel_inverse / Lithium6constant; -#ifndef __APPLE__ - if (ISNAN(fuel)) { - VS_LOG(error, "Fuel is NAN B"); - fuel = 0; - } -#endif - } - if ((afterburn) && (afterburntype == 0)) { - energy -= instantenergy; - } - if (WCfuelhack) { - if (fuel > warpenergy) { - fuel = warpenergy; - } - if (fuel < warpenergy) { - warpenergy = fuel; - } - } - return Res; -} - -void Unit::LateralThrust(float amt) { - if (amt > 1.0) { - amt = 1.0; - } - if (amt < -1.0) { - amt = -1.0; - } - ApplyLocalForce(amt * limits.lateral * Vector(1, 0, 0)); -} - -void Unit::VerticalThrust(float amt) { - if (amt > 1.0) { - amt = 1.0; - } - if (amt < -1.0) { - amt = -1.0; - } - ApplyLocalForce(amt * limits.vertical * Vector(0, 1, 0)); -} - -void Unit::LongitudinalThrust(float amt) { - if (amt > 1.0) { - amt = 1.0; - } - if (amt < -1.0) { - amt = -1.0; - } - ApplyLocalForce(amt * limits.forward * Vector(0, 0, 1)); -} - -void Unit::YawTorque(float amt) { - if (amt > limits.yaw) { - amt = limits.yaw; - } else if (amt < -limits.yaw) { - amt = -limits.yaw; - } - ApplyLocalTorque(amt * Vector(0, 1, 0)); -} - -void Unit::PitchTorque(float amt) { - if (amt > limits.pitch) { - amt = limits.pitch; - } else if (amt < -limits.pitch) { - amt = -limits.pitch; - } - ApplyLocalTorque(amt * Vector(1, 0, 0)); -} -void Unit::RollTorque(float amt) { - if (amt > limits.roll) { - amt = limits.roll; - } else if (amt < -limits.roll) { - amt = -limits.roll; - } - ApplyLocalTorque(amt * Vector(0, 0, 1)); -} /* ********************************************************************************** @@ -4689,66 +4414,7 @@ void Unit::UpdatePhysics2(const Transformation &trans, /****************************** ONLY SOUND/GFX STUFF LEFT IN THOSE FUNCTIONS *********************************/ -void Unit::Thrust(const Vector &amt1, bool afterburn) { - if (this->afterburntype == 0) { - afterburn = afterburn && this->energy > this->afterburnenergy * simulation_atom_var; - } //SIMULATION_ATOM; ? - if (this->afterburntype == 1) { - afterburn = afterburn && this->fuel > 0; - } - if (this->afterburntype == 2) { - afterburn = afterburn && this->warpenergy > 0; - } - - - //Unit::Thrust( amt1, afterburn ); - { - Vector amt = ClampThrust(amt1, afterburn); - ApplyLocalForce(amt); - } - static bool must_afterburn_to_buzz = - XMLSupport::parse_bool(vs_config->getVariable("audio", "buzzing_needs_afterburner", "false")); - if (_Universe->isPlayerStarship(this) != NULL) { - static int playerengine = AUDCreateSound(vs_config->getVariable("unitaudio", - "player_afterburner", - "sfx10.wav"), true); - static float enginegain = XMLSupport::parse_float(vs_config->getVariable("audio", "afterburner_gain", ".5")); - if (afterburn != AUDIsPlaying(playerengine)) { - if (afterburn) { - AUDPlay(playerengine, QVector(0, 0, 0), Vector(0, 0, 0), enginegain); - } else { - AUDStopPlaying(playerengine); - } - } - } else if (afterburn || !must_afterburn_to_buzz) { - static float buzzingtime = XMLSupport::parse_float(vs_config->getVariable("audio", "buzzing_time", "5")); - static float - buzzingdistance = XMLSupport::parse_float(vs_config->getVariable("audio", "buzzing_distance", "5")); - static float lastbuzz = getNewTime(); - Unit *playa = _Universe->AccessCockpit()->GetParent(); - if (playa) { - if (UnitUtil::getDistance(this, - playa) < buzzingdistance && playa->owner != this && this->owner != playa - && this->owner != playa->owner) { - float ttime = getNewTime(); - if (ttime - lastbuzz > buzzingtime) { - Vector pvel = playa->GetVelocity(); - Vector vel = this->GetVelocity(); - pvel.Normalize(); - vel.Normalize(); - float dotprod = vel.Dot(pvel); - if (dotprod < .86) { - lastbuzz = ttime; - //AUDPlay( this->sound->engine, this->Position(), this->GetVelocity(), 1 ); - playEngineSound(); - } else { - } - } - } - } - } -} Vector Unit::ResolveForces(const Transformation &trans, const Matrix &transmat) { #ifndef PERFRAMESOUND diff --git a/engine/src/cmd/unit_generic.h b/engine/src/cmd/unit_generic.h index 2c7486a920..333fca87b7 100644 --- a/engine/src/cmd/unit_generic.h +++ b/engine/src/cmd/unit_generic.h @@ -189,6 +189,14 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p //forbidden Unit &operator=(const Unit &) = delete; + // Called by Carrier::makeMasterPartList + // TODO: Implement + /// move constructor + Unit(Unit && other) noexcept = delete; + + /// move assignment operator + Unit &operator=(Unit && other) noexcept = delete; + Unit(); ~Unit() override; @@ -196,21 +204,24 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p * constructors are used. The useless argument will be removed * again later. */ + + // Called by Planet Unit(int dummy); /** Constructor that creates aa mesh with meshes as submeshes (number * of them) as either as subunit with faction faction */ + // Called by Missile Unit(std::vector &meshes, bool Subunit, int faction); /** Constructor that creates a mesh from an XML file If it is a * customizedUnit, it will check in that directory in the home dir for * the unit. */ + // Called by Carrier and mount //Uses a lot of stuff that does not belong to here Unit(const char *filename, bool SubUnit, int faction, std::string customizedUnit = std::string( ""), Flightgroup *flightgroup = NULL, int fg_subnumber = 0); - public: //Initialize many of the defaults inherant to the constructor @@ -666,27 +677,9 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p void SetGlowVisible(bool isvis); -/** - * Fire engine takes a unit vector for direction - * and how fast the fuel speed and mass coming out are - */ -/*unit vector... might default to "r"*/ - void FireEngines(const Vector &Direction, float FuelSpeed, float FMass); -//applies a force for the whole gameturn upon the center of mass - void ApplyForce(const Vector &Vforce); -//applies a force for the whole gameturn upon the center of mass, using local coordinates - void ApplyLocalForce(const Vector &Vforce); -//applies a force that is multipled by the mass of the ship - void Accelerate(const Vector &Vforce); -//Apply a torque in world level coords - void ApplyTorque(const Vector &Vforce, const QVector &Location); -//Applies a torque in local level coordinates - void ApplyLocalTorque(const Vector &Vforce, const Vector &Location); -//usually from thrusters remember if I have 2 balanced thrusters I should multiply their effect by 2 :) - void ApplyBalancedLocalTorque(const Vector &Vforce, const Vector &Location); - -//convenient shortcut to applying torques with vector and position - void ApplyLocalTorque(const Vector &torque); + + + //Applies damage to the local area given by pnt float ApplyLocalDamage(const Vector &pnt, const Vector &normal, @@ -700,32 +693,7 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p //short fix // virtual void ArmorDamageSound( const Vector &pnt ) {} // virtual void HullDamageSound( const Vector &pnt ) {} -//Clamps thrust to the limits struct - Vector ClampThrust(const Vector &thrust, bool afterburn); -//Takes a unit vector for direction of thrust and scales to limits - Vector MaxThrust(const Vector &thrust); -//Thrusts by ammt and clamps accordingly (afterburn or not) - virtual void Thrust(const Vector &amt, bool afterburn = false); -//Applies lateral thrust - void LateralThrust(float amt); -//Applies vertical thrust - void VerticalThrust(float amt); -//Applies forward thrust - void LongitudinalThrust(float amt); -//Clamps desired velocity to computer set limits - Vector ClampVelocity(const Vector &velocity, const bool afterburn); -//Clamps desired angular velocity to computer set limits - Vector ClampAngVel(const Vector &vel); -//Clamps desired torque to computer set limits of thrusters - Vector ClampTorque(const Vector &torque); -//scales unit size torque to limits in that direction - Vector MaxTorque(const Vector &torque); -//Applies a yaw of amt - void YawTorque(float amt); -//Applies a pitch of amt - void PitchTorque(float amt); -//Applies a roll of amt - void RollTorque(float amt); + //executes a repair if the repair bot is up to it void Repair(); @@ -768,6 +736,7 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p */ public: + Unit *Threat(); //not used yet StringPool::Reference target_fgid[3]; @@ -781,7 +750,7 @@ class Unit : public Armed, public Audible, public Drawable, public Damageable, p const Unit *Target() const; Unit *VelocityReference(); const Unit *VelocityReference() const; - Unit *Threat(); + //Uses Universe stuff so only in Unit class void VelocityReference(Unit *targ); void TargetTurret(Unit *targ);