diff --git a/src/game/card.rs b/src/game/card.rs index a601cf2..01699c6 100644 --- a/src/game/card.rs +++ b/src/game/card.rs @@ -168,7 +168,6 @@ impl EntityCommand for CardIcon { } } -// TODO: `min_level` field before the card can be offered in the level up menu. #[derive(Reflect, Serialize, Deserialize, Clone)] pub struct Card { pub name: String, @@ -177,6 +176,15 @@ pub struct Card { pub background_key: String, #[serde(rename = "icon")] pub icon_key: String, + /// The earliest level this card will be offered in the level up menu. + #[serde(default)] + pub min_level: usize, + /// The latest level this card will be offered in the level up menu. + #[serde(default = "inf")] + pub max_level: usize, + /// The relative probability of this card being offered in the level up menu. + #[serde(default = "one")] + pub weight: f64, #[serde(rename = "play_sfx", default)] play_sfx_path: String, @@ -195,6 +203,10 @@ fn one() -> f64 { 1.0 } +fn inf() -> usize { + usize::MAX +} + pub fn card(key: impl Into, active: Option) -> impl EntityCommand { let key = key.into(); diff --git a/src/screen/playing/level_up_menu.rs b/src/screen/playing/level_up_menu.rs index 7923d85..62e9579 100644 --- a/src/screen/playing/level_up_menu.rs +++ b/src/screen/playing/level_up_menu.rs @@ -7,11 +7,12 @@ use leafwing_input_manager::common_conditions::action_just_pressed; use leafwing_input_manager::prelude::*; use pyri_state::extra::entity_scope::StateScope; use pyri_state::prelude::*; -use rand::seq::IteratorRandom as _; +use rand::prelude::*; use crate::core::pause::Pause; use crate::core::UpdateSet; use crate::game::actor::level::up::LevelUp; +use crate::game::actor::level::Level; use crate::game::card::card; use crate::game::card::deck::Deck; use crate::game::card::deck::IsDeckDisplay; @@ -183,16 +184,26 @@ fn instructions_container(mut entity: EntityWorldMut) { } fn card_options_container(entity: Entity, world: &mut World) { - let config = SystemState::>::new(world).get(world); + let mut system_state = SystemState::<( + ConfigRef, + Query<&Selection, With>, + Query<&Level>, + )>::new(world); + let (config, selection_query, level_query) = system_state.get(world); let config = r!(config.get()); - // TODO: Pick cards options from a card pool based on level. - let card_keys = config + let selection = r!(selection_query.get_single()); + let level = r!(level_query.get(selection.0)); + let level = level.current; + let card_pool = config .card_map - .keys() - .choose_multiple(&mut rand::thread_rng(), 3) - .into_iter() - .cloned() + .iter() + .filter(|(_, card)| card.min_level <= level && level <= card.max_level) .collect::>(); + let card_keys = + r!(card_pool.choose_multiple_weighted(&mut rand::thread_rng(), 3, |(_, card)| card.weight)) + .into_iter() + .map(|(key, _)| (*key).clone()) + .collect::>(); world .entity_mut(entity)