use skill::{Skill, Effect, Colour}; use spec::{Spec}; use cryp::{Colours}; #[derive(Debug,Copy,Clone,Serialize,Deserialize,PartialEq,PartialOrd,Ord,Eq)] pub enum Item { // colours Blue, Green, Red, // base skills Attack, Block, Stun, Buff, Debuff, // specs // Base Damage, Life, Speed, // Lifes Upgrades GreenLifeI, RedLifeI, BlueLifeI, GRLI, GBLI, RBLI, // Damage Upgrades RedDamageI, BlueDamageI, GreenDamageI, GRDI, GBDI, RBDI, // Speed Upgrades RedSpeedI, BlueSpeedI, GreenSpeedI, GRSpeedI, GBSpeedI, RBSpeedI, Amplify, Banish, Blast, Chaos, Clutch, Corrupt, Curse, Decay, Hostility, Haste, Heal, Hex, Impurity, Invert, Parry, Purge, Purify, Reflect, Recharge, Ruin, Scatter, Silence, Slay, Sleep, Snare, Strangle, Strike, StrikeII, StrikeIII, Siphon, Taunt, Throw, Triage, TestTouch, TestStun, TestBlock, TestParry, TestSiphon, } pub enum ItemEffect { Skill, Spec, } impl Item { pub fn colours(&self, count: &mut Colours) { let combos = get_combos(); let combo = combos.iter().find(|c| c.item == *self); match combo { Some(c) => c.components.iter().for_each(|unit| match unit { Item::Red => count.red += 1, Item::Blue => count.blue += 1, Item::Green => count.green += 1, _ => { let mut combo_count = Colours::new(); unit.colours(&mut combo_count); count.red += combo_count.red; count.blue += combo_count.blue; count.green += combo_count.green; } }), None => (), } } pub fn components(&self) -> Vec { let combos = get_combos(); let combo = combos.iter().find(|c| c.item == *self); match combo { Some(c) => c.components.iter().flat_map(|c| c.components()).collect::>(), None => vec![*self], } } pub fn cost(&self) -> u16 { match self { Item::Red => 1, Item::Green => 1, Item::Blue => 1, Item::Attack => 2, Item::Block => 2, Item::Buff => 2, Item::Debuff => 2, Item::Stun => 2, Item::Damage => 3, Item::Life => 3, Item::Speed => 3, _ => { let combos = get_combos(); let combo = combos.iter().find(|c| c.item == *self) .unwrap_or_else(|| panic!("unable to find components for {:?}", self)); return combo.components.iter().fold(0, |acc, c| acc + c.cost()); }, } } pub fn speed(&self) -> u8 { match self { Item::Red => 3, Item::Green => 2, Item::Blue => 1, Item::Attack => 1, Item::Stun => 2, Item::Block => 3, Item::Buff => 4, Item::Debuff => 4, _ => { let combos = get_combos(); let combo = combos.iter().find(|c| c.item == *self) .unwrap_or_else(|| panic!("unable to find components for {:?}", self)); return combo.components.iter().fold(0, |acc, c| acc + c.speed()); }, } } pub fn effect(&self) -> Option { if let Some(_skill) = self.into_skill() { return Some(ItemEffect::Skill); } if let Some(_spec) = self.into_spec() { return Some(ItemEffect::Spec); } return None; } pub fn into_skill(&self) -> Option { match self { Item::Attack => Some(Skill::Attack), Item::Amplify => Some(Skill::Amplify), Item::Banish => Some(Skill::Banish), Item::Blast => Some(Skill::Blast), Item::Block => Some(Skill::Block), Item::Buff => Some(Skill::Buff), Item::Chaos => Some(Skill::Chaos), Item::Curse => Some(Skill::Curse), Item::Debuff => Some(Skill::Debuff), Item::Decay => Some(Skill::Decay), Item::Haste => Some(Skill::Haste), Item::Heal => Some(Skill::Heal), Item::Hex => Some(Skill::Hex), Item::Hostility => Some(Skill::Hostility), Item::Impurity => Some(Skill::Impurity), Item::Invert => Some(Skill::Invert), Item::Parry => Some(Skill::Parry), Item::Purge => Some(Skill::Purge), Item::Purify => Some(Skill::Purify), Item::Recharge => Some(Skill::Recharge), Item::Reflect => Some(Skill::Reflect), Item::Ruin => Some(Skill::Ruin), Item::Scatter => Some(Skill::Scatter), Item::Silence => Some(Skill::Silence), Item::Slay => Some(Skill::Slay), Item::Sleep => Some(Skill::Sleep), Item::Siphon => Some(Skill::Siphon), Item::Snare => Some(Skill::Snare), Item::Strangle => Some(Skill::Strangle), Item::Stun => Some(Skill::Stun), Item::Strike => Some(Skill::Strike), Item::StrikeII => Some(Skill::StrikeII), Item::StrikeIII => Some(Skill::StrikeIII), Item::Clutch => Some(Skill::Clutch), Item::Taunt => Some(Skill::Taunt), Item::Throw => Some(Skill::Throw), Item::Corrupt => Some(Skill::Corrupt), Item::Triage => Some(Skill::Triage), _ => None, } } pub fn into_spec(&self) -> Option { match *self { Item::Speed => Some(Spec::Speed), Item::RedSpeedI => Some(Spec::RedSpeedI), Item::BlueSpeedI => Some(Spec::BlueSpeedI), Item::GreenSpeedI => Some(Spec::GreenSpeedI), Item::GRSpeedI => Some(Spec::GRSpeedI), Item::GBSpeedI => Some(Spec::GBSpeedI), Item::RBSpeedI => Some(Spec::RBSpeedI), Item::Damage => Some(Spec::Damage), Item::RedDamageI => Some(Spec::RedDamageI), Item::BlueDamageI => Some(Spec::BlueDamageI), Item::GreenDamageI => Some(Spec::GreenDamageI), Item::GRDI => Some(Spec::GRDI), Item::GBDI => Some(Spec::GBDI), Item::RBDI => Some(Spec::RBDI), Item::Life => Some(Spec::Life), Item::GRLI => Some(Spec::GRLI), Item::GBLI => Some(Spec::GBLI), Item::RBLI => Some(Spec::RBLI), Item::GreenLifeI => Some(Spec::GreenLifeI), Item::RedLifeI => Some(Spec::RedLifeI), Item::BlueLifeI => Some(Spec::BlueLifeI), _ => None, } } pub fn into_colour(&self) -> Colour { match *self { Item::Red => Colour::Red, Item::Green => Colour::Green, Item::Blue => Colour::Blue, _ => panic!("{:?} is not a colour", self), } } pub fn into_description(&self) -> String { match self { // colours Item::Blue => format!("Combine with skills and specs to create upgraded items. \n Deterrents and destruction."), Item::Green => format!("Combine with skills and specs to create upgraded items.\n Protection and trickery."), Item::Red => format!("Combine with skills and specs to create upgraded items. \n Speed and chaos."), // base skills Item::Attack => format!("Deal red damage based on {:?}% red power", self.into_skill().unwrap().multiplier()), Item::Block => format!("Reduce incoming red damage by {:?}%", 100 - Effect::Block.apply(100, None)), Item::Stun => format!("Stun target cryp for {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Buff => format!("Increase target cryp red damage and speed by {:?}%", Effect::Buff.apply(100, None) - 100), Item::Debuff => format!("Slow target cryp"), // specs // Base Item::Damage => format!("Base ITEM for increased DAMAGE. DAMAGE determines the power of your SKILLS."), Item::Life => format!("Base ITEM for increased LIFE. When your CRYP reaches 0 GreenLife it becomes KO and cannot cast SKILLS."), Item::Speed => format!("Base ITEM for increased SPEED. SPEED determines the order in which skills resolve."), // Lifes Upgrades Item::GreenLifeI => format!("Increases CRYP GreenLife. When your CRYP reaches 0 GreenLife it becomes KO and cannot cast SKILLS."), Item::RedLifeI => format!("Increases CRYP RedLife. Red damage dealt to your cryp reduces RedLife before GreenLife."), Item::BlueLifeI => format!("Increases CRYP BlueLife. Blue damage dealt to your cryp reduces BlueLife before GreenLife."), Item::GRLI => format!("Increases CRYP GreenLife + RedLife"), Item::GBLI => format!("Increases CRYP GreenLife + BlueLife"), Item::RBLI => format!("Increases CRYP RedLife + BlueLife"), // Damage Upgrades Item::RedDamageI => format!("Increases CRYP RedDamage."), Item::BlueDamageI => format!("Increases CRYP BlueDamage."), Item::GreenDamageI => format!("Increases CRYP GreenDamage."), Item::GRDI => format!("Increases CRYP GreenDamage + RedDamage."), Item::GBDI => format!("Increases CRYP GreenDamage + BlueDamage."), Item::RBDI => format!("Increases CRYP RedDamage + BlueDamage."), // Speed Upgrades Item::RedSpeedI => format!("Increases CRYP SPEED and provides COLOUR BONUSES"), Item::BlueSpeedI => format!("Increases CRYP SPEED and provides COLOUR BONUSES"), Item::GreenSpeedI => format!("Increases CRYP SPEED and provides COLOUR BONUSES"), Item::GRSpeedI => format!("Increases CRYP SPEED and provides COLOUR BONUSES"), Item::GBSpeedI => format!("Increases CRYP SPEED and provides COLOUR BONUSES"), Item::RBSpeedI => format!("Increases CRYP SPEED and provides COLOUR BONUSES"), // Skills <- need to move effect mulltipliers into skills Item::Amplify => format!("Increase red and blue power by {:?}%. Lasts {:?}T", Effect::Amplify.apply(100, None) - 100, self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Banish => format!("Banish target for {:?}T. Banished cryps are immune to all skills and effects.", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Blast => format!("Deals blue damage {:?}% blue power.", self.into_skill().unwrap().multiplier()), Item::Chaos => format!( "Hits twice for red and blue damage. Damage is random 0 to 30% + {:?}% red and blue power.", self.into_skill().unwrap().multiplier()), Item::Clutch => format!("Cryp cannot be KO'd while active. Additionally provides immunity to disables."), Item::Corrupt => format!( "Self targetting defensive for {:?}T. Applies corrupt to attackers dealing blue damage {:?}% blue power per turn for {:?}T.", self.into_skill().unwrap().effect().first().unwrap().get_duration(), Skill::Corrupt.multiplier(), self.into_skill().unwrap().effect().first().unwrap().get_duration()), // Need secondary Item::Curse => format!( "Increases red and blue damage taken by 50%. Lasts {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Decay => format!( "Reduces healing taken by 50% and deals blue damage {:?}% blue power each turn. Lasts {:?}T", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Hostility => format!( "Gain Hostility for {:?}T. {} Hatred lasts {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_duration(), "When attacked by Hostility you gain Hatred which increased red and blue power based on damage taken.", self.into_skill().unwrap().secondary_duration()), Item::Haste => format!( "{} {:?}{}. Lasts {:?}T", "Haste increases Speed by 50%, Red based Attack skills will strike again dealing", Skill::HasteStrike.multiplier(), "% Speed as Red Damage", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Heal => format!("Heals for {:?}% green power.", self.into_skill().unwrap().multiplier()), Item::Hex => format!("Blue based skill that applies Hex for {:?}T. \ Hexed targets cannot cast any skills.", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Impurity => format!( "{} {:?}{}. Lasts {:?}T", "Impurity increases Green Power by 50%, Blue based Attack skills will blast again dealing", Skill::ImpureBlast.multiplier(), "% Green Power as Blue Damage", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Invert => format!( "Reverse healing into damage and damage into healing. Any excess red or blue damage is converted into shield recharge."), Item::Parry => format!("{} {:?}% red power and blocks red skills for {:?}T. {} {:?}% red power.", "Self targetting skill. Recharges RedLife for", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().effect().first().unwrap().get_duration(), "If a red skill is parried the cryp will riposte the source dealing red damage", Skill::Riposte.multiplier()), Item::Purge => format!("Remove buffs from target cryp"), Item::Purify => format!( "Remove debuffs and heals for {:?}% green power per debuff removed.", self.into_skill().unwrap().multiplier()), Item::Reflect => format!( "Reflect incoming skills to source. Lasts {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Recharge => format!( "Recharge red and blue shield based on {:?} red and blue power", self.into_skill().unwrap().multiplier()), Item::Ruin => format!( "Team wide Stun for {:?}T. Stunned cryps are unable to cast skills.", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Scatter => format!( "Caster links with target. Linked cryps split incoming damage evenly. Recharges target blue shield {:?}% of blue power", self.into_skill().unwrap().multiplier()), Item::Silence => format!( "Block the target from using blue skills for {:?}T and deals blue damage {:?}% blue power. {}", self.into_skill().unwrap().effect().first().unwrap().get_duration(), self.into_skill().unwrap().multiplier(), "Deals 45% more damage per blue skill on target"), Item::Slay => format!( "Deals red damage {:?}% red power and provides self healing based on damage dealt.", self.into_skill().unwrap().multiplier()), Item::Sleep => format!( "Stun for {:?}T and heal for {:?}% green power.", self.into_skill().unwrap().effect().first().unwrap().get_duration(), self.into_skill().unwrap().multiplier()), Item::Snare => format!( "Block the target from using red skills for {:?}T and deals red damage {:?}% red power. {}", self.into_skill().unwrap().effect().first().unwrap().get_duration(), self.into_skill().unwrap().multiplier(), "Deals 35% more damage per red skill on target"), Item::Strangle => format!( "Strangle the target disabling skills from both the caster and the target. While strangling deal red damage each turn {:?}% red power. Lasts {:?}T.", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Strike => format!( "Hits at maximum speed dealing red damage {:?}% red power", self.into_skill().unwrap().multiplier()), Item::StrikeII => format!( "Hits at maximum speed dealing red damage {:?}% red power", self.into_skill().unwrap().multiplier()), Item::StrikeIII => format!( "Hits at maximum speed dealing red damage {:?}% red power", self.into_skill().unwrap().multiplier()), Item::Siphon => format!( "Deals blue damage {:?}% blue power each turn and heals caster based on damage dealt. Lasts {:?}T", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Taunt => format!("{} {:?}T. Recharges RedLife for {:?} red power.", "Taunt redirects skills against the team to target, lasts", self.into_skill().unwrap().effect().first().unwrap().get_duration(), self.into_skill().unwrap().multiplier()), Item::Throw => format!( "Stun the target for {:?}T and applies Vulnerable increasing red damage taken by 50% for {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_duration(), self.into_skill().unwrap().secondary_duration()), Item::Triage => format!( "Heals target for {:?}% green power each turn. Lasts {:?}T", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().effect().first().unwrap().get_duration()), _ => format!("..."), } } fn combo(&self) -> Vec { match self { Item::Taunt => vec![Item::Buff, Item::Red, Item::Red], Item::Triage => vec![Item::Buff, Item::Green, Item::Green], Item::Scatter => vec![Item::Buff, Item::Blue, Item::Blue], //To be impl Item::Haste => vec![Item::Buff, Item::Red, Item::Green], Item::Impurity => vec![Item::Buff, Item::Green, Item::Blue], Item::Amplify => vec![Item::Buff, Item::Red, Item::Blue], // Some flavour Item::Snare => vec![Item::Debuff, Item::Red, Item::Red], Item::Purge => vec![Item::Debuff, Item::Green, Item::Green], // Needs flavour Item::Silence => vec![Item::Debuff, Item::Blue, Item::Blue], Item::Curse => vec![Item::Debuff, Item::Red, Item::Green], // To be reworked Item::Decay => vec![Item::Debuff, Item::Green, Item::Blue], Item::Invert => vec![Item::Debuff, Item::Red, Item::Blue], Item::Parry => vec![Item::Block, Item::Red, Item::Red], // Add red recharge Item::Purify => vec![Item::Block, Item::Green, Item::Green], Item::Corrupt => vec![Item::Block, Item::Blue, Item::Blue], Item::Clutch => vec![Item::Block, Item::Red, Item::Green], Item::Reflect => vec![Item::Block, Item::Green, Item::Blue], Item::Recharge => vec![Item::Block, Item::Red, Item::Blue], Item::Strangle => vec![Item::Stun, Item::Red, Item::Red], Item::Sleep => vec![Item::Stun, Item::Green, Item::Green], Item::Ruin => vec![Item::Stun, Item::Blue, Item::Blue], Item::Throw => vec![Item::Stun, Item::Red, Item::Green], Item::Hex => vec![Item::Stun, Item::Green, Item::Blue], Item::Banish => vec![Item::Stun, Item::Red, Item::Blue], Item::Strike => vec![Item::Attack, Item::Red, Item::Red], Item::StrikeII => vec![Item::Strike, Item::Strike, Item::Strike], Item::StrikeIII => vec![Item::StrikeII, Item::StrikeII, Item::StrikeII], Item::Heal => vec![Item::Attack, Item::Green, Item::Green], Item::Blast => vec![Item::Attack, Item::Blue, Item::Blue], Item::Slay => vec![Item::Attack, Item::Red, Item::Green], Item::Siphon => vec![Item::Attack, Item::Green, Item::Blue], Item::Chaos => vec![Item::Attack, Item::Red, Item::Blue], Item::RedDamageI => vec![Item::Damage, Item::Red, Item::Red], Item::GreenDamageI => vec![Item::Damage, Item::Green, Item::Green], Item::BlueDamageI => vec![Item::Damage, Item::Blue, Item::Blue], Item::GRDI => vec![Item::Damage, Item::Red, Item::Green], Item::GBDI => vec![Item::Damage, Item::Green, Item::Blue], Item::RBDI => vec![Item::Damage, Item::Red, Item::Blue], Item::RedLifeI => vec![Item::Life, Item::Red, Item::Red], Item::GreenLifeI => vec![Item::Life, Item::Green, Item::Green], Item::BlueLifeI => vec![Item::Life, Item::Blue, Item::Blue], Item::GRLI => vec![Item::Life, Item::Red, Item::Green], Item::GBLI => vec![Item::Life, Item::Green, Item::Blue], Item::RBLI => vec![Item::Life, Item::Red, Item::Blue], Item::RedSpeedI => vec![Item::Speed, Item::Red, Item::Red], Item::GreenSpeedI => vec![Item::Speed, Item::Green, Item::Green], Item::BlueSpeedI => vec![Item::Speed, Item::Blue, Item::Blue], Item::GRSpeedI => vec![Item::Speed, Item::Red, Item::Green], Item::GBSpeedI => vec![Item::Speed, Item::Green, Item::Blue], Item::RBSpeedI => vec![Item::Speed, Item::Red, Item::Blue], _ => vec![*self], } } } impl From for Item { fn from(skill: Skill) -> Item { match skill { Skill::Amplify => Item::Amplify, Skill::Attack => Item::Attack, Skill::Banish => Item::Banish, Skill::Blast => Item::Blast, Skill::Block => Item::Block, Skill::Buff => Item::Buff, Skill::Chaos => Item::Chaos, Skill::Curse => Item::Curse, Skill::Clutch => Item::Clutch, Skill::Decay => Item::Decay, Skill::Debuff => Item::Debuff, Skill::Haste => Item::Haste, Skill::Hostility => Item::Hostility, Skill::Heal => Item::Heal, Skill::Hex => Item::Hex, Skill::Impurity => Item::Impurity, Skill::Invert => Item::Invert, Skill::Parry => Item::Parry, Skill::Purge => Item::Purge, Skill::Purify => Item::Purify, Skill::Recharge => Item::Recharge, Skill::Reflect => Item::Reflect, Skill::Ruin => Item::Ruin, Skill::Scatter => Item::Scatter, Skill::Silence => Item::Silence, Skill::Siphon => Item::Siphon, Skill::Slay => Item::Slay, Skill::Sleep => Item::Sleep, Skill::Snare => Item::Snare, Skill::Strangle => Item::Strangle, Skill::Strike => Item::Strike, Skill::StrikeII => Item::StrikeII, Skill::StrikeIII => Item::StrikeIII, Skill::Stun => Item::Stun, Skill::Taunt => Item::Taunt, Skill::Throw => Item::Throw, Skill::Triage => Item::Triage, Skill::Corrupt => Item::Corrupt, Skill::CorruptionTick => Item::Corrupt, Skill::DecayTick => Item::Decay, Skill::SiphonTick => Item::Siphon, Skill::StrangleTick => Item::Strangle, Skill::TriageTick => Item::Triage, Skill::TestTouch => Item::TestTouch, Skill::TestStun => Item::TestStun, Skill::TestBlock => Item::TestBlock, Skill::TestParry => Item::TestParry, Skill::TestSiphon => Item::TestSiphon, _ => panic!("{:?} not implemented with item conversion", skill), } } } impl From for Item { fn from(spec: Spec) -> Item { match spec { Spec::Speed => Item::Speed, Spec::RedSpeedI => Item::RedSpeedI, Spec::BlueSpeedI => Item::BlueSpeedI, Spec::GreenSpeedI => Item::GreenSpeedI, Spec::GRSpeedI => Item::GRSpeedI, Spec::GBSpeedI => Item::GBSpeedI, Spec::RBSpeedI => Item::RBSpeedI, Spec::Damage => Item::Damage, Spec::RedDamageI => Item::RedDamageI, Spec::BlueDamageI => Item::BlueDamageI, Spec::GreenDamageI => Item::GreenDamageI, Spec::GRDI => Item::GRDI, Spec::GBDI => Item::GBDI, Spec::RBDI => Item::RBDI, Spec::Life => Item::Life, Spec::GRLI => Item::GRLI, Spec::GBLI => Item::GBLI, Spec::RBLI => Item::RBLI, Spec::GreenLifeI => Item::GreenLifeI, Spec::RedLifeI => Item::RedLifeI, Spec::BlueLifeI => Item::BlueLifeI, // _ => panic!("{:?} not implemented as a item", spec), } } } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct Combo { pub item: Item, pub components: Vec, } pub fn get_combos() -> Vec { let mut combinations = vec![ Combo { components: Item::Taunt.combo(), item: Item::Taunt }, Combo { components: Item::Triage.combo(), item: Item::Triage }, Combo { components: Item::Scatter.combo(), item: Item::Scatter }, //To be impl Combo { components: Item::Haste.combo(), item: Item::Haste }, Combo { components: Item::Impurity.combo(), item: Item::Impurity }, Combo { components: Item::Amplify.combo(), item: Item::Amplify }, // Some flavour Combo { components: Item::Snare.combo(), item: Item::Snare }, Combo { components: Item::Purge.combo(), item: Item::Purge }, // Needs flavour Combo { components: Item::Silence.combo(), item: Item::Silence }, Combo { components: Item::Curse.combo(), item: Item::Curse }, // To be reworked Combo { components: Item::Decay.combo(), item: Item::Decay }, Combo { components: Item::Invert.combo(), item: Item::Invert }, Combo { components: Item::Parry.combo(), item: Item::Parry }, // Add red recharge Combo { components: Item::Purify.combo(), item: Item::Purify }, Combo { components: Item::Corrupt.combo(), item: Item::Corrupt }, Combo { components: Item::Clutch.combo(), item: Item::Clutch }, Combo { components: Item::Reflect.combo(), item: Item::Reflect }, Combo { components: Item::Recharge.combo(), item: Item::Recharge }, Combo { components: Item::Strangle.combo(), item: Item::Strangle }, Combo { components: Item::Sleep.combo(), item: Item::Sleep }, Combo { components: Item::Ruin.combo(), item: Item::Ruin }, Combo { components: Item::Throw.combo(), item: Item::Throw }, Combo { components: Item::Hex.combo(), item: Item::Hex }, Combo { components: Item::Banish.combo(), item: Item::Banish }, Combo { components: Item::Strike.combo(), item: Item::Strike }, Combo { components: Item::StrikeII.combo(), item: Item::StrikeII }, Combo { components: Item::StrikeIII.combo(), item: Item::StrikeIII }, Combo { components: Item::Heal.combo(), item: Item::Heal }, Combo { components: Item::Blast.combo(), item: Item::Blast }, Combo { components: Item::Slay.combo(), item: Item::Slay }, Combo { components: Item::Siphon.combo(), item: Item::Siphon }, Combo { components: Item::Chaos.combo(), item: Item::Chaos }, Combo { components: Item::RedDamageI.combo(), item: Item::RedDamageI }, Combo { components: Item::GreenDamageI.combo(), item: Item::GreenDamageI }, Combo { components: Item::BlueDamageI.combo(), item: Item::BlueDamageI }, Combo { components: Item::GRDI.combo(), item: Item::GRDI }, Combo { components: Item::GBDI.combo(), item: Item::GBDI }, Combo { components: Item::RBDI.combo(), item: Item::RBDI }, Combo { components: Item::RedLifeI.combo(), item: Item::RedLifeI }, Combo { components: Item::GreenLifeI.combo(), item: Item::GreenLifeI }, Combo { components: Item::BlueLifeI.combo(), item: Item::BlueLifeI }, Combo { components: Item::GRLI.combo(), item: Item::GRLI }, Combo { components: Item::GBLI.combo(), item: Item::GBLI }, Combo { components: Item::RBLI.combo(), item: Item::RBLI }, Combo { components: Item::RedSpeedI.combo(), item: Item::RedSpeedI }, Combo { components: Item::GreenSpeedI.combo(), item: Item::GreenSpeedI }, Combo { components: Item::BlueSpeedI.combo(), item: Item::BlueSpeedI }, Combo { components: Item::GRSpeedI.combo(), item: Item::GRSpeedI }, Combo { components: Item::GBSpeedI.combo(), item: Item::GBSpeedI }, Combo { components: Item::RBSpeedI.combo(), item: Item::RBSpeedI }, ]; combinations.iter_mut().for_each(|set| set.components.sort_unstable()); return combinations; } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct ItemInfo { pub item: Item, pub spec: bool, pub skill: bool, pub description: String, } #[derive(Debug,Clone,Serialize,Deserialize)] pub struct ItemInfoCtr { pub combos: Vec, pub items: Vec, } pub fn item_info() -> ItemInfoCtr { let combos = get_combos(); let mut items = combos .into_iter() .flat_map(|mut c| { c.components.push(c.item); c.components }) .collect::>(); items.sort_unstable(); items.dedup(); let items = items .into_iter() .map(|v| ItemInfo { item: v, spec: v.into_spec().is_some(), skill: v.into_skill().is_some(), description: v.into_description(), }) .collect::>(); let combos = get_combos(); return ItemInfoCtr { combos, items, }; } #[cfg(test)] mod tests { use super::*; #[test] fn item_components_test() { assert_eq!(Item::Strike.components(), vec![Item::Red, Item::Red, Item::Attack]); assert_eq!(Item::StrikeII.components(), vec![ Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, ]); assert_eq!(Item::StrikeIII.components(), vec![ Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, Item::Red, Item::Red, Item::Attack, ]); } }