sots-engine/src/game/data/shipsection.h

115 lines
4.5 KiB
C++

// game::data -- ShipSectionDef: one `Species/<Race>/sections/*.shipsection`.
//
// shipsection {
// model PATH requires_tech TECH... section_type command|mission|engine
// section_class destroyer|cruiser|dreadnought
// health mass cost cpoints crew socket_fore/socket_aft NODE
// option TECH -- one-member option group
// option { option A option B } -- mutually exclusive option group
// optiondef { option ... } -- shield-level group (shield sections)
// bank { turretclass C turretsize S [weapon FILE] mount { node N min/max_azimuth min/max_inclination } ... }
// ftlspeed nodespeed engine_techera netforcelimits { force_* torque_* speed rotspeed }
// thruster { node effect idle_effect }
// }
//
// `options` is the normalised view of every `option` entry in file order:
// a scalar `option T` becomes a one-member group, a block keeps its members.
// `section_type` / `section_class` are case-mixed in the data; the enums are
// derived case-insensitively and the text is kept as written.
#pragma once
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "game/data/block.h"
#include "game/data/common.h"
#include "mars/parse/blocks.h"
namespace game::data {
enum class SectionType { None, Command, Mission, Engine, Other };
enum class SectionClass { None, Destroyer, Cruiser, Dreadnought, Other };
std::string_view section_type_name(SectionType t);
std::string_view section_class_name(SectionClass c);
SectionType parse_section_type(std::string_view s);
SectionClass parse_section_class(std::string_view s);
struct OptionGroup {
std::vector<std::string> members; // tech names, file order
bool scalar = false; // written as `option T` (one member)
int line = 0;
};
struct MountDef {
std::string node;
std::optional<double> min_azimuth, max_azimuth, min_inclination, max_inclination;
std::optional<double> home_azimuth, home_inclination;
int line = 0;
};
struct BankDef {
std::string turret_class; // last value if the key repeats
std::string turret_size;
std::string weapon; // fixed weapon file (NPC banks); "" when the design chooses
std::optional<bool> show_turrets, invincible;
std::vector<MountDef> mounts;
bool repeated_turret_spec = false; // turretsize/turretclass written more than once
int line = 0;
};
struct NetForceLimits {
std::optional<double> force_forward, force_right, force_up;
std::optional<double> torque_yaw, torque_pitch, torque_roll;
std::optional<double> speed, rotspeed;
};
struct ThrusterDef {
std::string node, effect, idle_effect;
};
struct ShipSectionDef {
// identity (filled by the catalog)
std::string race; // directory name under Species/
Species species = Species::Unknown;
std::string stem;
std::string file;
std::optional<int> id; // from the race's _shipsections.txt
std::optional<std::string> display_name, description;
std::vector<std::string> unlocked_by; // techs whose ship{section} lists this stem
// body
std::string model, dam_model;
std::vector<std::string> requires_tech; // AND; may name GRP_<group>
std::string section_type_text;
SectionType section_type = SectionType::None;
std::string section_class_text;
SectionClass section_class = SectionClass::None;
std::string design_class, entity_class;
std::optional<double> health, mass;
std::optional<std::int64_t> cost, cpoints, crew;
std::optional<std::int64_t> command_cost, maintenance_cost, command_quota;
std::string socket_fore, socket_aft, dam_socket_fore, dam_socket_aft;
std::vector<OptionGroup> options;
std::optional<OptionGroup> optiondef;
std::vector<BankDef> banks;
std::optional<double> ftlspeed, nodespeed, range, scanrange, tactical_sensor_range;
std::string engine_techera;
std::optional<NetForceLimits> netforcelimits;
std::vector<ThrusterDef> thrusters;
std::vector<std::string> exclude;
std::string explicit_command_section, explicit_engine_section;
std::optional<bool> explicit_section, autonomous, nodesign;
Block raw;
bool has_sockets() const { return !socket_fore.empty() || !socket_aft.empty(); }
};
Loaded<ShipSectionDef> load_shipsection(const mars::parse::Document& doc, std::string file = {});
Loaded<ShipSectionDef> parse_shipsection(std::string_view text, std::string file = {});
} // namespace game::data