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

108 lines
4.3 KiB
C++

// game::data -- WeaponDef: one `*.weapon` file.
//
// weapon {
// name @WEAPON_X weaponclass bullet weaponfamily gauss
// requires TECH [requires TECH2] cost N
// turretsize small turretclass standard
// burst_volleys N recharge_time T range R range_planet RP
// fc_* true/false rating_* N
// <class block> { rangetable {...} dam_pop dam_infra dam_terra ... }
// }
//
// Typed fields cover the keys design/combat rules read; the class-specific
// behaviour block (bolt/beam/torpedo/missile/...) is typed for `bolt` and
// reachable for every class through `behavior()` / `raw`.
#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 WeaponScope { Player, NPC };
// Damage falloff by range band: point-blank / effective / maximum.
struct RangeTable {
struct Band {
std::optional<double> range, deviation, damage;
};
Band point_blank, effective, maximum;
};
// Damage applied to a planet on impact (present in most behaviour blocks).
struct PlanetDamage {
std::optional<double> pop, infra, terra;
};
struct BoltDef {
RangeTable rangetable;
PlanetDamage planet;
std::optional<double> mass, beam_origin, beam_length, ricochet_mod;
std::string effect, impact_effect, expire_effect;
};
struct FireControl {
std::optional<bool> requires_los, requires_inrange, requires_enemycolony;
std::optional<bool> manual_target, manual_toggle, manual_launch;
std::optional<bool> controllable, holdsfire;
std::optional<bool> explicit_target, exclusive_launch, targets_expire;
};
struct Ratings {
std::optional<double> fire_rate, damage, accuracy, range;
};
struct WeaponDef {
// identity (filled by the catalog; empty/nullopt for a standalone load)
std::string stem; // file name without extension, as on disk
std::string file; // path relative to the data root, '/'-separated
WeaponScope scope = WeaponScope::Player;
std::optional<int> id; // from Weapons/_weapons.txt (player weapons only)
std::optional<std::string> display_name; // resolved `name` token
// body
std::string name; // "@WEAPON_X" token as written
std::string weapon_class; // drives engine behaviour (bullet, beam, missile, ...)
std::string weapon_family; // AI grouping (gauss, laser, torpedo, ...)
std::string weapon_damage_type;
std::vector<std::string> requires; // AND of techs; may be empty
std::vector<std::string> compatible_section; // rider weapons: section stems they carry
std::string exclusive_species;
std::optional<std::int64_t> cost;
std::string turret_size; // tiny / small / medium / large (as written)
std::string turret_class; // standard / missile / beam / ... (as written)
std::optional<double> track_speed_mod;
std::optional<std::int64_t> burst_volleys;
std::optional<double> recharge_time, volley_period, volley_duration, buildup_delay, solution_tolerance;
std::optional<std::int64_t> range, range_planet, muzzle_speed, hpbonus, dam_est;
std::optional<bool> hidden, pinpoint, blindfire, secondary_pd;
std::string model1, model2, model3;
std::string muzzle_effect, muzzle_sound, icon_file, icon_rect;
FireControl fc;
Ratings ratings;
std::string behavior_kind; // name of the class block found (bolt, beam, torpedo, ...)
std::optional<BoltDef> bolt; // typed when behavior_kind == "bolt"
std::optional<RangeTable> rangetable; // from bolt{} or torpedo{}
PlanetDamage planet_damage; // dam_pop/infra/terra of the behaviour block
Block raw; // the whole weapon{} block
const Block* behavior() const { return behavior_kind.empty() ? nullptr : raw.block(behavior_kind); }
};
// Names of the behaviour blocks the engine keys on `weaponclass`; the loader
// takes the first of these present in the weapon block.
const std::vector<std::string_view>& weapon_behavior_blocks();
Loaded<WeaponDef> load_weapon(const mars::parse::Document& doc, std::string file = {});
Loaded<WeaponDef> parse_weapon(std::string_view text, std::string file = {});
} // namespace game::data