use anyhow::Result; use cgmath::{Vector2, Zero}; use engine::prelude::*; use paste; use std::{ slice::{Iter, IterMut}, str::FromStr, }; use crate::config::save_game::SaveGame; use crate::items::{ability_addon::AbilityAddonTypes, ability_book::AbilityBook, Rarities}; use crate::{components::inventory::Storable, items::ItemSystem}; macro_rules! load { ($me: ident, $item_system:ident, $save_game:ident, $($index:literal,)+) => { paste::expr! { $( if $save_game.[].used { let ability = &$save_game.[]; let mut addons = Vec::new(); for addon in ability.addons.iter() { let mut split = addon.split('|'); let rarity = Rarities::from_str(&split.nth(0).unwrap())?; let addon_type = AbilityAddonTypes::from_str(&split.nth(0).unwrap())?; addons.push(Some($item_system.addon(rarity, addon_type))); } let book = $item_system.ability_book( &ability.name, ability.rarity, addons, ability.level, ); $me.abilities[$index] = Some(book); } )+ } }; } macro_rules! store { ($me: ident, $save_game:ident, $($index:literal,)+) => { paste::expr! { $( if let Some(book) = &$me.abilities[$index] { let ability = &mut $save_game.[]; ability.used = true; ability.name = book.ability().name().to_string(); ability.rarity = book.rarity(); ability.level = book.level(); for addon in book.addons().iter() { if let Some(addon) = addon { ability.addons.push(format!("{}|{}", addon.rarity(), addon.addon_type())); } } } )+ } }; } pub struct AbilitySlots { pub direction: Vector2, abilities: [Option; AbilitySlots::MAX_ABILITIES], } impl AbilitySlots { // stupid workaround for serde Deserialize pub const MAX_ABILITIES: usize = 4; pub fn empty() -> Self { Self { direction: Vector2::zero(), abilities: Default::default(), } } pub fn load(item_system: &ItemSystem, save_game: &SaveGame) -> Result { let mut me = Self::empty(); load!(me, item_system, save_game, 0, 1, 2, 3,); Ok(me) } pub fn store(&self, save_game: &mut SaveGame) { store!(self, save_game, 0, 1, 2, 3,); } pub fn insert_book(&mut self, book: AbilityBook, index: usize) -> Option { match self.abilities[index].clone() { Some(ability) => { if ability != book { self.abilities[index] = Some(book); } else { self.abilities[index] = Some(book); } Some(ability) } None => { self.abilities[index] = Some(book); None } } } // pub fn clear_book(&mut self, index: usize) { // self.abilities[index] = None; // } pub fn book(&self, index: usize) -> Option<&AbilityBook> { self.abilities[index].as_ref() } pub fn book_mut(&mut self, index: usize) -> Option<&mut AbilityBook> { self.abilities[index].as_mut() } pub fn iter(&self) -> Iter<'_, Option> { self.abilities.iter() } pub fn iter_mut(&mut self) -> IterMut<'_, Option> { self.abilities.iter_mut() } } impl EntityComponent for AbilitySlots { fn name(&self) -> &str { Self::debug_name() } } impl ComponentDebug for AbilitySlots { fn debug_name() -> &'static str { "AbilitySlots" } }