use skill::{Skill, Effect, Colour}; use spec::{Spec}; use construct::{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 Power, Life, Speed, // Lifes Upgrades GreenLifeI, RedLifeI, BlueLifeI, GRLI, GBLI, RBLI, // Power Upgrades RedPowerI, BluePowerI, GreenPowerI, 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::Power => 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::Power => Some(Spec::Power), Item::RedPowerI => Some(Spec::RedPowerI), Item::BluePowerI => Some(Spec::BluePowerI), Item::GreenPowerI => Some(Spec::GreenPowerI), 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 RedDamage based on {:?}% RedPower", self.into_skill().unwrap().multiplier()), Item::Block => format!("Reduce incoming RedDamage by {:?}%", 100 - self.into_skill().unwrap().effect().first().unwrap().get_multiplier()), Item::Stun => format!("Stun target construct for {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Buff => format!("Increase target construct RedPower and speed by {:?}%", self.into_skill().unwrap().effect().first().unwrap().get_multiplier() - 100), Item::Debuff => format!("Slow target construct speed by {:?}%", 100 - self.into_skill().unwrap().effect().first().unwrap().get_multiplier()), // specs // Base Item::Power => format!("Base ITEM for increased Power. Power determines the damage caused by your SKILLS."), Item::Life => format!("Base ITEM for increased LIFE. When your CONSTRUCT 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 CONSTRUCT GreenLife. When your CONSTRUCT reaches 0 GreenLife it becomes KO and cannot cast SKILLS."), Item::RedLifeI => format!("Increases CONSTRUCT RedLife. RedDamage dealt to your construct reduces RedLife before GreenLife."), Item::BlueLifeI => format!("Increases CONSTRUCT BlueLife. BlueDamage dealt to your construct reduces BlueLife before GreenLife."), Item::GRLI => format!("Increases CONSTRUCT GreenLife + RedLife"), Item::GBLI => format!("Increases CONSTRUCT GreenLife + BlueLife"), Item::RBLI => format!("Increases CONSTRUCT RedLife + BlueLife"), // Power Upgrades Item::RedPowerI => format!("Increases CONSTRUCT RedPower."), Item::BluePowerI => format!("Increases CONSTRUCT BluePower."), Item::GreenPowerI => format!("Increases CONSTRUCT GreenPower."), Item::GRDI => format!("Increases CONSTRUCT GreenPower + RedPower."), Item::GBDI => format!("Increases CONSTRUCT GreenPower + BluePower."), Item::RBDI => format!("Increases CONSTRUCT RedPower + BluePower."), // Speed Upgrades Item::RedSpeedI => format!("Increases CONSTRUCT SPEED and provides COLOUR BONUSES"), Item::BlueSpeedI => format!("Increases CONSTRUCT SPEED and provides COLOUR BONUSES"), Item::GreenSpeedI => format!("Increases CONSTRUCT SPEED and provides COLOUR BONUSES"), Item::GRSpeedI => format!("Increases CONSTRUCT SPEED and provides COLOUR BONUSES"), Item::GBSpeedI => format!("Increases CONSTRUCT SPEED and provides COLOUR BONUSES"), Item::RBSpeedI => format!("Increases CONSTRUCT SPEED and provides COLOUR BONUSES"), // Skills <- need to move effect mulltipliers into skills Item::Amplify => format!("Increase red and BluePower by {:?}%. Lasts {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_multiplier() - 100, self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Banish => format!("Banish target for {:?}T. Banished constructs are immune to all skills and effects.", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Blast => format!("Deals BlueDamage {:?}% BluePower.", self.into_skill().unwrap().multiplier()), Item::Chaos => format!( "Hits twice for red and BlueDamage. Damage is random 0 to 30% + {:?}% red and BluePower.", self.into_skill().unwrap().multiplier()), Item::Clutch => format!("Construct cannot be KO'd while active. Additionally provides immunity to disables."), Item::Corrupt => format!( "Self targetting defensive for {:?}T. Applies corrupt to attackers dealing BlueDamage {:?}% BluePower per turn for {:?}T.", self.into_skill().unwrap().effect().first().unwrap().get_duration(), Skill::Corrupt.multiplier(), self.into_skill().unwrap().effect().last().unwrap().get_duration()), Item::Curse => format!( "Increases red and BlueDamage taken by {:?}%. Lasts {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_multiplier() - 100, self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Decay => format!( "Reduces healing taken by {:?}% and deals BlueDamage {:?}% BluePower each turn. Lasts {:?}T", 100 - self.into_skill().unwrap().effect().first().unwrap().get_multiplier(), 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 BluePower based on Damage taken.", self.into_skill().unwrap().effect().last().unwrap().get_duration()), Item::Haste => format!( "Haste increases Speed by {:?}%, Red based Attack skills will strike again dealing {:?}{}. Lasts {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_multiplier() - 100, Skill::HasteStrike.multiplier(), "% Speed as RedDamage", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Heal => format!("Heals for {:?}% GreenPower.", 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!( "Impurity increases GreenPower by {:?}%, Blue based Attack skills will blast again dealing {:?}{}. Lasts {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_multiplier() - 100, Skill::ImpureBlast.multiplier(), "% GreenPower as BluePower", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Invert => format!( "Reverse healing into Damage and Damage into healing. Any excess red or BlueDamage is converted into shield recharge."), Item::Parry => format!("{} {:?}% RedPower and blocks red skills for {:?}T. {} {:?}% RedPower.", "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 construct will riposte the source dealing RedDamage", Skill::Riposte.multiplier()), Item::Purge => format!("Remove buffs from target construct"), Item::Purify => format!( "Remove debuffs and heals for {:?}% GreenPower 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 BluePower", self.into_skill().unwrap().multiplier()), Item::Ruin => format!( "Team wide Stun for {:?}T. Stunned constructs are unable to cast skills.", self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Scatter => format!( "Caster links with target. Linked constructs split incoming Damage evenly. Recharges target blue shield {:?}% of BluePower", self.into_skill().unwrap().multiplier()), Item::Silence => format!( "Block the target from using blue skills for {:?}T and deals BlueDamage {:?}% BluePower. {}", 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 RedDamage {:?}% RedPower and provides self healing based on Damage dealt.", self.into_skill().unwrap().multiplier()), Item::Sleep => format!( "Stun for {:?}T and heal for {:?}% GreenPower.", 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 RedDamage {:?}% RedPower. {}", 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 RedDamage each turn {:?}% RedPower. Lasts {:?}T.", self.into_skill().unwrap().multiplier(), self.into_skill().unwrap().effect().first().unwrap().get_duration()), Item::Strike => format!( "Hits at maximum speed dealing RedDamage {:?}% RedPower", self.into_skill().unwrap().multiplier()), Item::StrikeII => format!( "Hits at maximum speed dealing RedDamage {:?}% RedPower", self.into_skill().unwrap().multiplier()), Item::StrikeIII => format!( "Hits at maximum speed dealing RedDamage {:?}% RedPower", self.into_skill().unwrap().multiplier()), Item::Siphon => format!( "Deals BlueDamage {:?}% BluePower 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 {:?} RedPower.", "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 RedDamage taken by {:?}% for {:?}T", self.into_skill().unwrap().effect().first().unwrap().get_duration(), self.into_skill().unwrap().effect().first().unwrap().get_multiplier() - 100, self.into_skill().unwrap().effect().last().unwrap().get_duration()), Item::Triage => format!( "Heals target for {:?}% GreenPower 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::RedPowerI => vec![Item::Power, Item::Red, Item::Red], Item::GreenPowerI => vec![Item::Power, Item::Green, Item::Green], Item::BluePowerI => vec![Item::Power, Item::Blue, Item::Blue], Item::GRDI => vec![Item::Power, Item::Red, Item::Green], Item::GBDI => vec![Item::Power, Item::Green, Item::Blue], Item::RBDI => vec![Item::Power, 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::Power => Item::Power, Spec::RedPowerI => Item::RedPowerI, Spec::BluePowerI => Item::BluePowerI, Spec::GreenPowerI => Item::GreenPowerI, 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::RedPowerI.combo(), item: Item::RedPowerI }, Combo { components: Item::GreenPowerI.combo(), item: Item::GreenPowerI }, Combo { components: Item::BluePowerI.combo(), item: Item::BluePowerI }, 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, ]); } }