use shrev::{EventChannel, ReaderId}; use space_crush_common::{ components::{Fleet, FleetOwned, Position, Ship, ShipType}, misc::WorldHelper, return_if_none, }; use specs::{prelude::*, Entities, Entity, ReadStorage, System, World, WriteStorage}; use crate::{ components::FleetInfo, 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>, entities: Entities<'a>, ships: ReadStorage<'a, Ship>, fleet_owned: WriteStorage<'a, FleetOwned>, positions: ReadStorage<'a, Position>, fleet_infos: ReadStorage<'a, FleetInfo>, 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, entities, ships, mut fleet_owned, positions, fleet_infos, 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 (id, position, fleet) in (&entities, &positions, &fleets).join() { let r = fleet.orbit_max * fleet.orbit_max; if (position.pos - pos).length_sqr() <= r { self.target_fleet = Some(id); break; } } } MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => { let selection = player_state.selection.take(); let target_fleet = return_if_none!(self.target_fleet.take()); let mut selection = return_if_none!(selection); let fleet_info = return_if_none!(fleet_infos.get(selection.fleet)); for (ship, fleet_owned, _) in (&ships, &mut fleet_owned, &fleet_info.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; } _ => (), } } } }