Crafting slots now properly check component recipe book to see if an input is valid.

This commit is contained in:
Sam 2022-05-06 00:22:23 -04:00
parent e9f36b9486
commit 1b85258838
3 changed files with 79 additions and 79 deletions

View File

@ -2,7 +2,7 @@ use super::{
get_quality_col,
img_ids::{Imgs, ImgsRot},
item_imgs::{animate_by_pulse, ItemImgs},
slots::{CraftSlot, SlotManager},
slots::{CraftSlot, CraftSlotInfo, SlotManager},
Show, TEXT_COLOR, TEXT_DULL_RED_COLOR, TEXT_GRAY_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
};
use crate::ui::{
@ -20,8 +20,8 @@ use common::{
modular,
modular::ModularComponent,
tool::{AbilityMap, ToolKind},
Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, MaterialKind,
MaterialStatManifest, Quality, TagExampleInfo,
Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, MaterialStatManifest, Quality,
TagExampleInfo,
},
slot::InvSlotId,
Inventory,
@ -38,8 +38,8 @@ use conrod_core::{
use hashbrown::HashMap;
use i18n::Localization;
use std::{collections::BTreeMap, sync::Arc};
use strum::{EnumIter, IntoEnumIterator};
use tracing::warn;
use vek::*;
widget_ids! {
@ -882,7 +882,7 @@ impl<'a> Widget for Crafting<'a> {
index: 0,
invslot: self.show.crafting_fields.recipe_inputs.get(&0).copied(),
requirement: match recipe_kind {
RecipeKind::ModularWeapon => |item| {
RecipeKind::ModularWeapon => |item, _, _| {
item.map_or(false, |item| {
matches!(
&*item.kind(),
@ -892,43 +892,26 @@ impl<'a> Widget for Crafting<'a> {
)
})
},
// TODO: Maybe try to figure out way to get this to work?
// Captures self and toolkind which prevents it from becoming a function
// Some(RecipeKind::Component(toolkind)) => |inv, slot| {
// inv.and_then(|inv| inv.get(slot)).map_or(false, |item| {
// self.client.component_recipe_book().iter().filter(|(key,
// _recipe)| key.toolkind == toolkind).any(|(key, _recipe)| key.material
// == item.item_definition_id()) })
// },
RecipeKind::Component(
ToolKind::Sword | ToolKind::Axe | ToolKind::Hammer,
) => |item| {
item.map_or(false, |item| {
matches!(&*item.kind(), ItemKind::Ingredient { .. })
&& item
.tags()
.contains(&ItemTag::MaterialKind(MaterialKind::Metal))
&& item
.tags()
RecipeKind::Component(_) => |item, comp_recipes, info| {
if let Some(CraftSlotInfo::Tool(toolkind)) = info {
item.map_or(false, |item| {
comp_recipes
.iter()
.any(|tag| matches!(tag, ItemTag::Material(_)))
})
.filter(|(key, _)| key.toolkind == toolkind)
.any(|(key, _)| {
Some(key.material.as_str())
== item.item_definition_id().raw()
})
})
} else {
false
}
},
RecipeKind::Component(
ToolKind::Bow | ToolKind::Staff | ToolKind::Sceptre,
) => |item| {
item.map_or(false, |item| {
matches!(&*item.kind(), ItemKind::Ingredient { .. })
&& item
.tags()
.contains(&ItemTag::MaterialKind(MaterialKind::Wood))
&& item
.tags()
.iter()
.any(|tag| matches!(tag, ItemTag::Material(_)))
})
},
RecipeKind::Component(_) | RecipeKind::Simple => |_| unreachable!(),
RecipeKind::Simple => |_, _, _| unreachable!(),
},
info: match recipe_kind {
RecipeKind::Component(toolkind) => Some(CraftSlotInfo::Tool(toolkind)),
RecipeKind::ModularWeapon | RecipeKind::Simple => None,
},
};
@ -957,7 +940,7 @@ impl<'a> Widget for Crafting<'a> {
index: 1,
invslot: self.show.crafting_fields.recipe_inputs.get(&1).copied(),
requirement: match recipe_kind {
RecipeKind::ModularWeapon => |item| {
RecipeKind::ModularWeapon => |item, _, _| {
item.map_or(false, |item| {
matches!(
&*item.kind(),
@ -967,22 +950,26 @@ impl<'a> Widget for Crafting<'a> {
)
})
},
// TODO: Maybe try to figure out way to get this to work?
// Captures self and toolkind which prevents it from becoming a function
// Some(RecipeKind::Component(toolkind)) => |inv, slot| {
// inv.and_then(|inv| inv.get(slot)).map_or(false, |item| {
// self.client.component_recipe_book().iter().filter(|(key,
// _recipe)| key.toolkind == toolkind).any(|(key, _recipe)| key.modifier
// == Some(item.item_definition_id()))
// }) },
RecipeKind::Component(_) => |item| {
item.map_or(false, |item| {
item.item_definition_id().raw().map_or(false, |id| {
id.starts_with("common.items.crafting_ing.animal_misc")
RecipeKind::Component(_) => |item, comp_recipes, info| {
if let Some(CraftSlotInfo::Tool(toolkind)) = info {
item.map_or(false, |item| {
comp_recipes
.iter()
.filter(|(key, _)| key.toolkind == toolkind)
.any(|(key, _)| {
key.modifier.as_deref()
== item.item_definition_id().raw()
})
})
})
} else {
false
}
},
RecipeKind::Simple => |_| unreachable!(),
RecipeKind::Simple => |_, _, _| unreachable!(),
},
info: match recipe_kind {
RecipeKind::Component(toolkind) => Some(CraftSlotInfo::Tool(toolkind)),
RecipeKind::ModularWeapon | RecipeKind::Simple => None,
},
};
@ -1493,7 +1480,7 @@ impl<'a> Widget for Crafting<'a> {
// Widget generation for every ingredient
for (i, (recipe_input, amount)) in ingredients.enumerate() {
let item_def = match recipe_input {
RecipeInput::Item(item_def) => Arc::clone(item_def),
RecipeInput::Item(item_def) => Some(Arc::clone(item_def)),
RecipeInput::Tag(tag) | RecipeInput::TagSameItem(tag) => self
.inventory
.slots()
@ -1508,11 +1495,9 @@ impl<'a> Widget for Crafting<'a> {
}
})
})
.unwrap_or_else(|| {
Arc::<ItemDef>::load_expect_cloned(
tag.exemplar_identifier()
.unwrap_or("common.items.weapons.empty.empty"),
)
.or_else(|| {
tag.exemplar_identifier()
.map(Arc::<ItemDef>::load_expect_cloned)
}),
RecipeInput::ListSameItem(item_defs) => self
.inventory
@ -1528,22 +1513,25 @@ impl<'a> Widget for Crafting<'a> {
}
})
})
.unwrap_or_else(|| {
item_defs
.first()
.and_then(|i| {
i.item_definition_id()
.raw()
.map(Arc::<ItemDef>::load_expect_cloned)
})
.unwrap_or_else(|| {
Arc::<ItemDef>::load_expect_cloned(
"common.items.weapons.empty.empty",
)
})
.or_else(|| {
item_defs.first().and_then(|i| {
i.item_definition_id()
.raw()
.map(Arc::<ItemDef>::load_expect_cloned)
})
}),
};
let item_def = if let Some(item_def) = item_def {
item_def
} else {
warn!(
"Failed to create example item def for recipe input {:?}",
recipe_input
);
continue;
};
// Grey color for images and text if their amount is too low to craft the
// item
let item_count_in_inventory = self.inventory.item_count(&*item_def);

View File

@ -3479,6 +3479,8 @@ impl Hud {
inventories
.get(client.entity())
.and_then(|inv| inv.get(i.slot)),
client.component_recipe_book(),
c.info,
) {
self.show
.crafting_fields

View File

@ -5,10 +5,14 @@ use super::{
util,
};
use crate::ui::slot::{self, SlotKey, SumSlot};
use common::comp::{
ability::{Ability, AbilityInput, AuxiliaryAbility},
slot::InvSlotId,
ActiveAbilities, Body, Energy, Inventory, Item, ItemKey, SkillSet,
use common::{
comp::{
ability::{Ability, AbilityInput, AuxiliaryAbility},
item::tool::ToolKind,
slot::InvSlotId,
ActiveAbilities, Body, Energy, Inventory, Item, ItemKey, SkillSet,
},
recipe::ComponentRecipeBook,
};
use conrod_core::{image, Color};
use specs::Entity as EcsEntity;
@ -239,7 +243,13 @@ impl<'a> SlotKey<AbilitiesSource<'a>, img_ids::Imgs> for AbilitySlot {
pub struct CraftSlot {
pub index: u32,
pub invslot: Option<InvSlotId>,
pub requirement: fn(Option<&Item>) -> bool,
pub requirement: fn(Option<&Item>, &ComponentRecipeBook, Option<CraftSlotInfo>) -> bool,
pub info: Option<CraftSlotInfo>,
}
#[derive(Clone, Copy, Debug)]
pub enum CraftSlotInfo {
Tool(ToolKind),
}
impl PartialEq for CraftSlot {