use shrev::{EventChannel, ReaderId}; use space_crush_common::{ components::{MeetingPoint, Position}, continue_if_none, misc::WorldHelper, systems::FleetControlEvent, }; use specs::{prelude::*, Entities, Entity, ReadStorage, System, World}; use crate::{ misc::MouseEvent, resources::{Camera, Config, GameState, InputState, Selection}, Error, }; pub struct FleetMove { mouse_event_id: ReaderId, target_meeting_point: Option, } #[derive(SystemData)] pub struct FleetMoveData<'a> { game_state: WriteExpect<'a, GameState>, fleet_control: WriteExpect<'a, EventChannel>, mouse_events: ReadExpect<'a, EventChannel>, input_state: ReadExpect<'a, InputState>, camera: ReadExpect<'a, Camera>, config: ReadExpect<'a, Config>, entities: Entities<'a>, positions: ReadStorage<'a, Position>, meeting_points: ReadStorage<'a, MeetingPoint>, } impl FleetMove { pub fn new(world: &mut World) -> Result { let mouse_event_id = world.register_event_reader::()?; let target_meeting_point = None; Ok(Self { mouse_event_id, target_meeting_point, }) } } impl<'a> System<'a> for FleetMove { type SystemData = FleetMoveData<'a>; fn run(&mut self, data: Self::SystemData) { let FleetMoveData { mut game_state, mut fleet_control, mouse_events, input_state, camera, config, entities, positions, meeting_points, } = 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, meeting_point) in (&entities, &positions, &meeting_points).join() { let r = meeting_point.max() * meeting_point.max(); if (position.get() - pos).length_sqr() <= r { self.target_meeting_point = Some(id); break; } } } MouseEvent::ButtonUp(button) if button == &config.input.fleet_move_button => { let selection = game_state.selection_mut().take(); let selection = continue_if_none!(selection); let Selection { fleet, count } = selection; let target = continue_if_none!(self.target_meeting_point); let player = game_state.player_id(); let event = FleetControlEvent::MoveToMeetingPoint { player, fleet, count, target, }; fleet_control.single_write(event); } MouseEvent::Move(_, _) => { self.target_meeting_point = None; } _ => (), } } } }