Files
flightgear/src/AIModel/AICarrier.hxx
T
2022-10-20 20:29:11 +08:00

182 lines
9.3 KiB
C++

// FGAICarrier - AIShip-derived class creates an AI aircraft carrier
//
// Written by David Culp, started October 2004.
//
// Copyright (C) 2004 David P. Culp - davidculp2@comcast.net
//
// This program 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.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#pragma once
#include <list>
#include <string>
#include <string_view>
#include <simgear/compiler.h>
#include <simgear/emesary/Emesary.hxx>
#include "AIShip.hxx"
#include "AIBase.hxx"
#include "AIManager.hxx"
class FGAIManager;
class FGAICarrier;
class FGAICarrier : public FGAIShip, simgear::Emesary::IReceiver
{
public:
FGAICarrier();
virtual ~FGAICarrier();
string_view getTypeString(void) const override { return "carrier"; }
void readFromScenario(SGPropertyNode* scFileNode) override;
void setSign(const std::string&);
void setDeckAltitudeFt(const double altitude_feet);
void setTACANChannelID(const std::string&);
double getDefaultModelRadius() override { return 350.0; }
void bind() override;
void UpdateWind(double dt);
void setWind_from_east(double fps);
void setWind_from_north(double fps);
void setMaxLat(double deg);
void setMinLat(double deg);
void setMaxLong(double deg);
void setMinLong(double deg);
void setMPControl(bool c);
void setAIControl(bool c);
void TurnToLaunch();
void TurnToRecover();
void TurnToBase();
void ReturnToBox();
bool OutsideBox();
bool init(ModelSearchOrder searchOrder) override;
bool getParkPosition(const std::string& id, SGGeod& geodPos, double& hdng, SGVec3d& uvw);
/**
* @brief type-safe wrapper around AIManager::getObjectFromProperty
*/
static SGSharedPtr<FGAICarrier> findCarrierByNameOrPennant(const std::string& namePennant);
static std::pair<bool, SGGeod> initialPositionForCarrier(const std::string& namePennant);
/**
* for a given scenario node, check for carriers within, and write nodes with
* names, pennants and initial position into the second argument.
* This is used to support 'start on a carrier', since we can quickly find
* the corresponding scenario file to be loaded.
*/
static void extractCarriersFromScenario(SGPropertyNode_ptr xmlNode, SGPropertyNode_ptr scenario);
bool getFLOLSPositionHeading(SGGeod& pos, double& heading) const;
double getFLOLFSGlidepathAngleDeg() const;
double getDeckAltitudeFt() const { return _deck_altitude_ft; }
virtual simgear::Emesary::ReceiptStatus Receive(simgear::Emesary::INotificationPtr n) override;
private:
/// Is sufficient to be private, stores a possible position to place an
/// aircraft on start
struct ParkPosition {
ParkPosition(const ParkPosition& pp)
: name(pp.name), offset(pp.offset), heading_deg(pp.heading_deg)
{
}
ParkPosition(const std::string& n, const SGVec3d& off = SGVec3d(), double heading = 0)
: name(n), offset(off), heading_deg(heading)
{
}
std::string name;
SGVec3d offset;
double heading_deg;
};
void update(double dt) override;
bool InToWind(); // set if the carrier is in to wind
void UpdateElevator(double dt);
void UpdateJBD(double dt);
bool _AIControl = false; // under AI control. Either this or MPControl will be true
SGPropertyNode_ptr _ai_latch_node;
SGPropertyNode_ptr _altitude_node;
double _angled_deck_degrees = -8.55; // angled deck offset from carrier heading. usually negative
double _base_course = 0;
double _base_speed = 0;
double _deck_altitude_ft = 65.0065;
double _elevator_pos_norm = 0;
double _elevator_pos_norm_raw = 0;
double _elevator_time_constant = 0;
double _elevator_transition_time = 0;
bool _elevators = false;
double _flols_angle = 0;
double _flols_dist = 0; // the distance of the eyepoint from the flols
int _flols_visible_light = 0; // the flols light which is visible at the moment
SGPropertyNode_ptr _flols_x_node;
SGPropertyNode_ptr _flols_y_node;
SGPropertyNode_ptr _flols_z_node;
double _flolsApproachAngle = 3.0; ///< glidepath angle for the FLOLS
double _flolsHeadingOffsetDeg = 0.0; /// angle in degrees offset from the carrier centerline
SGVec3d _flolsPosOffset;
SGVec3d _flolsTouchdownPosition;
SGPropertyNode_ptr _heading_node;
bool _in_to_wind = false;
bool _jbd = false;
double _jbd_elevator_pos_norm = 0;
double _jbd_elevator_pos_norm_raw = 0;
double _jbd_time_constant = 0;
double _jbd_transition_time = 0;
SGPropertyNode_ptr _latitude_node;
SGPropertyNode_ptr _launchbar_state_node;
double _lineup = 0; // lineup angle deviation from carrier;
SGPropertyNode_ptr _longitude_node;
SGVec3d _lsoPosition; /// LSO position
double _max_lat = 0;
double _max_lon = 0;
double _min_lat = 0;
double _min_lon = 0;
SGGeod _mOpBoxPos; // operational box limit for carrier.
bool _MPControl = false; // being controlled by MP. Either this or AIControl will be true
SGPropertyNode_ptr _pitch_node;
std::list<ParkPosition> _ppositions; // List of positions where an aircraft can start.
double _rel_wind = 0;
double _rel_wind_from_deg = 0;
double _rel_wind_speed_kts = 0;
bool _returning = false; // set if the carrier is returning to an operating box
SGPropertyNode_ptr _roll_node;
std::string _sign; // The sign (pennant) of this carrier; e.g. CVN-68
SGPropertyNode_ptr _surface_wind_from_deg_node;
SGPropertyNode_ptr _surface_wind_speed_node;
std::string _TACAN_channel_id;
SGVec3d _towerPosition;
bool _turn_to_base_course = true;
bool _turn_to_launch_hdg = true;
bool _turn_to_recovery_hdg = true;
int _view_index = 0;
SGPropertyNode_ptr _view_position_alt_ft_node;
SGPropertyNode_ptr _view_position_lat_deg_node;
SGPropertyNode_ptr _view_position_lon_deg_node;
bool _wave_off_lights_demand = false; // when waveoff requested.
double _wind_from_deg = 0; //true wind direction
double _wind_from_east = 0; // fps
double _wind_from_north = 0; // fps
double _wind_speed_kts = 0; //true wind speed
SGPropertyNode_ptr _is_user_craft;
};