diff --git a/src/charges.rs b/src/charges.rs index feaf1d1..8bde7d5 100644 --- a/src/charges.rs +++ b/src/charges.rs @@ -2,7 +2,10 @@ //! Actions may only be used if at least one charge is available. //! Unlike pools, charges are not shared across abilities. -use bevy::ecs::prelude::{Component, Resource}; +use bevy::{ + ecs::prelude::{Component, Resource}, + reflect::Reflect, +}; use std::marker::PhantomData; use crate::{Abilitylike, CannotUseAbility}; @@ -80,10 +83,11 @@ use std::collections::HashMap; /// Action::Spell.trigger(&mut abilities_bundle.charges, &mut abilities_bundle.cooldowns, Some(&mut mana_bundle.pool), Some(&mut mana_bundle.ability_costs)); /// } /// ``` -#[derive(Resource, Component, Clone, PartialEq, Eq, Debug)] +#[derive(Resource, Component, Clone, PartialEq, Eq, Debug, Reflect)] pub struct ChargeState { /// The underlying [`Charges`]. charges_map: HashMap, + #[reflect(ignore)] _phantom: PhantomData, } @@ -100,7 +104,7 @@ impl Default for ChargeState { /// /// Charges refresh when [`Charges::refresh`] is called manually, /// or when the corresponding cooldown expires (if the [`InputManagerPlugin`](crate::plugin::InputManagerPlugin) is added). -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Reflect)] pub struct Charges { current: u8, max: u8, @@ -111,7 +115,7 @@ pub struct Charges { } /// What happens when [`Charges`] are replenished? -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect)] pub enum ReplenishStrategy { /// A single charge will be recovered. /// @@ -124,7 +128,7 @@ pub enum ReplenishStrategy { } /// How do these charges replenish when cooldowns are refreshed? -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect)] pub enum CooldownStrategy { /// Cooldowns refresh will have no effect on the charges. Ignore, diff --git a/src/cooldown.rs b/src/cooldown.rs index fc22e72..fb8d8f7 100644 --- a/src/cooldown.rs +++ b/src/cooldown.rs @@ -5,8 +5,11 @@ use crate::{ Abilitylike, CannotUseAbility, }; -use bevy::ecs::prelude::{Component, Resource}; use bevy::utils::Duration; +use bevy::{ + ecs::prelude::{Component, Resource}, + reflect::Reflect, +}; use serde::{Deserialize, Serialize}; use std::{collections::HashMap, marker::PhantomData}; @@ -49,7 +52,7 @@ use std::{collections::HashMap, marker::PhantomData}; /// // We just jumped, so the cooldown isn't ready yet /// assert_eq!(cooldowns.ready(Action::Jump), Err(CannotUseAbility::OnCooldown)); /// ``` -#[derive(Resource, Component, Debug, Clone, PartialEq, Eq)] +#[derive(Resource, Component, Debug, Clone, PartialEq, Eq, Reflect)] pub struct CooldownState { /// The [`Cooldown`] of each action /// @@ -61,6 +64,7 @@ pub struct CooldownState { /// Whenever any cooldown for an action of type `A` is triggered, /// this global cooldown is triggered. pub global_cooldown: Option, + #[reflect(ignore)] _phantom: PhantomData, } @@ -251,7 +255,7 @@ impl CooldownState { /// cooldown.refresh(); /// assert!(cooldown.ready().is_ok()); /// ``` -#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Reflect)] pub struct Cooldown { max_time: Duration, /// The amount of time that has elapsed since all [`Charges`](crate::charges::Charges) were fully replenished. diff --git a/src/lib.rs b/src/lib.rs index c2aadf5..a01fa6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,7 +4,7 @@ #![doc = include_str!("../README.md")] use crate::cooldown::CooldownState; -use bevy::ecs::prelude::*; +use bevy::{ecs::prelude::*, reflect::Reflect}; use charges::{ChargeState, Charges}; use cooldown::Cooldown; use leafwing_input_manager::Actionlike; @@ -219,7 +219,7 @@ pub fn trigger_ability( /// If you would like to track resource costs for your abilities, combine this with a [`PoolBundle`](crate::pool::PoolBundle). /// /// Use with [`AbilityPlugin`](crate::plugin::AbilityPlugin), providing the same enum type to both. -#[derive(Bundle, Clone, Debug, PartialEq, Eq)] +#[derive(Bundle, Clone, Debug, PartialEq, Eq, Reflect)] pub struct AbilitiesBundle { /// A [`CooldownState`] component pub cooldowns: CooldownState, diff --git a/src/plugin.rs b/src/plugin.rs index 24bd30d..07e16af 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,6 +1,6 @@ //! Contains main plugin exported by this crate. -use crate::Abilitylike; +use crate::{AbilitiesBundle, Abilitylike}; use bevy::ecs::prelude::*; use core::marker::PhantomData; @@ -65,6 +65,9 @@ impl Plugin for AbilityPlugin { .before(InputManagerSystem::Update), ); + // Type registration + app.register_type::>(); + // Resources app.init_resource::>(); } diff --git a/src/pool.rs b/src/pool.rs index 443b2d2..93704fa 100644 --- a/src/pool.rs +++ b/src/pool.rs @@ -6,9 +6,11 @@ //! Pools have a maximum value and a minimum value (almost always zero), can regenerate over time, and can be spent to pay for abilities. //! //! The [`regenerate_resource_pool`](crate::systems::regenerate_resource_pool) system will regenerate resource pools of a given type if manually added. +//! +//! Remember to manually register these types for reflection with [`App::register_type`](bevy::app::App::register_type) if you wish to serialize or inspect them. -use bevy::ecs::prelude::*; use bevy::utils::Duration; +use bevy::{ecs::prelude::*, reflect::Reflect}; use core::ops::{Add, AddAssign, Div, Mul, Sub, SubAssign}; use std::{collections::HashMap, marker::PhantomData}; use thiserror::Error; @@ -146,7 +148,7 @@ pub trait RegeneratingPool: Pool { pub struct MaxPoolLessThanMin; /// Stores the cost (in terms of the [`Pool::Quantity`] of ability) associated with each ability of type `A`. -#[derive(Component, Debug)] +#[derive(Component, Resource, Debug, Reflect)] pub struct AbilityCosts { /// The underlying cost of each ability. cost_map: HashMap, @@ -270,12 +272,15 @@ impl AbilityCosts { /// as you want the other functionality of pools (current, max, regen, depletion) /// but often cannot spend it on abilities. /// -/// # Important Note +/// # Usage /// /// Note that resource pools are not controlled by [`AbilityPlugin`](crate::plugin::AbilityPlugin). /// If you want regeneration to occur automatically, add [`regenerate_resource_pool`](crate::systems::regenerate_resource_pool) /// to your schedule. -#[derive(Bundle)] +/// +/// These types are not automatically registered by [`AbilityPlugin`](crate::plugin::AbilityPlugin). +/// You must register them manually with [`App::register_type`](bevy::app::App::register_type) if you wish to serialize or inspect them. +#[derive(Bundle, Reflect)] pub struct PoolBundle { /// The resource pool used to pay for abilities pub pool: P, diff --git a/src/premade_pools.rs b/src/premade_pools.rs index 08a954f..4ce4d9d 100644 --- a/src/premade_pools.rs +++ b/src/premade_pools.rs @@ -11,6 +11,8 @@ use derive_more::{Add, AddAssign, Sub, SubAssign}; /// A premade resource pool for life (aka health, hit points or HP). pub mod life { + use bevy::reflect::Reflect; + use crate::pool::RegeneratingPool; use super::*; @@ -19,7 +21,7 @@ pub mod life { /// If they lose it all, they die or pass out. /// /// This is intended to be stored as a component on each entity. - #[derive(Debug, Clone, PartialEq, Component, Resource)] + #[derive(Debug, Clone, PartialEq, Component, Resource, Reflect)] pub struct LifePool { /// The current life. current: Life, @@ -52,7 +54,7 @@ pub mod life { /// /// This can be used for damage computations, life regeneration, healing and so on. #[derive( - Debug, Clone, Copy, PartialEq, PartialOrd, Default, Add, Sub, AddAssign, SubAssign, + Debug, Clone, Copy, PartialEq, PartialOrd, Default, Add, Sub, AddAssign, SubAssign, Reflect, )] pub struct Life(pub f32); @@ -172,6 +174,8 @@ pub mod life { /// A premade resource pool for mana (aka MP). pub mod mana { + use bevy::reflect::Reflect; + use crate::pool::RegeneratingPool; use super::*; @@ -180,7 +184,7 @@ pub mod mana { /// Units must spend mana to cast spells according to their [`AbilityCosts`](crate::pool::AbilityCosts) component. /// /// This is intended to be stored as a component on each entity. - #[derive(Debug, Clone, PartialEq, Component, Resource)] + #[derive(Debug, Clone, PartialEq, Component, Resource, Reflect)] pub struct ManaPool { /// The current mana. current: Mana, @@ -212,7 +216,7 @@ pub mod mana { /// /// This can be used for ability costs, mana regeneration and so on. #[derive( - Debug, Clone, Copy, PartialEq, PartialOrd, Default, Add, Sub, AddAssign, SubAssign, + Debug, Clone, Copy, PartialEq, PartialOrd, Default, Add, Sub, AddAssign, SubAssign, Reflect, )] pub struct Mana(pub f32);