Initial Commit
This commit is contained in:
158
src/main.rs
Normal file
158
src/main.rs
Normal file
@@ -0,0 +1,158 @@
|
||||
use bevy::{
|
||||
app::{App, Update},
|
||||
ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
query::{Added, With, Without},
|
||||
system::{Commands, Query},
|
||||
},
|
||||
};
|
||||
use guardian_core::*;
|
||||
use tokio::runtime::Handle;
|
||||
|
||||
// Every incomming (voice) message is an event
|
||||
// Systems can handle the events, eg bogey dope, set tripwire or radio check
|
||||
// voice responses; srs should be a resource?
|
||||
// |- srs plugin adds a resource to use to send messages i guess
|
||||
// |-- or spawn an entity with a message commands.spawn((VoiceMessage("Hello World"), TextMessage("Hello World!")))
|
||||
// |-- srs plugin will check if these components are Added<VoiceMessage> or w/e and handle accordingly
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
App::new()
|
||||
.insert_resource(TokioResource(Handle::current()))
|
||||
.add_plugins(DefaultPlugins)
|
||||
.add_systems(Update, (add_tripwire, tripwire))
|
||||
.run();
|
||||
}
|
||||
|
||||
// this will be on a tripwire command event (from srs), instead of Added<Player>, not everyone may want it; opt-in over opt-out
|
||||
fn add_tripwire(mut commands: Commands, players: Query<Entity, Added<Player>>) {
|
||||
for ent in players.iter() {
|
||||
commands.entity(ent).insert(Tripwire {
|
||||
range: 30.0,
|
||||
reported: vec![],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn tripwire(
|
||||
mut commands: Commands,
|
||||
mut players: Query<(&Id, &Callsign, &Position, &mut Tripwire), With<Player>>,
|
||||
npc: Query<(&Id, &Position, &Heading, &Side), Without<Player>>,
|
||||
) {
|
||||
for (p_id, p_callsign, p_position, mut p_tripwire) in players.iter_mut() {
|
||||
let _p_id = &p_id.0;
|
||||
let _p_callsign = &p_callsign.0;
|
||||
for (n_id, n_position, n_heading, side) in npc.iter() {
|
||||
if side.0 != Coalition::Red {
|
||||
continue;
|
||||
}
|
||||
|
||||
let n_id = &n_id.0;
|
||||
|
||||
let distance = n_position.distance_to_nmi(p_position);
|
||||
if distance <= p_tripwire.range && !p_tripwire.reported.contains(n_id) {
|
||||
p_tripwire.reported.push(*n_id);
|
||||
|
||||
let bra = Braa::new(p_position, n_position, n_heading);
|
||||
commands.spawn(TextMessage::new(bra.to_text()));
|
||||
} else if distance > p_tripwire.range && p_tripwire.reported.contains(n_id) {
|
||||
p_tripwire.reported.retain(|b| b != n_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
struct Tripwire {
|
||||
range: f64,
|
||||
reported: Vec<u32>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Aspect {
|
||||
Hot,
|
||||
Flank,
|
||||
Cold,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Aspect {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Hot => write!(f, "Hot"),
|
||||
Self::Flank => write!(f, "Flank"),
|
||||
Self::Cold => write!(f, "Cold"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Braa {
|
||||
bearing: i32,
|
||||
range: i32,
|
||||
angels: i32,
|
||||
aspect: Aspect,
|
||||
}
|
||||
|
||||
impl Braa {
|
||||
pub fn new(unit_a: &Position, unit_b: &Position, heading_b: &Heading) -> Self {
|
||||
let bearing = unit_a.get_bearing_to(unit_b);
|
||||
let range = unit_a.distance_to_nmi(unit_b).round() as i32;
|
||||
let angels = unit_b.angels();
|
||||
let aspect = {
|
||||
let bearing = unit_b.get_bearing_to(unit_a);
|
||||
let angle = (bearing - heading_b.0 as i32) % 360;
|
||||
if (45..135).contains(&angle) {
|
||||
Aspect::Flank
|
||||
} else if (135..225).contains(&angle) {
|
||||
Aspect::Cold
|
||||
} else if (225..315).contains(&angle) {
|
||||
Aspect::Flank
|
||||
} else if !(45..=315).contains(&angle) {
|
||||
Aspect::Hot
|
||||
} else {
|
||||
Aspect::Cold
|
||||
}
|
||||
};
|
||||
|
||||
Self {
|
||||
bearing,
|
||||
range,
|
||||
angels,
|
||||
aspect,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_text(&self) -> String {
|
||||
format!(
|
||||
"BRA {}° for {}NM at {} thousand {}",
|
||||
self.bearing, self.range, self.angels, self.aspect
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_voice(&self) -> String {
|
||||
let bearing = split(&self.bearing.to_string(), 1);
|
||||
let range = split(&self.range.to_string(), 1);
|
||||
format!(
|
||||
"BRA <break time=\"250ms\"/> {} <break /> {} <break /> {} thousand <break /> {}",
|
||||
bearing, range, self.angels, self.aspect
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn split(input: &str, n: usize) -> String {
|
||||
input
|
||||
.chars()
|
||||
.enumerate()
|
||||
.flat_map(|(i, c)| {
|
||||
if i != 0 && i % n == 0 {
|
||||
Some(' ')
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.into_iter()
|
||||
.chain(std::iter::once(c))
|
||||
})
|
||||
.collect::<String>()
|
||||
}
|
||||
Reference in New Issue
Block a user