mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Addressed more comments on MR.
This commit is contained in:
parent
259db56ca6
commit
524845b661
@ -12,12 +12,36 @@
|
||||
(1, Asset("common.loadout.world.traveler0.rawhide")),
|
||||
]),
|
||||
active_hands: ([
|
||||
(1, "common.items.weapons.sword.bronze-0"),
|
||||
(1, "common.items.weapons.axe.bronze_axe-0"),
|
||||
(1, "common.items.weapons.hammer.bronze_hammer-0"),
|
||||
(1, "common.items.weapons.bow.bone-0"),
|
||||
(1, "common.items.weapons.staff.fiery_wishing_rod"),
|
||||
(1, "common.items.weapons.sceptre.root_green0"),
|
||||
(1, (
|
||||
tool: Sword,
|
||||
material: Bronze,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Axe,
|
||||
material: Bronze,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Hammer,
|
||||
material: Bronze,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Bow,
|
||||
material: Wood,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Staff,
|
||||
material: Wood,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Sceptre,
|
||||
material: Wood,
|
||||
hands: None,
|
||||
)),
|
||||
], None),
|
||||
)),
|
||||
items: [
|
||||
|
@ -12,12 +12,36 @@
|
||||
(1, Asset("common.loadout.world.traveler1.wool")),
|
||||
]),
|
||||
active_hands: ([
|
||||
(1, "common.items.weapons.sword.iron-0"),
|
||||
(1, "common.items.weapons.axe.iron_axe-0"),
|
||||
(1, "common.items.weapons.hammer.iron_hammer-0"),
|
||||
(1, "common.items.weapons.bow.hardwood-0"),
|
||||
(1, "common.items.weapons.staff.heated_arm"),
|
||||
(1, "common.items.weapons.sceptre.staff_nature"),
|
||||
(1, (
|
||||
tool: Sword,
|
||||
material: Iron,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Axe,
|
||||
material: Iron,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Hammer,
|
||||
material: Iron,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Bow,
|
||||
material: Bamboo,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Staff,
|
||||
material: Bamboo,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Sceptre,
|
||||
material: Bamboo,
|
||||
hands: None,
|
||||
)),
|
||||
], None),
|
||||
)),
|
||||
items: [
|
||||
|
@ -17,18 +17,66 @@
|
||||
(1, Asset("common.loadout.world.traveler2.carapace")),
|
||||
]),
|
||||
active_hands: ([
|
||||
(1, "common.items.weapons.sword.steel-0"),
|
||||
(1, "common.items.weapons.axe.steel_axe-0"),
|
||||
(1, "common.items.weapons.hammer.steel_hammer-0"),
|
||||
(1, "common.items.weapons.bow.metal-0"),
|
||||
(1, "common.items.weapons.staff.golden_khakkara"),
|
||||
(1, "common.items.weapons.sceptre.totem_green"),
|
||||
(1, "common.items.weapons.sword.cobalt-0"),
|
||||
(1, "common.items.weapons.axe.cobalt_axe-0"),
|
||||
(1, "common.items.weapons.hammer.cobalt_hammer-0"),
|
||||
(1, "common.items.weapons.bow.frostwood-0"),
|
||||
(1, "common.items.weapons.staff.aurora"),
|
||||
(1, "common.items.weapons.sceptre.loops0"),
|
||||
(1, (
|
||||
tool: Sword,
|
||||
material: Steel,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Axe,
|
||||
material: Steel,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Hammer,
|
||||
material: Steel,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Bow,
|
||||
material: Hardwood,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Staff,
|
||||
material: Hardwood,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Sceptre,
|
||||
material: Hardwood,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Sword,
|
||||
material: Cobalt,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Axe,
|
||||
material: Cobalt,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Hammer,
|
||||
material: Cobalt,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Bow,
|
||||
material: Ironwood,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Staff,
|
||||
material: Ironwood,
|
||||
hands: None,
|
||||
)),
|
||||
(1, (
|
||||
tool: Sceptre,
|
||||
material: Ironwood,
|
||||
hands: None,
|
||||
)),
|
||||
], None),
|
||||
)),
|
||||
items: [
|
||||
|
@ -17,18 +17,41 @@
|
||||
(1, Asset("common.loadout.world.traveler3.dragonscale")),
|
||||
]),
|
||||
active_hands: ([
|
||||
(2, "common.items.weapons.sword.bloodsteel-0"),
|
||||
(2, "common.items.weapons.axe.bloodsteel_axe-0"),
|
||||
(2, "common.items.weapons.hammer.runic_hammer"),
|
||||
(2, "common.items.weapons.bow.eldwood-0"),
|
||||
(2, "common.items.weapons.staff.ruby_rod"),
|
||||
(2, "common.items.weapons.sceptre.emerald"),
|
||||
(2, (
|
||||
tool: Sword,
|
||||
material: Orichalcum,
|
||||
hands: None,
|
||||
)),
|
||||
(2, (
|
||||
tool: Axe,
|
||||
material: Orichalcum,
|
||||
hands: None,
|
||||
)),
|
||||
(2, (
|
||||
tool: Hammer,
|
||||
material: Orichalcum,
|
||||
hands: None,
|
||||
)),
|
||||
(2, (
|
||||
tool: Bow,
|
||||
material: Eldwood,
|
||||
hands: None,
|
||||
)),
|
||||
(2, (
|
||||
tool: Staff,
|
||||
material: Eldwood,
|
||||
hands: None,
|
||||
)),
|
||||
(2, (
|
||||
tool: Sceptre,
|
||||
material: Eldwood,
|
||||
hands: None,
|
||||
)),
|
||||
(2, "common.items.weapons.sword.caladbolg"),
|
||||
(2, "common.items.weapons.hammer.mjolnir"),
|
||||
(2, "common.items.weapons.axe.parashu"),
|
||||
(2, "common.items.weapons.bow.sagitta"),
|
||||
(1, "common.items.weapons.staff.phoenix"),
|
||||
(1, "common.items.weapons.staff.laevateinn"),
|
||||
(2, "common.items.weapons.staff.laevateinn"),
|
||||
(1, "common.items.weapons.sceptre.root_evil"),
|
||||
(1, "common.items.weapons.sceptre.caduceus"),
|
||||
], None),
|
||||
|
@ -1864,7 +1864,7 @@
|
||||
craft_sprite: Some(CraftingBench),
|
||||
),
|
||||
"winged coronet": (
|
||||
output: ("common.items.armor.misc.head.winged_coronet", 1, false),
|
||||
output: ("common.items.armor.misc.head.winged_coronet", 1),
|
||||
inputs: [
|
||||
(Item("common.items.mineral.gem.emerald"), 1, false),
|
||||
(Item("common.items.mineral.ingot.gold"), 4, false),
|
||||
|
@ -36,11 +36,22 @@ impl<T: ItemDesc> From<&T> for ItemKey {
|
||||
ItemKey::Tool(item_definition_id.to_owned())
|
||||
}
|
||||
},
|
||||
ItemKind::ModularComponent(_) => {
|
||||
match modular::weapon_component_to_key(item_desc) {
|
||||
Ok(key) => ItemKey::ModularWeaponComponent(key),
|
||||
// TODO: Maybe use a different ItemKey?
|
||||
Err(_) => ItemKey::Tool(item_definition_id.to_owned()),
|
||||
ItemKind::ModularComponent(mod_comp) => {
|
||||
use modular::ModularComponent;
|
||||
match mod_comp {
|
||||
ModularComponent::ToolPrimaryComponent { .. } => {
|
||||
match modular::weapon_component_to_key(
|
||||
item_definition_id,
|
||||
item_desc.components(),
|
||||
) {
|
||||
Ok(key) => ItemKey::ModularWeaponComponent(key),
|
||||
// TODO: Maybe use a different ItemKey?
|
||||
Err(_) => ItemKey::Tool(item_definition_id.to_owned()),
|
||||
}
|
||||
},
|
||||
ModularComponent::ToolSecondaryComponent { .. } => {
|
||||
ItemKey::Tool(item_definition_id.to_owned())
|
||||
},
|
||||
}
|
||||
},
|
||||
ItemKind::Lantern(Lantern { kind, .. }) => ItemKey::Lantern(kind.clone()),
|
||||
|
@ -82,6 +82,10 @@ pub enum Quality {
|
||||
Debug, // Red
|
||||
}
|
||||
|
||||
impl Quality {
|
||||
pub const MIN: Self = Self::Low;
|
||||
}
|
||||
|
||||
pub trait TagExampleInfo {
|
||||
fn name(&self) -> &str;
|
||||
/// What item to show in the crafting hud if the player has nothing with the
|
||||
@ -379,20 +383,19 @@ where
|
||||
{
|
||||
serializer.serialize_str(match field {
|
||||
ItemBase::Raw(item_def) => &item_def.item_definition_id,
|
||||
// TODO: Encode this data somehow
|
||||
ItemBase::Modular(mod_base) => mod_base.pseudo_item_id(),
|
||||
})
|
||||
}
|
||||
|
||||
// Custom de-serialization for ItemDef to retrieve the ItemDef from assets using
|
||||
// its asset specifier (item_definition_id)
|
||||
// Custom de-serialization for ItemBase to retrieve the ItemBase from assets
|
||||
// using its asset specifier (item_definition_id)
|
||||
fn deserialize_item_base<'de, D>(deserializer: D) -> Result<ItemBase, D::Error>
|
||||
where
|
||||
D: de::Deserializer<'de>,
|
||||
{
|
||||
struct ItemDefStringVisitor;
|
||||
struct ItemBaseStringVisitor;
|
||||
|
||||
impl<'de> de::Visitor<'de> for ItemDefStringVisitor {
|
||||
impl<'de> de::Visitor<'de> for ItemBaseStringVisitor {
|
||||
type Value = ItemBase;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
@ -413,7 +416,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(ItemDefStringVisitor)
|
||||
deserializer.deserialize_str(ItemBaseStringVisitor)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@ -581,6 +584,7 @@ impl PartialEq for Item {
|
||||
(&self.item_base, &other.item_base)
|
||||
{
|
||||
self_def.item_definition_id == other_def.item_definition_id
|
||||
&& self.components == other.components
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -592,6 +596,15 @@ impl assets::Compound for ItemDef {
|
||||
cache: &assets::AssetCache<S>,
|
||||
specifier: &str,
|
||||
) -> Result<Self, BoxedError> {
|
||||
if specifier.starts_with("veloren.core.") {
|
||||
return Err(format!(
|
||||
"Attempted to load an asset from a specifier reserved for core veloren functions. \
|
||||
Specifier: {}",
|
||||
specifier
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let RawItemDef {
|
||||
name,
|
||||
description,
|
||||
@ -650,17 +663,10 @@ impl Item {
|
||||
|
||||
pub fn new_from_item_base(
|
||||
inner_item: ItemBase,
|
||||
input_components: &[Item],
|
||||
components: Vec<Item>,
|
||||
ability_map: &AbilityMap,
|
||||
msm: &MaterialStatManifest,
|
||||
) -> Self {
|
||||
let mut components = Vec::new();
|
||||
components.extend(
|
||||
input_components
|
||||
.iter()
|
||||
.map(|comp| comp.duplicate(ability_map, msm)),
|
||||
);
|
||||
|
||||
let item_hash = {
|
||||
let mut s = DefaultHasher::new();
|
||||
inner_item.item_definition_id().hash(&mut s);
|
||||
@ -684,8 +690,12 @@ impl Item {
|
||||
/// Creates a new instance of an `Item` from the provided asset identifier
|
||||
/// Panics if the asset does not exist.
|
||||
pub fn new_from_asset_expect(asset_specifier: &str) -> Self {
|
||||
let err_string = format!("Expected asset to exist: {}", asset_specifier);
|
||||
Item::new_from_asset(asset_specifier).expect(&err_string)
|
||||
Item::new_from_asset(asset_specifier).unwrap_or_else(|err| {
|
||||
panic!(
|
||||
"Expected asset to exist: {}, instead got error {:?}",
|
||||
asset_specifier, err
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a Vec containing one of each item that matches the provided
|
||||
@ -709,7 +719,7 @@ impl Item {
|
||||
let ability_map = AbilityMap::default();
|
||||
Ok(Item::new_from_item_base(
|
||||
inner_item,
|
||||
&[],
|
||||
Vec::new(),
|
||||
&ability_map,
|
||||
&msm,
|
||||
))
|
||||
@ -718,12 +728,17 @@ impl Item {
|
||||
/// Duplicates an item, creating an exact copy but with a new item ID
|
||||
#[must_use]
|
||||
pub fn duplicate(&self, ability_map: &AbilityMap, msm: &MaterialStatManifest) -> Self {
|
||||
let duplicated_components = self
|
||||
.components
|
||||
.iter()
|
||||
.map(|comp| comp.duplicate(ability_map, msm))
|
||||
.collect();
|
||||
let mut new_item = Item::new_from_item_base(
|
||||
match &self.item_base {
|
||||
ItemBase::Raw(item_def) => ItemBase::Raw(Arc::clone(item_def)),
|
||||
ItemBase::Modular(mod_base) => ItemBase::Modular(mod_base.duplicate()),
|
||||
ItemBase::Modular(mod_base) => ItemBase::Modular(mod_base.clone()),
|
||||
},
|
||||
&self.components,
|
||||
duplicated_components,
|
||||
ability_map,
|
||||
msm,
|
||||
);
|
||||
@ -812,9 +827,6 @@ impl Item {
|
||||
ability_map: &AbilityMap,
|
||||
msm: &MaterialStatManifest,
|
||||
) {
|
||||
// TODO: hook for typechecking (not needed atm if this is only used by DB
|
||||
// persistence, but will definitely be needed once enhancement slots are
|
||||
// added to prevent putting a sword into another sword)
|
||||
self.components.push(component);
|
||||
// adding a component changes the stats, so recalculate the ItemConfig
|
||||
self.update_item_config(ability_map, msm);
|
||||
@ -981,7 +993,7 @@ impl Item {
|
||||
pub fn create_test_item_from_kind(kind: ItemKind) -> Self {
|
||||
Self::new_from_item_base(
|
||||
ItemBase::Raw(Arc::new(ItemDef::create_test_itemdef_from_kind(kind))),
|
||||
&[],
|
||||
Vec::new(),
|
||||
&Default::default(),
|
||||
&Default::default(),
|
||||
)
|
||||
@ -1056,7 +1068,7 @@ impl Component for Item {
|
||||
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ItemDrop(pub Item);
|
||||
|
||||
impl Component for ItemDrop {
|
||||
|
@ -15,12 +15,6 @@ pub enum ModularBase {
|
||||
}
|
||||
|
||||
impl ModularBase {
|
||||
pub(super) fn duplicate(&self) -> Self {
|
||||
match self {
|
||||
ModularBase::Tool => ModularBase::Tool,
|
||||
}
|
||||
}
|
||||
|
||||
// DO NOT CHANGE. THIS IS A PERSISTENCE RELATED FUNCTION. MUST MATCH THE
|
||||
// FUNCTION BELOW.
|
||||
pub fn pseudo_item_id(&self) -> &str {
|
||||
@ -106,13 +100,16 @@ impl ModularBase {
|
||||
let material_name = comp
|
||||
.components()
|
||||
.iter()
|
||||
.find_map(|mat| match &*mat.kind() {
|
||||
ItemKind::Ingredient { descriptor, .. } => {
|
||||
Some(descriptor.to_owned())
|
||||
.find_map(|mat| match mat.kind() {
|
||||
Cow::Owned(ItemKind::Ingredient { descriptor, .. }) => {
|
||||
Some(Cow::Owned(descriptor))
|
||||
},
|
||||
Cow::Borrowed(ItemKind::Ingredient { descriptor, .. }) => {
|
||||
Some(Cow::Borrowed(descriptor.as_str()))
|
||||
},
|
||||
_ => None,
|
||||
})
|
||||
.unwrap_or_else(|| "Modular".to_owned());
|
||||
.unwrap_or_else(|| "Modular".into());
|
||||
Some(format!("{} {}", material_name, weapon_name))
|
||||
},
|
||||
_ => None,
|
||||
@ -126,7 +123,7 @@ impl ModularBase {
|
||||
pub fn compute_quality(&self, components: &[Item]) -> Quality {
|
||||
components
|
||||
.iter()
|
||||
.fold(Quality::Low, |a, b| a.max(b.quality()))
|
||||
.fold(Quality::MIN, |a, b| a.max(b.quality()))
|
||||
}
|
||||
|
||||
pub fn ability_spec(&self, components: &[Item]) -> Option<Cow<AbilitySpec>> {
|
||||
@ -165,26 +162,15 @@ impl ModularComponent {
|
||||
) -> Option<tool::Stats> {
|
||||
match self {
|
||||
Self::ToolPrimaryComponent { stats, .. } => {
|
||||
let mut material_multipliers = Vec::new();
|
||||
for component in components.iter() {
|
||||
if let Some(tool_stats) = msm.0.get(component.item_definition_id()) {
|
||||
material_multipliers.push(*tool_stats);
|
||||
}
|
||||
}
|
||||
let average_material_mult = components
|
||||
.iter()
|
||||
.filter_map(|comp| msm.0.get(comp.item_definition_id()).copied().zip(Some(1)))
|
||||
.reduce(|(stats_a, count_a), (stats_b, count_b)| {
|
||||
(stats_a + stats_b, count_a + count_b)
|
||||
})
|
||||
.map_or_else(tool::Stats::one, |(stats_sum, count)| stats_sum / count);
|
||||
|
||||
// Take the average of the material multipliers
|
||||
let material_mult = if !material_multipliers.is_empty() {
|
||||
let mut average_mult = tool::Stats::zero();
|
||||
for stat in material_multipliers.iter() {
|
||||
average_mult += *stat;
|
||||
}
|
||||
average_mult /= material_multipliers.len();
|
||||
average_mult
|
||||
} else {
|
||||
tool::Stats::one()
|
||||
};
|
||||
|
||||
Some(*stats * material_mult)
|
||||
Some(*stats * average_material_mult)
|
||||
},
|
||||
Self::ToolSecondaryComponent { stats, .. } => Some(*stats),
|
||||
}
|
||||
@ -208,8 +194,8 @@ lazy_static! {
|
||||
let mut component_pool = HashMap::new();
|
||||
|
||||
// Load recipe book (done to check that material is valid for a particular component)
|
||||
let recipe::RawRecipeBook(recipes) =
|
||||
recipe::RawRecipeBook::load_expect_cloned("common.recipe_book");
|
||||
let recipe_book = recipe::RawRecipeBook::load_expect("common.recipe_book");
|
||||
let recipes = &recipe_book.read().0;
|
||||
|
||||
const ASSET_PREFIX: &str = "common.items.crafting_ing.modular.primary";
|
||||
|
||||
@ -309,59 +295,54 @@ pub fn random_weapon(
|
||||
let material = Item::new_from_asset_expect(material_id);
|
||||
let primary_components = PRIMARY_COMPONENT_POOL
|
||||
.get(&(tool, material_id.to_owned()))
|
||||
.map_or(Vec::new(), |components| {
|
||||
components
|
||||
.iter()
|
||||
.filter(|(_def, hand)| match (hand_restriction, hand) {
|
||||
(Some(restriction), Some(hand)) => restriction == *hand,
|
||||
(None, _) | (_, None) => true,
|
||||
})
|
||||
.map(|entry| (1.0, entry))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|(_def, hand)| match (hand_restriction, hand) {
|
||||
(Some(restriction), Some(hand)) => restriction == *hand,
|
||||
(None, _) | (_, None) => true,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let (primary_component, hand_restriction) = {
|
||||
let (def, hand) = primary_components
|
||||
.choose(&mut rng)
|
||||
.ok_or(ModularWeaponCreationError::PrimaryComponentNotFound)?
|
||||
.1;
|
||||
.ok_or(ModularWeaponCreationError::PrimaryComponentNotFound)?;
|
||||
let comp = Item::new_from_item_base(
|
||||
ItemBase::Raw(Arc::clone(def)),
|
||||
&[material],
|
||||
vec![material],
|
||||
&ability_map,
|
||||
&msm,
|
||||
);
|
||||
(comp, hand_restriction.or(*hand))
|
||||
};
|
||||
|
||||
let secondary_components =
|
||||
SECONDARY_COMPONENT_POOL
|
||||
.get(&tool)
|
||||
.map_or(Vec::new(), |components| {
|
||||
components
|
||||
.iter()
|
||||
.filter(|(_def, hand)| match (hand_restriction, hand) {
|
||||
(Some(restriction), Some(hand)) => restriction == *hand,
|
||||
(None, _) | (_, None) => true,
|
||||
})
|
||||
.map(|entry| (1.0, entry))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let secondary_components = SECONDARY_COMPONENT_POOL
|
||||
.get(&tool)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.filter(|(_def, hand)| match (hand_restriction, hand) {
|
||||
(Some(restriction), Some(hand)) => restriction == *hand,
|
||||
(None, _) | (_, None) => true,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let secondary_component = {
|
||||
let def = &secondary_components
|
||||
.choose(&mut rng)
|
||||
.ok_or(ModularWeaponCreationError::SecondaryComponentNotFound)?
|
||||
.1
|
||||
.0;
|
||||
Item::new_from_item_base(ItemBase::Raw(Arc::clone(def)), &[], &ability_map, &msm)
|
||||
Item::new_from_item_base(
|
||||
ItemBase::Raw(Arc::clone(def)),
|
||||
Vec::new(),
|
||||
&ability_map,
|
||||
&msm,
|
||||
)
|
||||
};
|
||||
|
||||
// Create modular weapon
|
||||
let components = vec![primary_component, secondary_component];
|
||||
Ok(Item::new_from_item_base(
|
||||
ItemBase::Modular(ModularBase::Tool),
|
||||
&components,
|
||||
vec![primary_component, secondary_component],
|
||||
&ability_map,
|
||||
&msm,
|
||||
))
|
||||
@ -407,29 +388,17 @@ pub type ModularWeaponComponentKey = (String, String);
|
||||
|
||||
pub enum ModularWeaponComponentKeyError {
|
||||
MaterialNotFound,
|
||||
NotMainComponent,
|
||||
}
|
||||
|
||||
pub fn weapon_component_to_key(
|
||||
mod_weap_comp: &dyn ItemDesc,
|
||||
item_def_id: &str,
|
||||
components: &[Item],
|
||||
) -> Result<ModularWeaponComponentKey, ModularWeaponComponentKeyError> {
|
||||
match if let ItemKind::ModularComponent(ModularComponent::ToolPrimaryComponent { .. }) =
|
||||
&*mod_weap_comp.kind()
|
||||
{
|
||||
let component_id = mod_weap_comp.item_definition_id().to_owned();
|
||||
let material_id = mod_weap_comp
|
||||
.components()
|
||||
.iter()
|
||||
.find_map(|mat| match &*mat.kind() {
|
||||
ItemKind::Ingredient { .. } => Some(mat.item_definition_id().to_owned()),
|
||||
_ => None,
|
||||
});
|
||||
Some((component_id, material_id))
|
||||
} else {
|
||||
None
|
||||
} {
|
||||
Some((component_id, Some(material_id))) => Ok((component_id, material_id)),
|
||||
Some((_component_id, None)) => Err(ModularWeaponComponentKeyError::MaterialNotFound),
|
||||
None => Err(ModularWeaponComponentKeyError::NotMainComponent),
|
||||
match components.iter().find_map(|mat| match &*mat.kind() {
|
||||
ItemKind::Ingredient { .. } => Some(mat.item_definition_id().to_owned()),
|
||||
_ => None,
|
||||
}) {
|
||||
Some(material_id) => Ok((item_def_id.to_owned(), material_id)),
|
||||
None => Err(ModularWeaponComponentKeyError::MaterialNotFound),
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
ops::{AddAssign, DivAssign, Mul, MulAssign, Sub},
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
@ -139,28 +139,39 @@ impl Asset for Stats {
|
||||
const EXTENSION: &'static str = "ron";
|
||||
}
|
||||
|
||||
impl AddAssign<Stats> for Stats {
|
||||
fn add_assign(&mut self, other: Stats) {
|
||||
self.equip_time_secs += other.equip_time_secs;
|
||||
self.power += other.power;
|
||||
self.effect_power += other.effect_power;
|
||||
self.speed += other.speed;
|
||||
self.crit_chance += other.crit_chance;
|
||||
self.range += other.range;
|
||||
self.energy_efficiency += other.energy_efficiency;
|
||||
self.buff_strength += other.buff_strength;
|
||||
impl Add<Stats> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self {
|
||||
equip_time_secs: self.equip_time_secs + other.equip_time_secs,
|
||||
power: self.power + other.power,
|
||||
effect_power: self.effect_power + other.effect_power,
|
||||
speed: self.speed + other.speed,
|
||||
crit_chance: self.crit_chance + other.crit_chance,
|
||||
range: self.range + other.range,
|
||||
energy_efficiency: self.energy_efficiency + other.energy_efficiency,
|
||||
buff_strength: self.buff_strength + other.buff_strength,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl MulAssign<Stats> for Stats {
|
||||
fn mul_assign(&mut self, other: Stats) {
|
||||
self.equip_time_secs *= other.equip_time_secs;
|
||||
self.power *= other.power;
|
||||
self.effect_power *= other.effect_power;
|
||||
self.speed *= other.speed;
|
||||
self.crit_chance *= other.crit_chance;
|
||||
self.range *= other.range;
|
||||
self.energy_efficiency *= other.energy_efficiency;
|
||||
self.buff_strength *= other.buff_strength;
|
||||
impl AddAssign<Stats> for Stats {
|
||||
fn add_assign(&mut self, other: Stats) { *self = *self + other; }
|
||||
}
|
||||
impl Sub<Stats> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self::Output {
|
||||
Self {
|
||||
equip_time_secs: self.equip_time_secs - other.equip_time_secs,
|
||||
power: self.power - other.power,
|
||||
effect_power: self.effect_power - other.effect_power,
|
||||
speed: self.speed - other.speed,
|
||||
crit_chance: self.crit_chance - other.crit_chance,
|
||||
range: self.range - other.range,
|
||||
energy_efficiency: self.range - other.energy_efficiency,
|
||||
buff_strength: self.buff_strength - other.buff_strength,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Mul<Stats> for Stats {
|
||||
@ -179,35 +190,29 @@ impl Mul<Stats> for Stats {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl DivAssign<usize> for Stats {
|
||||
fn div_assign(&mut self, scalar: usize) {
|
||||
self.equip_time_secs /= scalar as f32;
|
||||
self.power /= scalar as f32;
|
||||
self.effect_power /= scalar as f32;
|
||||
self.speed /= scalar as f32;
|
||||
self.crit_chance /= scalar as f32;
|
||||
self.range /= scalar as f32;
|
||||
self.energy_efficiency /= scalar as f32;
|
||||
self.buff_strength /= scalar as f32;
|
||||
}
|
||||
impl MulAssign<Stats> for Stats {
|
||||
fn mul_assign(&mut self, other: Stats) { *self = *self * other; }
|
||||
}
|
||||
|
||||
impl Sub<Stats> for Stats {
|
||||
impl Div<usize> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, other: Self) -> Self::Output {
|
||||
fn div(self, scalar: usize) -> Self {
|
||||
let scalar = scalar as f32;
|
||||
Self {
|
||||
equip_time_secs: self.equip_time_secs - other.equip_time_secs,
|
||||
power: self.power - other.power,
|
||||
effect_power: self.effect_power - other.effect_power,
|
||||
speed: self.speed - other.speed,
|
||||
crit_chance: self.crit_chance - other.crit_chance,
|
||||
range: self.range - other.range,
|
||||
energy_efficiency: self.range - other.energy_efficiency,
|
||||
buff_strength: self.buff_strength - other.buff_strength,
|
||||
equip_time_secs: self.equip_time_secs / scalar,
|
||||
power: self.power / scalar,
|
||||
effect_power: self.effect_power / scalar,
|
||||
speed: self.speed / scalar,
|
||||
crit_chance: self.crit_chance / scalar,
|
||||
range: self.range / scalar,
|
||||
energy_efficiency: self.energy_efficiency / scalar,
|
||||
buff_strength: self.buff_strength / scalar,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl DivAssign<usize> for Stats {
|
||||
fn div_assign(&mut self, scalar: usize) { *self = *self / scalar; }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct MaterialStatManifest(pub HashMap<String, Stats>);
|
||||
@ -262,11 +267,9 @@ impl Tool {
|
||||
|
||||
pub fn base_effect_power(&self) -> f32 { self.stats.effect_power }
|
||||
|
||||
pub fn base_speed(&self) -> f32 {
|
||||
// Has floor to prevent infinite durations being created later down due to a
|
||||
// divide by zero
|
||||
self.stats.speed.max(0.1)
|
||||
}
|
||||
/// Has floor to prevent infinite durations being created later down due to
|
||||
/// a divide by zero
|
||||
pub fn base_speed(&self) -> f32 { self.stats.speed.max(0.1) }
|
||||
|
||||
pub fn base_crit_chance(&self) -> f32 { self.stats.crit_chance }
|
||||
|
||||
|
@ -205,7 +205,7 @@ impl Loadout {
|
||||
|
||||
/// Returns all items currently equipped that an item of the given ItemKind
|
||||
/// could replace
|
||||
pub(super) fn equipped_items_of_kind<'a>(
|
||||
pub(super) fn equipped_items_replaceable_by<'a>(
|
||||
&'a self,
|
||||
item_kind: &'a ItemKind,
|
||||
) -> impl Iterator<Item = &'a Item> {
|
||||
|
@ -72,6 +72,13 @@ impl ItemSpec {
|
||||
};
|
||||
Ok(item)
|
||||
},
|
||||
ItemSpec::ModularWeapon {
|
||||
tool,
|
||||
material,
|
||||
hands,
|
||||
} => {
|
||||
item::modular::random_weapon(*tool, *material, *hands)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,20 +164,6 @@ impl Hands {
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
ItemSpec::ModularWeapon {
|
||||
tool,
|
||||
material,
|
||||
hands,
|
||||
} => {
|
||||
let item = item::modular::random_weapon(*tool, *material, *hands)
|
||||
.expect("Invalid modular weapon");
|
||||
if !equip_slot.can_hold(&*item.kind()) {
|
||||
panic!(
|
||||
"Tried to place {:?} handed {:?} {:?} into {:?}",
|
||||
hands, material, tool, equip_slot
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -775,11 +775,11 @@ impl Inventory {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn equipped_items_of_kind<'a>(
|
||||
pub fn equipped_items_replaceable_by<'a>(
|
||||
&'a self,
|
||||
item_kind: &'a ItemKind,
|
||||
) -> impl Iterator<Item = &'a Item> {
|
||||
self.loadout.equipped_items_of_kind(item_kind)
|
||||
self.loadout.equipped_items_replaceable_by(item_kind)
|
||||
}
|
||||
|
||||
pub fn swap_equipped_weapons(&mut self) { self.loadout.swap_equipped_weapons() }
|
||||
|
@ -24,7 +24,7 @@ pub(super) fn get_test_bag(slots: u16) -> Item {
|
||||
|
||||
Item::new_from_item_base(
|
||||
ItemBase::Raw(Arc::new(item_def)),
|
||||
&[],
|
||||
Vec::new(),
|
||||
&AbilityMap::default(),
|
||||
&MaterialStatManifest::default(),
|
||||
)
|
||||
|
@ -130,7 +130,20 @@ impl<T: AsRef<str>> LootSpec<T> {
|
||||
tool,
|
||||
material,
|
||||
hands,
|
||||
} => item::modular::random_weapon(*tool, *material, *hands).ok(),
|
||||
} => item::modular::random_weapon(*tool, *material, *hands).map_or_else(
|
||||
|e| {
|
||||
warn!(
|
||||
?e,
|
||||
"error while creating modular weapon. Toolkind: {:?}, Material: {:?}, \
|
||||
Hands: {:?}",
|
||||
tool,
|
||||
material,
|
||||
hands
|
||||
);
|
||||
None
|
||||
},
|
||||
Option::Some,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use crate::{
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum RecipeInput {
|
||||
@ -127,7 +127,7 @@ impl Recipe {
|
||||
|
||||
let crafted_item = Item::new_from_item_base(
|
||||
ItemBase::Raw(Arc::clone(item_def)),
|
||||
&components,
|
||||
components,
|
||||
ability_map,
|
||||
msm,
|
||||
);
|
||||
@ -247,15 +247,12 @@ pub fn modular_weapon(
|
||||
) -> Result<Item, ModularWeaponError> {
|
||||
use modular::ModularComponent;
|
||||
// Closure to get inner modular component info from item in a given slot
|
||||
fn unwrap_modular(inv: &Inventory, slot: InvSlotId) -> Option<ModularComponent> {
|
||||
if let Some(ItemKind::ModularComponent(mod_comp)) =
|
||||
inv.get(slot).map(|item| item.kind()).as_deref()
|
||||
{
|
||||
// TODO: Remove
|
||||
Some(mod_comp.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
fn unwrap_modular(inv: &Inventory, slot: InvSlotId) -> Option<Cow<ModularComponent>> {
|
||||
inv.get(slot).and_then(|item| match item.kind() {
|
||||
Cow::Owned(ItemKind::ModularComponent(mod_comp)) => Some(Cow::Owned(mod_comp)),
|
||||
Cow::Borrowed(ItemKind::ModularComponent(mod_comp)) => Some(Cow::Borrowed(mod_comp)),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
// Checks if both components are comptabile, and if so returns the toolkind to
|
||||
@ -277,13 +274,12 @@ pub fn modular_weapon(
|
||||
hand_restriction: hands_b,
|
||||
..
|
||||
},
|
||||
) = (primary_component, secondary_component)
|
||||
) = (&*primary_component, &*secondary_component)
|
||||
{
|
||||
// Checks that both components are of the same tool kind
|
||||
if tool_a == tool_b {
|
||||
// Checks that if both components have a hand restriction, they are the same
|
||||
let hands_check =
|
||||
hands_a.map_or(true, |hands| hands_b.map_or(true, |hands2| hands == hands2));
|
||||
let hands_check = hands_a.zip(*hands_b).map_or(true, |(a, b)| a == b);
|
||||
if hands_check {
|
||||
Ok(())
|
||||
} else {
|
||||
@ -310,10 +306,9 @@ pub fn modular_weapon(
|
||||
.expect("Expected component to exist");
|
||||
|
||||
// Create modular weapon
|
||||
let components = vec![primary_component, secondary_component];
|
||||
Ok(Item::new_from_item_base(
|
||||
ItemBase::Modular(modular::ModularBase::Tool),
|
||||
&components,
|
||||
vec![primary_component, secondary_component],
|
||||
ability_map,
|
||||
msm,
|
||||
))
|
||||
|
@ -942,7 +942,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
}
|
||||
})
|
||||
})
|
||||
.unwrap_or({
|
||||
.unwrap_or_else(|| {
|
||||
item_defs
|
||||
.first()
|
||||
.map(|i| i.item_definition_id())
|
||||
|
@ -464,7 +464,7 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
|
||||
let item_kind = &*item.kind();
|
||||
|
||||
let equip_slot = inventory.equipped_items_of_kind(item_kind);
|
||||
let equip_slot = inventory.equipped_items_replaceable_by(item_kind);
|
||||
|
||||
let (title, desc) = (item.name().to_string(), item.description().to_string());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user