use std::num::NonZeroU32; use galactica_content::SystemObjectHandle; use rapier2d::math::Isometry; /// A ship autopilot. /// An autopilot is a lightweight ShipController that /// temporarily has control over a ship. #[derive(Debug, Clone)] pub enum ShipAutoPilot { /// No autopilot, use usual behavior. None, /// Automatically arrange for landing on the given object Landing { /// The body we want to land on target: SystemObjectHandle, }, } /// Ship state machine. /// Any ship we keep track of is in one of these states. /// Dead ships don't exist---they removed once their collapse /// sequence fully plays out. #[derive(Debug, Clone)] pub enum ShipState { /// This ship is dead, and should be removed from the game. Dead, /// This ship is alive and well in open space Flying { /// The autopilot we're using. /// Overrides ship controller. autopilot: ShipAutoPilot, }, /// This ship has been destroyed, and is playing its collapse sequence. Collapsing, /// This ship is landed on a planet Landed { /// The planet this ship is landed on target: SystemObjectHandle, }, /// This ship is landing on a planet /// (playing the animation) Landing { /// The planet we're landing on target: SystemObjectHandle, /// Our current z-coordinate current_z: f32, }, /// This ship is taking off from a planet /// (playing the animation) UnLanding { /// The point to which we're going, in world coordinates to_position: Isometry, /// The planet we're taking off from from: SystemObjectHandle, /// Our current z-coordinate current_z: f32, }, } impl ShipState { /// What planet is this ship landed on? pub fn landed_on(&self) -> Option { match self { Self::Landed { target } => Some(*target), _ => None, } } /// An integer representing each state. /// Makes detecting state changes cheap and easy. pub fn as_int(&self) -> NonZeroU32 { NonZeroU32::new(match self { Self::Dead => 1, Self::Collapsing => 2, Self::Flying { .. } => 3, Self::Landed { .. } => 4, Self::Landing { .. } => 5, Self::UnLanding { .. } => 6, }) .unwrap() } /// Is this state Dead? pub fn is_dead(&self) -> bool { match self { Self::Dead => true, _ => false, } } /// Is this state Collapsing? pub fn is_collapsing(&self) -> bool { match self { Self::Collapsing => true, _ => false, } } /// Is this state Flying? pub fn is_flying(&self) -> bool { match self { Self::Flying { .. } => true, _ => false, } } /// Is this state Landed? pub fn is_landed(&self) -> bool { match self { Self::Landed { .. } => true, _ => false, } } /// Is this state Landing? pub fn is_landing(&self) -> bool { match self { Self::Landing { .. } => true, _ => false, } } /// Is this state UnLanding? pub fn is_unlanding(&self) -> bool { match self { Self::UnLanding { .. } => true, _ => false, } } }