1261c30724
The interceptor's launch is one sequence: the cap opens, the round is thrown out unlit and slows under linear gas drag (`cold` ticks), the motor lights where it has reached, it turns with a growing rate while thrust spools up (`boost` ticks), and full guidance starts only at `cold + boost`. A rail launch lights at once but spools over the same `boost` ticks; the electric P1-SUN has no rocket spool or plume. S-400/500 now hold the unlit ejection for 20/24 ticks (1.00/1.20 s at 20 Hz); IRIS-T/Tor keep shorter 8-tick throws. Ignition, its sound, flame and recorded MotorIgnition event all use the missile's current position. The RM48U strike follows the same 20-tick choreography, counts the throw in its flight time and starts its recorded smoke at ignition. Maximum speed, turn, accel, pk and every collision rule are unchanged. Co-Authored-By: Kimi Code <noreply@kimi.com>
543 lines
13 KiB
Rust
543 lines
13 KiB
Rust
// Generated by tools/gen_catalog.py from catalog/specs.json. Do not edit.
|
||
// Game-scale values, not real weapon data; the catalog is the only copy.
|
||
|
||
/// Share of the old slew speed a launcher keeps when it has no rate of its own.
|
||
const DRIVE_SCALE: f64 = 0.4;
|
||
/// Ticks a drive takes to reach its top speed (and to stop from it).
|
||
const DRIVE_RAMP: f64 = 8.0;
|
||
const DRIVE_TRAINABLE: (f64, f64) = (0.12, 0.0);
|
||
const DRIVE_VERTICAL: (f64, f64) = (0.15, 0.0);
|
||
const DRIVE_OTHER: (f64, f64) = (0.05, 0.05);
|
||
/// Ballistic flight's gravity, blocks a tick².
|
||
const GRAVITY: f64 = 0.05;
|
||
/// Height over the target where the Oreshnik's blocks release their submunitions.
|
||
const BLOCK_SPLIT: f64 = 300.0;
|
||
/// How near a depot a system reloads straight from it.
|
||
const DEPOT_REACH: f64 = 60.0;
|
||
/// How near a truck must come to hand a reload over, or to load up at a depot.
|
||
const HANDOVER: f64 = 10.0;
|
||
/// What a truck carries.
|
||
const TRUCK_LOAD: u32 = 2;
|
||
const STOCK_LIMIT: u32 = 1000000;
|
||
|
||
const DRONE_SPEC_SHAHED: DroneSpec = DroneSpec {
|
||
name: "Шахед-136",
|
||
key: "shahed",
|
||
model: "airdef:shahed",
|
||
speed: 0.6,
|
||
turn: 0.035,
|
||
cruise: 45.0,
|
||
clearance: 18.0,
|
||
dive: 32.0,
|
||
warhead: 3,
|
||
scale: 1.3,
|
||
engine: Engine::Prop(1.34, 1.0),
|
||
decoy: false,
|
||
stealth: 1.0,
|
||
rcs: 0.3,
|
||
sound: (sound::DRONE_SHAHED, 1.0, 48),
|
||
class: Class::Drone,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_S400_EJECT,
|
||
};
|
||
|
||
const DRONE_SPEC_GERAN3: DroneSpec = DroneSpec {
|
||
name: "Герань-3",
|
||
key: "geran3",
|
||
model: "airdef:geran3",
|
||
speed: 1.6,
|
||
turn: 0.03,
|
||
cruise: 60.0,
|
||
clearance: 18.0,
|
||
dive: 50.0,
|
||
warhead: 2,
|
||
scale: 1.15,
|
||
engine: Engine::Jet(0.34, 1.55, 1.0),
|
||
decoy: false,
|
||
stealth: 1.1,
|
||
rcs: 0.4,
|
||
sound: (sound::DRONE_GERAN3, 1.0, 40),
|
||
class: Class::Jet,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_S400_EJECT,
|
||
};
|
||
|
||
const DRONE_SPEC_LANCET: DroneSpec = DroneSpec {
|
||
name: "Ланцет-3",
|
||
key: "lancet",
|
||
model: "airdef:lancet",
|
||
speed: 1.1,
|
||
turn: 0.07,
|
||
cruise: 25.0,
|
||
clearance: 10.0,
|
||
dive: 38.0,
|
||
warhead: 1,
|
||
scale: 0.9,
|
||
engine: Engine::Prop(0.93, 0.55),
|
||
decoy: false,
|
||
stealth: 1.4,
|
||
rcs: 0.08,
|
||
sound: (sound::DRONE_LANCET, 1.0, 32),
|
||
class: Class::Drone,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_S400_EJECT,
|
||
};
|
||
|
||
const DRONE_SPEC_GERBERA: DroneSpec = DroneSpec {
|
||
name: "Гербера",
|
||
key: "gerbera",
|
||
model: "airdef:gerbera",
|
||
speed: 0.5,
|
||
turn: 0.04,
|
||
cruise: 40.0,
|
||
clearance: 15.0,
|
||
dive: 30.0,
|
||
warhead: 0,
|
||
scale: 1.1,
|
||
engine: Engine::Prop(1.03, 0.9),
|
||
decoy: true,
|
||
stealth: 0.9,
|
||
rcs: 0.4,
|
||
sound: (sound::DRONE_SHAHED, 1.3, 40),
|
||
class: Class::Drone,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_S400_EJECT,
|
||
};
|
||
|
||
const DRONE_SPEC_KH101: DroneSpec = DroneSpec {
|
||
name: "Х-101",
|
||
key: "kh101",
|
||
model: "airdef:kh101",
|
||
speed: 2.4,
|
||
turn: 0.025,
|
||
cruise: 0.0,
|
||
clearance: 12.0,
|
||
dive: 26.0,
|
||
warhead: 6,
|
||
scale: 1.6,
|
||
engine: Engine::Jet(-0.27, 1.4, 0.6),
|
||
decoy: false,
|
||
stealth: 1.5,
|
||
rcs: 0.05,
|
||
sound: (sound::DRONE_CRUISE, 1.0, 50),
|
||
class: Class::Cruise,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_PATRIOT,
|
||
};
|
||
|
||
const DRONE_SPEC_KALIBR: DroneSpec = DroneSpec {
|
||
name: "Калибр",
|
||
key: "kalibr",
|
||
model: "airdef:kalibr",
|
||
speed: 2.1,
|
||
turn: 0.025,
|
||
cruise: 0.0,
|
||
clearance: 15.0,
|
||
dive: 26.0,
|
||
warhead: 5,
|
||
scale: 1.5,
|
||
engine: Engine::Jet(-0.2, 1.5, 0.6),
|
||
decoy: false,
|
||
stealth: 1.3,
|
||
rcs: 0.15,
|
||
sound: (sound::DRONE_CRUISE, 1.2, 50),
|
||
class: Class::Cruise,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_PATRIOT,
|
||
};
|
||
|
||
const DRONE_SPEC_KH22: DroneSpec = DroneSpec {
|
||
name: "Х-22",
|
||
key: "kh22",
|
||
model: "airdef:kh22",
|
||
speed: 4.0,
|
||
turn: 0.03,
|
||
cruise: 140.0,
|
||
clearance: 40.0,
|
||
dive: 150.0,
|
||
warhead: 7,
|
||
scale: 1.8,
|
||
engine: Engine::Rocket(1.5, 1.3),
|
||
decoy: false,
|
||
stealth: 1.4,
|
||
rcs: 1.0,
|
||
sound: (sound::DRONE_ROCKET, 0.8, 46),
|
||
class: Class::Supersonic,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_PATRIOT,
|
||
};
|
||
|
||
const DRONE_SPEC_ZIRCON: DroneSpec = DroneSpec {
|
||
name: "Циркон",
|
||
key: "zircon",
|
||
model: "airdef:zircon",
|
||
speed: 5.5,
|
||
turn: 0.025,
|
||
cruise: 90.0,
|
||
clearance: 30.0,
|
||
dive: 110.0,
|
||
warhead: 6,
|
||
scale: 1.4,
|
||
engine: Engine::Rocket(1.5, 1.1),
|
||
decoy: false,
|
||
stealth: 2.0,
|
||
rcs: 0.4,
|
||
sound: (sound::DRONE_ROCKET, 1.35, 46),
|
||
class: Class::Supersonic,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_S400,
|
||
};
|
||
|
||
const DRONE_SPEC_ISKANDER: DroneSpec = DroneSpec {
|
||
name: "Искандер-М",
|
||
key: "iskander",
|
||
model: "airdef:iskander",
|
||
speed: 5.0,
|
||
turn: 0.04,
|
||
cruise: 0.0,
|
||
clearance: 0.0,
|
||
dive: 0.0,
|
||
warhead: 8,
|
||
scale: 1.8,
|
||
engine: Engine::Rocket(1.5, 1.6),
|
||
decoy: false,
|
||
stealth: 1.6,
|
||
rcs: 0.6,
|
||
sound: (sound::DRONE_ROCKET, 0.7, 46),
|
||
class: Class::Ballistic,
|
||
ballistic: Some(1000.0),
|
||
launch_sound: sound::LAUNCH_S500,
|
||
};
|
||
|
||
const DRONE_SPEC_KINZHAL: DroneSpec = DroneSpec {
|
||
name: "Кинжал",
|
||
key: "kinzhal",
|
||
model: "airdef:kinzhal",
|
||
speed: 7.5,
|
||
turn: 0.03,
|
||
cruise: 0.0,
|
||
clearance: 0.0,
|
||
dive: 0.0,
|
||
warhead: 8,
|
||
scale: 1.7,
|
||
engine: Engine::Rocket(1.5, 1.5),
|
||
decoy: false,
|
||
stealth: 2.2,
|
||
rcs: 0.5,
|
||
sound: (sound::DRONE_ROCKET, 0.6, 46),
|
||
class: Class::Ballistic,
|
||
ballistic: Some(1500.0),
|
||
launch_sound: sound::LAUNCH_S500,
|
||
};
|
||
|
||
const DRONE_SPEC_ORESHNIK: DroneSpec = DroneSpec {
|
||
name: "Орешник",
|
||
key: "oreshnik",
|
||
model: "airdef:iskander",
|
||
speed: 9.0,
|
||
turn: 0.0,
|
||
cruise: 0.0,
|
||
clearance: 0.0,
|
||
dive: 0.0,
|
||
warhead: 0,
|
||
scale: 2.6,
|
||
engine: Engine::Rocket(1.5, 2.4),
|
||
decoy: false,
|
||
stealth: 3.0,
|
||
rcs: 2.0,
|
||
sound: (sound::DRONE_ROCKET, 0.5, 46),
|
||
class: Class::Ballistic,
|
||
ballistic: Some(2600.0),
|
||
launch_sound: sound::LAUNCH_S500,
|
||
};
|
||
|
||
const DRONE_SPEC_ORESHNIKBLOCK: DroneSpec = DroneSpec {
|
||
name: "Орешник: блок",
|
||
key: "oreshnik_block",
|
||
model: "airdef:reentry",
|
||
speed: 9.0,
|
||
turn: 0.0,
|
||
cruise: 0.0,
|
||
clearance: 0.0,
|
||
dive: 0.0,
|
||
warhead: 4,
|
||
scale: 1.6,
|
||
engine: Engine::Rocket(1.0, 1.0),
|
||
decoy: false,
|
||
stealth: 3.5,
|
||
rcs: 0.4,
|
||
sound: (sound::DRONE_BALLISTIC, 0.8, 9999),
|
||
class: Class::Ballistic,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_S500,
|
||
};
|
||
|
||
const DRONE_SPEC_ORESHNIKSUB: DroneSpec = DroneSpec {
|
||
name: "Орешник: суббоеприпас",
|
||
key: "oreshnik_sub",
|
||
model: "airdef:reentry",
|
||
speed: 9.0,
|
||
turn: 0.05,
|
||
cruise: 0.0,
|
||
clearance: 0.0,
|
||
dive: 0.0,
|
||
warhead: 3,
|
||
scale: 1.1,
|
||
engine: Engine::Rocket(1.0, 1.0),
|
||
decoy: false,
|
||
stealth: 4.0,
|
||
rcs: 0.08,
|
||
sound: (sound::DRONE_BALLISTIC, 1.0, 9999),
|
||
class: Class::Ballistic,
|
||
ballistic: None,
|
||
launch_sound: sound::LAUNCH_S500,
|
||
};
|
||
|
||
const MISSILE_SPEC_PAC3: MissileSpec = MissileSpec {
|
||
model: "airdef:pac3",
|
||
speed: 5.5,
|
||
accel: 0.35,
|
||
turn: 0.3,
|
||
boost: 8,
|
||
cold: 0,
|
||
eject: 0.0,
|
||
eject_drag: 0.0,
|
||
pk: 0.9,
|
||
fuse: 4.0,
|
||
life: 240,
|
||
scale: 1.0,
|
||
flame: 1.0,
|
||
rear: 28.0,
|
||
seeker: 110.0,
|
||
launch_sound: sound::LAUNCH_PATRIOT,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 1.0),
|
||
};
|
||
|
||
const MISSILE_SPEC_M57E6: MissileSpec = MissileSpec {
|
||
model: "airdef:m57e6",
|
||
speed: 5.0,
|
||
accel: 0.5,
|
||
turn: 0.32,
|
||
boost: 5,
|
||
cold: 0,
|
||
eject: 0.0,
|
||
eject_drag: 0.0,
|
||
pk: 0.82,
|
||
fuse: 3.0,
|
||
life: 160,
|
||
scale: 0.85,
|
||
flame: 0.65,
|
||
rear: 28.0,
|
||
seeker: 0.0,
|
||
launch_sound: sound::LAUNCH_PANTSIR,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 1.12),
|
||
};
|
||
|
||
const MISSILE_SPEC_M48N6: MissileSpec = MissileSpec {
|
||
model: "airdef:m48n6",
|
||
speed: 7.0,
|
||
accel: 0.5,
|
||
turn: 0.22,
|
||
boost: 8,
|
||
cold: 20,
|
||
eject: 2.4,
|
||
eject_drag: 0.07,
|
||
pk: 0.9,
|
||
fuse: 5.0,
|
||
life: 300,
|
||
scale: 1.5,
|
||
flame: 1.4,
|
||
rear: 30.0,
|
||
seeker: 120.0,
|
||
launch_sound: sound::LAUNCH_S400_EJECT,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 0.88),
|
||
};
|
||
|
||
const MISSILE_SPEC_M77N6: MissileSpec = MissileSpec {
|
||
model: "airdef:m77n6",
|
||
speed: 9.0,
|
||
accel: 0.6,
|
||
turn: 0.22,
|
||
boost: 8,
|
||
cold: 24,
|
||
eject: 2.6,
|
||
eject_drag: 0.07,
|
||
pk: 0.95,
|
||
fuse: 6.0,
|
||
life: 320,
|
||
scale: 1.7,
|
||
flame: 1.6,
|
||
rear: 32.0,
|
||
seeker: 120.0,
|
||
launch_sound: sound::LAUNCH_S500_EJECT,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 0.8),
|
||
};
|
||
|
||
const MISSILE_SPEC_IRIST: MissileSpec = MissileSpec {
|
||
model: "airdef:irist_missile",
|
||
speed: 7.0,
|
||
accel: 0.5,
|
||
turn: 0.35,
|
||
boost: 6,
|
||
cold: 8,
|
||
eject: 1.8,
|
||
eject_drag: 0.1,
|
||
pk: 0.9,
|
||
fuse: 4.0,
|
||
life: 260,
|
||
scale: 0.95,
|
||
flame: 0.9,
|
||
rear: 28.0,
|
||
seeker: 90.0,
|
||
launch_sound: sound::LAUNCH_S400_EJECT,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 1.05),
|
||
};
|
||
|
||
const MISSILE_SPEC_AMRAAM: MissileSpec = MissileSpec {
|
||
model: "airdef:amraam_missile",
|
||
speed: 6.0,
|
||
accel: 0.45,
|
||
turn: 0.3,
|
||
boost: 6,
|
||
cold: 0,
|
||
eject: 0.0,
|
||
eject_drag: 0.0,
|
||
pk: 0.85,
|
||
fuse: 4.0,
|
||
life: 260,
|
||
scale: 0.9,
|
||
flame: 0.9,
|
||
rear: 28.0,
|
||
seeker: 130.0,
|
||
launch_sound: sound::LAUNCH_PATRIOT,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 1.05),
|
||
};
|
||
|
||
const MISSILE_SPEC_M9M317: MissileSpec = MissileSpec {
|
||
model: "airdef:m48n6",
|
||
speed: 6.5,
|
||
accel: 0.5,
|
||
turn: 0.25,
|
||
boost: 8,
|
||
cold: 0,
|
||
eject: 0.0,
|
||
eject_drag: 0.0,
|
||
pk: 0.85,
|
||
fuse: 5.0,
|
||
life: 300,
|
||
scale: 1.1,
|
||
flame: 1.2,
|
||
rear: 32.0,
|
||
seeker: 90.0,
|
||
launch_sound: sound::LAUNCH_PATRIOT,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 0.9),
|
||
};
|
||
|
||
const MISSILE_SPEC_M9M338: MissileSpec = MissileSpec {
|
||
model: "airdef:m57e6",
|
||
speed: 5.5,
|
||
accel: 0.6,
|
||
turn: 0.4,
|
||
boost: 4,
|
||
cold: 8,
|
||
eject: 1.6,
|
||
eject_drag: 0.1,
|
||
pk: 0.9,
|
||
fuse: 3.0,
|
||
life: 160,
|
||
scale: 1.0,
|
||
flame: 0.8,
|
||
rear: 28.0,
|
||
seeker: 70.0,
|
||
launch_sound: sound::LAUNCH_S400_EJECT,
|
||
voice: (sound::MISSILE_FLIGHT, 1.0, 1.15),
|
||
};
|
||
|
||
const MISSILE_SPEC_P1SUN: MissileSpec = MissileSpec {
|
||
model: "airdef:p1sun",
|
||
speed: 2.8,
|
||
accel: 0.12,
|
||
turn: 0.3,
|
||
boost: 4,
|
||
cold: 0,
|
||
eject: 0.0,
|
||
eject_drag: 0.0,
|
||
pk: 0.8,
|
||
fuse: 3.0,
|
||
life: 900,
|
||
scale: 0.8,
|
||
flame: 0.0,
|
||
rear: 10.0,
|
||
seeker: 60.0,
|
||
launch_sound: sound::DRONE_LANCET,
|
||
voice: (sound::DRONE_LANCET, 0.8, 1.6),
|
||
};
|
||
|
||
impl DroneKind {
|
||
/// Its row of numbers from `catalog/specs.json`.
|
||
pub fn spec(self) -> &'static DroneSpec {
|
||
match self {
|
||
DroneKind::Shahed => &DRONE_SPEC_SHAHED,
|
||
DroneKind::Geran3 => &DRONE_SPEC_GERAN3,
|
||
DroneKind::Lancet => &DRONE_SPEC_LANCET,
|
||
DroneKind::Gerbera => &DRONE_SPEC_GERBERA,
|
||
DroneKind::Kh101 => &DRONE_SPEC_KH101,
|
||
DroneKind::Kalibr => &DRONE_SPEC_KALIBR,
|
||
DroneKind::Kh22 => &DRONE_SPEC_KH22,
|
||
DroneKind::Zircon => &DRONE_SPEC_ZIRCON,
|
||
DroneKind::Iskander => &DRONE_SPEC_ISKANDER,
|
||
DroneKind::Kinzhal => &DRONE_SPEC_KINZHAL,
|
||
DroneKind::Oreshnik => &DRONE_SPEC_ORESHNIK,
|
||
DroneKind::OreshnikBlock => &DRONE_SPEC_ORESHNIKBLOCK,
|
||
DroneKind::OreshnikSub => &DRONE_SPEC_ORESHNIKSUB,
|
||
}
|
||
}
|
||
}
|
||
|
||
impl MissileKind {
|
||
fn spec(self) -> &'static MissileSpec {
|
||
match self {
|
||
MissileKind::Pac3 => &MISSILE_SPEC_PAC3,
|
||
MissileKind::M57e6 => &MISSILE_SPEC_M57E6,
|
||
MissileKind::M48n6 => &MISSILE_SPEC_M48N6,
|
||
MissileKind::M77n6 => &MISSILE_SPEC_M77N6,
|
||
MissileKind::IrisT => &MISSILE_SPEC_IRIST,
|
||
MissileKind::Amraam => &MISSILE_SPEC_AMRAAM,
|
||
MissileKind::M9m317 => &MISSILE_SPEC_M9M317,
|
||
MissileKind::M9m338 => &MISSILE_SPEC_M9M338,
|
||
MissileKind::P1sun => &MISSILE_SPEC_P1SUN,
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Save keys by kind; a rename needs an explicit migration.
|
||
#[cfg(test)]
|
||
pub(super) const DRONE_SPEC_KEYS: [(DroneKind, &str); 13] = [
|
||
(DroneKind::Shahed, "shahed"),
|
||
(DroneKind::Geran3, "geran3"),
|
||
(DroneKind::Lancet, "lancet"),
|
||
(DroneKind::Gerbera, "gerbera"),
|
||
(DroneKind::Kh101, "kh101"),
|
||
(DroneKind::Kalibr, "kalibr"),
|
||
(DroneKind::Kh22, "kh22"),
|
||
(DroneKind::Zircon, "zircon"),
|
||
(DroneKind::Iskander, "iskander"),
|
||
(DroneKind::Kinzhal, "kinzhal"),
|
||
(DroneKind::Oreshnik, "oreshnik"),
|
||
(DroneKind::OreshnikBlock, "oreshnik_block"),
|
||
(DroneKind::OreshnikSub, "oreshnik_sub"),
|
||
];
|
||
|
||
#[cfg(test)]
|
||
pub(super) const MISSILE_SPEC_MODELS: [(MissileKind, &str); 9] = [
|
||
(MissileKind::Pac3, "airdef:pac3"),
|
||
(MissileKind::M57e6, "airdef:m57e6"),
|
||
(MissileKind::M48n6, "airdef:m48n6"),
|
||
(MissileKind::M77n6, "airdef:m77n6"),
|
||
(MissileKind::IrisT, "airdef:irist_missile"),
|
||
(MissileKind::Amraam, "airdef:amraam_missile"),
|
||
(MissileKind::M9m317, "airdef:m48n6"),
|
||
(MissileKind::M9m338, "airdef:m57e6"),
|
||
(MissileKind::P1sun, "airdef:p1sun"),
|
||
];
|