use shrev::{EventChannel, ReaderId}; use space_crush_common::{ components::{Fleet, FleetOwned, Orbit, Player, Position, Ship, ShipType}, continue_if_none, misc::WorldHelper, }; use specs::{prelude::*, Entity, ReadStorage, System, World, WriteStorage}; use crate::{ misc::MouseEvent, resources::{Camera, Config, InputState, PlayerState}, Error, }; pub struct FleetControl { mouse_event_id: ReaderId, target_fleet: Option, } #[derive(SystemData)] pub struct FleetControlData<'a> { player_state: WriteExpect<'a, PlayerState>, mouse_events: ReadExpect<'a, EventChannel>, input_state: ReadExpect<'a, InputState>, camera: ReadExpect<'a, Camera>, config: ReadExpect<'a, Config>, ships: ReadStorage<'a, Ship>, fleet_owned: WriteStorage<'a, FleetOwned>, positions: ReadStorage<'a, Position>, players: ReadStorage<'a, Player>, orbits: ReadStorage<'a, Orbit>, fleets: ReadStorage<'a, Fleet>, } impl FleetControl { pub fn new(world: &mut World) -> Result { let mouse_event_id = world.register_event_reader::()?; let target_fleet = None; Ok(Self { mouse_event_id, target_fleet, }) } } impl<'a> System<'a> for FleetControl { type SystemData = FleetControlData<'a>; fn run(&mut self, data: Self::SystemData) { let FleetControlData { mut player_state, mouse_events, input_state, camera, config, ships, mut fleet_owned, positions, players, orbits, fleets, } = data; let events = mouse_events.read(&mut self.mouse_event_id); for event in events { match event { MouseEvent::ButtonDown(button) if button == &config.input.fleet_move_button => { let pos = camera.view_to_world(input_state.mouse_pos); for (position, orbit) in (&positions, &orbits).join() { let r = orbit.max * orbit.max; if (position.pos - pos).length_sqr() <= r { let player_id = player_state.player_id; let player = continue_if_none!(players.get(player_id)); let fleet_id = continue_if_none!(orbit.fleets.get(player.index)); let fleet_id = *continue_if_none!(fleet_id); self.target_fleet = Some(fleet_id); break; } } } MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => { let selection = player_state.selection.take(); let target_fleet = continue_if_none!(self.target_fleet.take()); let mut selection = continue_if_none!(selection); let fleet = continue_if_none!(fleets.get(selection.fleet)); for (ship, fleet_owned, _) in (&ships, &mut fleet_owned, &fleet.owned).join() { match &ship.type_ { ShipType::Fighter if selection.count.fighter > 0 => { fleet_owned.owner = target_fleet; selection.count.fighter -= 1; } ShipType::Bomber if selection.count.bomber > 0 => { fleet_owned.owner = target_fleet; selection.count.bomber -= 1; } ShipType::Transporter if selection.count.transporter > 0 => { fleet_owned.owner = target_fleet; selection.count.transporter -= 1; } _ => (), } } } MouseEvent::Move(_, _) => { self.target_fleet = None; } _ => (), } } } }