From 85b73824874adcbf1cdcb852f1673df0dbb81b36 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 25 Jul 2021 16:27:00 -0500 Subject: [PATCH] Added handedness requirements to recipes and components. --- .../modular/damage/sword/greatsword.ron | 11 +- .../modular/damage/sword/katana.ron | 15 +- .../modular/damage/sword/longsword.ron | 6 +- .../modular/damage/sword/ornate.ron | 12 +- .../modular/damage/sword/sabre.ron | 20 +- .../modular/damage/sword/sawblade.ron | 16 +- .../modular/damage/sword/zweihander.ron | 17 +- .../modular/held/sword/hand-and-half.ron | 24 +++ .../modular/held/sword/one-handed.ron | 5 +- .../modular/held/sword/two-handed.ron | 5 +- common/src/comp/inventory/item/mod.rs | 62 +++--- common/src/comp/inventory/item/modular.rs | 195 +++++++++--------- common/src/comp/inventory/item/tool.rs | 34 ++- common/src/comp/inventory/mod.rs | 6 +- voxygen/src/hud/crafting.rs | 4 +- 15 files changed, 260 insertions(+), 172 deletions(-) create mode 100644 assets/common/items/crafting_ing/modular/held/sword/hand-and-half.ron diff --git a/assets/common/items/crafting_ing/modular/damage/sword/greatsword.ron b/assets/common/items/crafting_ing/modular/damage/sword/greatsword.ron index 4b50d05ef8..8f08ea97bd 100644 --- a/assets/common/items/crafting_ing/modular/damage/sword/greatsword.ron +++ b/assets/common/items/crafting_ing/modular/damage/sword/greatsword.ron @@ -6,16 +6,19 @@ ItemDef( modkind: Damage, stats: ( equip_time_secs: 0.25, - power: 1.1, - effect_power: 1.6, - speed: 0.85, + power: 0.9, + effect_power: 2.0, + speed: 0.8, crit_chance: 0.15, range: 1.0, energy_efficiency: 0.8, buff_strength: 0.8, ), + hand_restriction: Some(Two), )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Damage))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/damage/sword/katana.ron b/assets/common/items/crafting_ing/modular/damage/sword/katana.ron index f56321265f..72a3f301b6 100644 --- a/assets/common/items/crafting_ing/modular/damage/sword/katana.ron +++ b/assets/common/items/crafting_ing/modular/damage/sword/katana.ron @@ -6,16 +6,19 @@ ItemDef( modkind: Damage, stats: ( equip_time_secs: 0.25, - power: 0.7, + power: 0.9, effect_power: 0.8, speed: 1.5, - crit_chance: 0.2, - range: 0.8, - energy_efficiency: 1.2, - buff_strength: 1.0, + crit_chance: 0.15, + range: 1.0, + energy_efficiency: 0.8, + buff_strength: 0.8, ), + hand_restriction: Some(One), )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Damage))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: One)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/damage/sword/longsword.ron b/assets/common/items/crafting_ing/modular/damage/sword/longsword.ron index ecfc947b71..c4a9836c8e 100644 --- a/assets/common/items/crafting_ing/modular/damage/sword/longsword.ron +++ b/assets/common/items/crafting_ing/modular/damage/sword/longsword.ron @@ -14,8 +14,12 @@ ItemDef( energy_efficiency: 1.0, buff_strength: 1.0, ), + hand_restriction: None, )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Damage))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: One)), + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/damage/sword/ornate.ron b/assets/common/items/crafting_ing/modular/damage/sword/ornate.ron index 25e1a53823..05d5fda64b 100644 --- a/assets/common/items/crafting_ing/modular/damage/sword/ornate.ron +++ b/assets/common/items/crafting_ing/modular/damage/sword/ornate.ron @@ -6,16 +6,20 @@ ItemDef( modkind: Damage, stats: ( equip_time_secs: 0.25, - power: 0.8, + power: 0.9, effect_power: 0.8, - speed: 1.0, + speed: 0.9, crit_chance: 0.5, range: 1.0, - energy_efficiency: 1.1, + energy_efficiency: 0.8, buff_strength: 0.8, ), + hand_restriction: None, )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Damage))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: One)), + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/damage/sword/sabre.ron b/assets/common/items/crafting_ing/modular/damage/sword/sabre.ron index 6d2aaeea7d..1555dc2373 100644 --- a/assets/common/items/crafting_ing/modular/damage/sword/sabre.ron +++ b/assets/common/items/crafting_ing/modular/damage/sword/sabre.ron @@ -6,16 +6,20 @@ ItemDef( modkind: Damage, stats: ( equip_time_secs: 0.25, - power: 1.6, - effect_power: 0.9, - speed: 0.8, - crit_chance: 0.2, - range: 0.9, - energy_efficiency: 0.9, - buff_strength: 0.9, + power: 1.5, + effect_power: 0.8, + speed: 0.9, + crit_chance: 0.15, + range: 1.0, + energy_efficiency: 0.8, + buff_strength: 0.8, ), + hand_restriction: None, )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Damage))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: One)), + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/damage/sword/sawblade.ron b/assets/common/items/crafting_ing/modular/damage/sword/sawblade.ron index 2553fffe9e..10354a9e11 100644 --- a/assets/common/items/crafting_ing/modular/damage/sword/sawblade.ron +++ b/assets/common/items/crafting_ing/modular/damage/sword/sawblade.ron @@ -6,16 +6,20 @@ ItemDef( modkind: Damage, stats: ( equip_time_secs: 0.25, - power: 0.8, - effect_power: 0.7, + power: 0.9, + effect_power: 0.8, speed: 0.9, - crit_chance: 0.25, + crit_chance: 0.15, range: 1.0, - energy_efficiency: 0.75, - buff_strength: 1.8, + energy_efficiency: 0.8, + buff_strength: 2.0, ), + hand_restriction: None, )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Damage))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: One)), + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/damage/sword/zweihander.ron b/assets/common/items/crafting_ing/modular/damage/sword/zweihander.ron index ce29dfb1a3..f575b15944 100644 --- a/assets/common/items/crafting_ing/modular/damage/sword/zweihander.ron +++ b/assets/common/items/crafting_ing/modular/damage/sword/zweihander.ron @@ -6,16 +6,19 @@ ItemDef( modkind: Damage, stats: ( equip_time_secs: 0.25, - power: 1.4, - effect_power: 1.1, - speed: 0.7, - crit_chance: 0.1, + power: 1.0, + effect_power: 0.9, + speed: 0.9, + crit_chance: 0.2, range: 1.5, - energy_efficiency: 0.8, - buff_strength: 1.1, + energy_efficiency: 0.9, + buff_strength: 0.9, ), + hand_restriction: Some(Two), )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Damage))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/held/sword/hand-and-half.ron b/assets/common/items/crafting_ing/modular/held/sword/hand-and-half.ron new file mode 100644 index 0000000000..ba4cd2d7b0 --- /dev/null +++ b/assets/common/items/crafting_ing/modular/held/sword/hand-and-half.ron @@ -0,0 +1,24 @@ +ItemDef( + name: "Hand-and-a-half sword hilt", + description: "A sword hilt.", + kind: ModularComponent(( + toolkind: Sword, + modkind: Held, + stats: ( + equip_time_secs: 1.0, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + ), + )), + quality: Common, + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: One)), + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], +) + diff --git a/assets/common/items/crafting_ing/modular/held/sword/one-handed.ron b/assets/common/items/crafting_ing/modular/held/sword/one-handed.ron index d766d11b1e..1a5834cca9 100644 --- a/assets/common/items/crafting_ing/modular/held/sword/one-handed.ron +++ b/assets/common/items/crafting_ing/modular/held/sword/one-handed.ron @@ -14,8 +14,11 @@ ItemDef( energy_efficiency: 1.1, buff_strength: 0.9, ), + hand_restriction: Some(One), )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Held))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: One)), + ], ) diff --git a/assets/common/items/crafting_ing/modular/held/sword/two-handed.ron b/assets/common/items/crafting_ing/modular/held/sword/two-handed.ron index 92d0cfd574..13b5c7b188 100644 --- a/assets/common/items/crafting_ing/modular/held/sword/two-handed.ron +++ b/assets/common/items/crafting_ing/modular/held/sword/two-handed.ron @@ -14,8 +14,11 @@ ItemDef( energy_efficiency: 0.9, buff_strength: 1.1, ), + hand_restriction: Some(Two), )), quality: Common, - tags: [ModularComponent((toolkind: Sword, modkind: Held))], + tags: [ + ModularComponent((toolkind: Sword, modkind: Held, hands: Two)), + ], ) diff --git a/common/src/comp/inventory/item/mod.rs b/common/src/comp/inventory/item/mod.rs index e058ec6937..2ecf3f39b2 100644 --- a/common/src/comp/inventory/item/mod.rs +++ b/common/src/comp/inventory/item/mod.rs @@ -24,7 +24,7 @@ use crossbeam_utils::atomic::AtomicCell; use serde::{de, Deserialize, Serialize, Serializer}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; -use std::{collections::hash_map::DefaultHasher, fmt, sync::Arc}; +use std::{borrow::Cow, collections::hash_map::DefaultHasher, fmt, sync::Arc}; use strum::IntoStaticStr; use tracing::error; use vek::Rgb; @@ -83,10 +83,10 @@ pub enum Quality { } pub trait TagExampleInfo { - fn name(&self) -> &'static str; + fn name(&self) -> Cow<'static, str>; /// What item to show in the crafting hud if the player has nothing with the /// tag - fn exemplar_identifier(&self) -> &'static str; + fn exemplar_identifier(&self) -> Cow<'static, str>; } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -216,9 +216,11 @@ impl MaterialTag { } impl TagExampleInfo for MaterialTag { - fn name(&self) -> &'static str { self.material.into() } + fn name(&self) -> Cow<'static, str> { Cow::Borrowed(self.material.into()) } - fn exemplar_identifier(&self) -> &'static str { "common.items.tag_examples.placeholder" } + fn exemplar_identifier(&self) -> Cow<'static, str> { + Cow::Borrowed("common.items.tag_examples.placeholder") + } } #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] @@ -239,40 +241,40 @@ pub enum ItemTag { } impl TagExampleInfo for ItemTag { - fn name(&self) -> &'static str { + fn name(&self) -> Cow<'static, str> { match self { ItemTag::Material(material) => material.name(), ItemTag::ModularComponent(kind) => kind.name(), - ItemTag::MetalIngot => "metal ingot", - ItemTag::Textile => "textile", - ItemTag::Leather => "leather", - ItemTag::Cultist => "cultist", - ItemTag::Potion => "potion", - ItemTag::Food => "food", - ItemTag::BaseMaterial => "basemat", - ItemTag::CraftingTool => "tool", - ItemTag::Utility => "utility", - ItemTag::Bag => "bag", - ItemTag::SalvageInto(_) => "salvage", + ItemTag::MetalIngot => Cow::Borrowed("metal ingot"), + ItemTag::Textile => Cow::Borrowed("textile"), + ItemTag::Leather => Cow::Borrowed("leather"), + ItemTag::Cultist => Cow::Borrowed("cultist"), + ItemTag::Potion => Cow::Borrowed("potion"), + ItemTag::Food => Cow::Borrowed("food"), + ItemTag::BaseMaterial => Cow::Borrowed("basemat"), + ItemTag::CraftingTool => Cow::Borrowed("tool"), + ItemTag::Utility => Cow::Borrowed("utility"), + ItemTag::Bag => Cow::Borrowed("bag"), + ItemTag::SalvageInto(_) => Cow::Borrowed("salvage"), } } // TODO: Autogenerate these? - fn exemplar_identifier(&self) -> &'static str { + fn exemplar_identifier(&self) -> Cow<'static, str> { match self { - ItemTag::Material(_) => "common.items.tag_examples.placeholder", + ItemTag::Material(_) => Cow::Borrowed("common.items.tag_examples.placeholder"), ItemTag::ModularComponent(tag) => tag.exemplar_identifier(), - ItemTag::MetalIngot => "common.items.tag_examples.metal_ingot", - ItemTag::Textile => "common.items.tag_examples.textile", - ItemTag::Leather => "common.items.tag_examples.leather", - ItemTag::Cultist => "common.items.tag_examples.cultist", - ItemTag::Potion => "common.items.tag_examples.placeholder", - ItemTag::Food => "common.items.tag_examples.placeholder", - ItemTag::BaseMaterial => "common.items.tag_examples.placeholder", - ItemTag::CraftingTool => "common.items.tag_examples.placeholder", - ItemTag::Utility => "common.items.tag_examples.placeholder", - ItemTag::Bag => "common.items.tag_examples.placeholder", - ItemTag::SalvageInto(_) => "common.items.tag_examples.placeholder", + ItemTag::MetalIngot => Cow::Borrowed("common.items.tag_examples.metal_ingot"), + ItemTag::Textile => Cow::Borrowed("common.items.tag_examples.textile"), + ItemTag::Leather => Cow::Borrowed("common.items.tag_examples.leather"), + ItemTag::Cultist => Cow::Borrowed("common.items.tag_examples.cultist"), + ItemTag::Potion => Cow::Borrowed("common.items.tag_examples.placeholder"), + ItemTag::Food => Cow::Borrowed("common.items.tag_examples.placeholder"), + ItemTag::BaseMaterial => Cow::Borrowed("common.items.tag_examples.placeholder"), + ItemTag::CraftingTool => Cow::Borrowed("common.items.tag_examples.placeholder"), + ItemTag::Utility => Cow::Borrowed("common.items.tag_examples.placeholder"), + ItemTag::Bag => Cow::Borrowed("common.items.tag_examples.placeholder"), + ItemTag::SalvageInto(_) => Cow::Borrowed("common.items.tag_examples.placeholder"), } } } diff --git a/common/src/comp/inventory/item/modular.rs b/common/src/comp/inventory/item/modular.rs index 6cc6011fe5..4bce2f9038 100644 --- a/common/src/comp/inventory/item/modular.rs +++ b/common/src/comp/inventory/item/modular.rs @@ -1,8 +1,12 @@ -use super::{tool, ItemKind, ItemTag, Quality, RawItemDef, TagExampleInfo, ToolKind}; +use super::{ + tool::{self, Hands}, + ItemKind, ItemTag, Quality, RawItemDef, TagExampleInfo, ToolKind, +}; use crate::recipe::{RawRecipe, RawRecipeBook, RawRecipeInput}; use hashbrown::HashMap; use lazy_static::lazy_static; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum ModularComponentKind { @@ -30,87 +34,63 @@ pub struct ModularComponent { pub struct ModularComponentTag { toolkind: ToolKind, modkind: ModularComponentKind, + hands: Hands, } impl TagExampleInfo for ModularComponentTag { - fn name(&self) -> &'static str { - match self.modkind { - ModularComponentKind::Damage => match self.toolkind { - ToolKind::Sword => "sword blade", - ToolKind::Axe => "axe head", - ToolKind::Hammer => "hammer head", - ToolKind::Bow => "bow limbs", - ToolKind::Dagger => "dagger blade", - ToolKind::Staff => "staff head", - ToolKind::Sceptre => "sceptre head", - // TODO: naming - ToolKind::Spear => "spear damage component", - ToolKind::Blowgun => "blowgun damage component", - ToolKind::Shield => "shield damage component", - ToolKind::Debug => "debug damage component", - ToolKind::Farming => "farming damage component", - ToolKind::Pick => "pickaxe head", - ToolKind::Natural => "natural damage component", - ToolKind::Empty => "empty damage component", - }, - ModularComponentKind::Held => match self.toolkind { - ToolKind::Sword => "sword hilt", - ToolKind::Axe => "axe shaft", - ToolKind::Hammer => "hammer shaft", - ToolKind::Bow => "bow riser", - ToolKind::Dagger => "dagger grip", - ToolKind::Staff => "staff shaft", - ToolKind::Sceptre => "sceptre shaft", - // TODO: naming - ToolKind::Spear => "spear held component", - ToolKind::Blowgun => "blowgun held component", - ToolKind::Shield => "shield held component", - ToolKind::Natural => "natural held component", - ToolKind::Debug => "debug held component", - ToolKind::Farming => "farming held component", - ToolKind::Pick => "pickaxe handle", - ToolKind::Empty => "empty held component", - }, - } + fn name(&self) -> Cow<'static, str> { + Cow::Owned(format!( + "{} {}", + self.hands.identifier_name().to_owned(), + match self.modkind { + ModularComponentKind::Damage => match self.toolkind { + ToolKind::Sword => "sword blade", + ToolKind::Axe => "axe head", + ToolKind::Hammer => "hammer head", + ToolKind::Bow => "bow limbs", + ToolKind::Dagger => "dagger blade", + ToolKind::Staff => "staff head", + ToolKind::Sceptre => "sceptre head", + // TODO: naming + ToolKind::Spear => "spear damage component", + ToolKind::Blowgun => "blowgun damage component", + ToolKind::Shield => "shield damage component", + ToolKind::Debug => "debug damage component", + ToolKind::Farming => "farming damage component", + ToolKind::Pick => "pickaxe head", + ToolKind::Natural => "natural damage component", + ToolKind::Empty => "empty damage component", + }, + ModularComponentKind::Held => match self.toolkind { + ToolKind::Sword => "sword hilt", + ToolKind::Axe => "axe shaft", + ToolKind::Hammer => "hammer shaft", + ToolKind::Bow => "bow riser", + ToolKind::Dagger => "dagger grip", + ToolKind::Staff => "staff shaft", + ToolKind::Sceptre => "sceptre shaft", + // TODO: naming + ToolKind::Spear => "spear held component", + ToolKind::Blowgun => "blowgun held component", + ToolKind::Shield => "shield held component", + ToolKind::Natural => "natural held component", + ToolKind::Debug => "debug held component", + ToolKind::Farming => "farming held component", + ToolKind::Pick => "pickaxe handle", + ToolKind::Empty => "empty held component", + }, + } + )) } - fn exemplar_identifier(&self) -> &'static str { - match self.modkind { - ModularComponentKind::Damage => match self.toolkind { - ToolKind::Sword => "common.items.tag_examples.modular.damage.sword", - ToolKind::Axe => "common.items.tag_examples.modular.damage.axe", - ToolKind::Hammer => "common.items.tag_examples.modular.damage.hammer", - ToolKind::Bow => "common.items.tag_examples.modular.damage.bow", - ToolKind::Dagger => "common.items.tag_examples.modular.damage.dagger", - ToolKind::Staff => "common.items.tag_examples.modular.damage.staff", - ToolKind::Sceptre => "common.items.tag_examples.modular.damage.sceptre", - ToolKind::Shield => "common.items.tag_examples.modular.damage.shield", - ToolKind::Spear => "common.items.tag_examples.modular.damage.spear", - ToolKind::Blowgun => "common.items.tag_examples.modular.damage.blowgun", - ToolKind::Natural => "common.items.tag_examples.modular.damage.natural", - ToolKind::Debug => "common.items.tag_examples.modular.damage.debug", - ToolKind::Farming => "common.items.tag_examples.modular.damage.farming", - ToolKind::Pick => "common.items.tag_examples.modular.damage.pick", - ToolKind::Empty => "common.items.tag_examples.modular.damage.empty", - }, - ModularComponentKind::Held => match self.toolkind { - ToolKind::Sword => "common.items.tag_examples.modular.held.sword", - ToolKind::Axe => "common.items.tag_examples.modular.held.axe", - ToolKind::Hammer => "common.items.tag_examples.modular.held.hammer", - ToolKind::Bow => "common.items.tag_examples.modular.held.bow", - ToolKind::Dagger => "common.items.tag_examples.modular.held.dagger", - ToolKind::Staff => "common.items.tag_examples.modular.held.staff", - ToolKind::Sceptre => "common.items.tag_examples.modular.held.sceptre", - ToolKind::Shield => "common.items.tag_examples.modular.held.shield", - ToolKind::Spear => "common.items.tag_examples.modular.held.spear", - ToolKind::Blowgun => "common.items.tag_examples.modular.held.blowgun", - ToolKind::Natural => "common.items.tag_examples.modular.held.natural", - ToolKind::Debug => "common.items.tag_examples.modular.held.debug", - ToolKind::Farming => "common.items.tag_examples.modular.held.farming", - ToolKind::Pick => "common.items.tag_examples.modular.held.pick", - ToolKind::Empty => "common.items.tag_examples.modular.held.empty", - }, - } + fn exemplar_identifier(&self) -> Cow<'static, str> { + Cow::Owned(format!( + "{}.{}.{}.{}", + TAG_EXAMPLES_PREFIX, + self.modkind.identifier_name(), + self.toolkind.identifier_name(), + self.hands.identifier_name() + )) } } @@ -128,13 +108,28 @@ const MODKINDS: [ModularComponentKind; 2] = const WEAPON_PREFIX: &str = "common.items.weapons.modular"; const TAG_EXAMPLES_PREFIX: &str = "common.items.tag_examples.modular"; -fn make_weapon_def(toolkind: ToolKind) -> (String, RawItemDef) { - let identifier = format!("{}.{}", WEAPON_PREFIX, toolkind.identifier_name(),); - let name = format!("Modular {}", toolkind.identifier_name()); - let description = format!("A {} made of components", toolkind.identifier_name()); +const HANDS: [Hands; 2] = [Hands::One, Hands::Two]; + +fn make_weapon_def(toolkind: ToolKind, hands: Hands) -> (String, RawItemDef) { + let identifier = format!( + "{}.{}.{}", + WEAPON_PREFIX, + toolkind.identifier_name(), + hands.identifier_name() + ); + let name = format!( + "Modular {} {}", + hands.identifier_name(), + toolkind.identifier_name() + ); + let description = format!( + "A {} {} made of components", + hands.identifier_name(), + toolkind.identifier_name() + ); let tool = tool::Tool { kind: toolkind, - hands: tool::Hands::Two, + hands, stats: tool::StatKind::Modular, }; let kind = ItemKind::Tool(tool); @@ -151,13 +146,14 @@ fn make_weapon_def(toolkind: ToolKind) -> (String, RawItemDef) { (identifier, item) } -fn make_recipe_def(identifier: String, toolkind: ToolKind) -> RawRecipe { +fn make_recipe_def(identifier: String, toolkind: ToolKind, hands: Hands) -> RawRecipe { let output = (identifier, 1); let mut inputs = Vec::new(); for &modkind in &MODKINDS { let input = RawRecipeInput::Tag(ItemTag::ModularComponent(ModularComponentTag { toolkind, modkind, + hands, })); inputs.push((input, 1, true)); } @@ -168,14 +164,23 @@ fn make_recipe_def(identifier: String, toolkind: ToolKind) -> RawRecipe { } } -fn make_tagexample_def(toolkind: ToolKind, modkind: ModularComponentKind) -> (String, RawItemDef) { +fn make_tagexample_def( + toolkind: ToolKind, + modkind: ModularComponentKind, + hands: Hands, +) -> (String, RawItemDef) { let identifier = format!( - "{}.{}.{}", + "{}.{}.{}.{}", TAG_EXAMPLES_PREFIX, modkind.identifier_name(), toolkind.identifier_name(), + hands.identifier_name(), ); - let tag = ModularComponentTag { toolkind, modkind }; + let tag = ModularComponentTag { + toolkind, + modkind, + hands, + }; // TODO: i18n let name = format!("Any {}", tag.name()); let description = format!( @@ -205,15 +210,15 @@ fn initialize_modular_assets() -> (HashMap, RawRecipeBook) { let mut itemdefs = HashMap::new(); let mut recipes = HashMap::new(); for &toolkind in &SUPPORTED_TOOLKINDS { - let (identifier, item) = make_weapon_def(toolkind); - itemdefs.insert(identifier.clone(), item); - let recipe = make_recipe_def(identifier.clone(), toolkind); - recipes.insert(identifier, recipe); - } - for &toolkind in &SUPPORTED_TOOLKINDS { - for &modkind in &MODKINDS { - let (identifier, item) = make_tagexample_def(toolkind, modkind); - itemdefs.insert(identifier, item); + for &hands in &HANDS { + let (identifier, item) = make_weapon_def(toolkind, hands); + itemdefs.insert(identifier.clone(), item); + let recipe = make_recipe_def(identifier.clone(), toolkind, hands); + recipes.insert(identifier, recipe); + for &modkind in &MODKINDS { + let (identifier, item) = make_tagexample_def(toolkind, modkind, hands); + itemdefs.insert(identifier, item); + } } } (itemdefs, RawRecipeBook(recipes)) diff --git a/common/src/comp/inventory/item/tool.rs b/common/src/comp/inventory/item/tool.rs index fa64e6ede0..48d6e51717 100644 --- a/common/src/comp/inventory/item/tool.rs +++ b/common/src/comp/inventory/item/tool.rs @@ -39,6 +39,7 @@ pub enum ToolKind { } impl ToolKind { + // Changing this will break persistence of modular weapons pub fn identifier_name(&self) -> &'static str { match self { ToolKind::Sword => "sword", @@ -76,12 +77,22 @@ impl ToolKind { } } -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum Hands { One, Two, } +impl Hands { + // Changing this will break persistence of modular weapons + pub fn identifier_name(&self) -> &'static str { + match self { + Hands::One => "one-handed", + Hands::Two => "two-handed", + } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] pub struct Stats { pub equip_time_secs: f32, @@ -108,6 +119,19 @@ impl Stats { } } + pub fn oned() -> Stats { + Stats { + equip_time_secs: 1.0, + power: 1.0, + effect_power: 1.0, + speed: 1.0, + crit_chance: 1.0, + range: 1.0, + energy_efficiency: 1.0, + buff_strength: 1.0, + } + } + #[must_use] pub fn clamp_speed(mut self) -> Self { // if a tool has 0.0 speed, that panics due to being infinite duration, so @@ -205,16 +229,18 @@ impl StatKind { pub fn resolve_stats(&self, msm: &MaterialStatManifest, components: &[Item]) -> Stats { let mut stats = match self { StatKind::Direct(stats) => *stats, - StatKind::Modular => Stats::zeroed(), + StatKind::Modular => Stats::oned(), }; let mut multipliers: Vec = Vec::new(); for item in components.iter() { match item.kind() { + // Modular components directly multiply against the base stats ItemKind::ModularComponent(mc) => { let inner_stats = StatKind::Direct(mc.stats).resolve_stats(msm, item.components()); - stats += inner_stats; + stats *= inner_stats; }, + // Ingredients push multiplier to vec as the ingredient multipliers are averaged ItemKind::Ingredient { .. } => { if let Some(mult_stats) = msm.0.get(item.item_definition_id()) { multipliers.push(*mult_stats); @@ -224,7 +250,7 @@ impl StatKind { _ => (), } } - // Take the average of the material multipliers, to allow alloyed blades + // Take the average of the material multipliers if !multipliers.is_empty() { let mut average_mult = Stats::zeroed(); for stat in multipliers.iter() { diff --git a/common/src/comp/inventory/mod.rs b/common/src/comp/inventory/mod.rs index 50d6db001c..57fa613cee 100644 --- a/common/src/comp/inventory/mod.rs +++ b/common/src/comp/inventory/mod.rs @@ -2,7 +2,7 @@ use core::ops::Not; use serde::{Deserialize, Serialize}; use specs::{Component, DerefFlaggedStorage}; use specs_idvs::IdvStorage; -use std::{convert::TryFrom, mem, ops::Range}; +use std::{borrow::Cow, convert::TryFrom, mem, ops::Range}; use tracing::{debug, trace, warn}; use vek::Vec3; @@ -128,8 +128,8 @@ impl Inventory { // Quality is sorted in reverse since we want high quality items first InventorySortOrder::Quality => Ord::cmp(&b.quality(), &a.quality()), InventorySortOrder::Tag => Ord::cmp( - a.tags.first().map_or("", |tag| tag.name()), - b.tags.first().map_or("", |tag| tag.name()), + &a.tags.first().map_or(Cow::Borrowed(""), |tag| tag.name()), + &b.tags.first().map_or(Cow::Borrowed(""), |tag| tag.name()), ), }); diff --git a/voxygen/src/hud/crafting.rs b/voxygen/src/hud/crafting.rs index 5748ce0952..a2d0cd5759 100644 --- a/voxygen/src/hud/crafting.rs +++ b/voxygen/src/hud/crafting.rs @@ -28,7 +28,7 @@ use conrod_core::{ widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon, }; use i18n::Localization; -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; use strum::{EnumIter, IntoEnumIterator}; @@ -467,7 +467,7 @@ impl<'a> Widget for Crafting<'a> { }, SearchFilter::Input => recipe.inputs().any(|(input, _, _)| { let input_name = match input { - RecipeInput::Item(def) => def.name.as_str(), + RecipeInput::Item(def) => Cow::Borrowed(def.name()), RecipeInput::Tag(tag) => tag.name(), RecipeInput::TagSameItem(tag, _) => tag.name(), }