mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added a repair equipped and a repair all button. Cleaned up some hacks that used to exist.
This commit is contained in:
parent
658de93c59
commit
ca879173be
@ -3,6 +3,9 @@ hud-crafting-recipes = Recipes
|
||||
hud-crafting-ingredients = Ingredients:
|
||||
hud-crafting-craft = Craft
|
||||
hud-crafting-craft_all = Craft All
|
||||
hud-crafting-repair = Repair
|
||||
hud-crafting-repair_equipped = Repair Equipped
|
||||
hud-crafting-repair_all = Repair All
|
||||
hud-crafting-tool_cata = Requires:
|
||||
hud-crafting-req_crafting_station = Requires:
|
||||
hud-crafting-anvil = Anvil
|
||||
|
@ -1222,10 +1222,13 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_durability(&mut self) {
|
||||
pub fn apply_durability(&mut self, ability_map: &AbilityMap, msm: &MaterialStatManifest) {
|
||||
if let Some(durability) = &mut self.durability {
|
||||
*durability += 1;
|
||||
}
|
||||
// Update item state after applying durability because stats have potential to
|
||||
// change from different durability
|
||||
self.update_item_state(ability_map, msm);
|
||||
}
|
||||
|
||||
pub fn persistence_durability(&self) -> Option<NonZeroU32> {
|
||||
@ -1244,7 +1247,12 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_durability(&mut self) { self.durability = self.durability.map(|_| 0); }
|
||||
pub fn reset_durability(&mut self, ability_map: &AbilityMap, msm: &MaterialStatManifest) {
|
||||
self.durability = self.durability.map(|_| 0);
|
||||
// Update item state after applying durability because stats have potential to
|
||||
// change from different durability
|
||||
self.update_item_state(ability_map, msm);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn create_test_item_from_kind(kind: ItemKind) -> Self {
|
||||
|
@ -311,6 +311,12 @@ impl Loadout {
|
||||
self.slots.iter().filter_map(|x| x.slot.as_ref())
|
||||
}
|
||||
|
||||
pub(super) fn items_with_slot(&self) -> impl Iterator<Item = (EquipSlot, &Item)> {
|
||||
self.slots
|
||||
.iter()
|
||||
.filter_map(|x| x.slot.as_ref().map(|i| (x.equip_slot, i)))
|
||||
}
|
||||
|
||||
/// Checks that a slot can hold a given item
|
||||
pub(super) fn slot_can_hold(
|
||||
&self,
|
||||
@ -428,23 +434,25 @@ impl Loadout {
|
||||
.filter(|slot| slot.slot.as_ref().map_or(false, |i| i.has_durability()))
|
||||
.for_each(|slot| {
|
||||
if let Some(item) = &mut slot.slot {
|
||||
item.apply_durability();
|
||||
// Update item state after applying durability because stats have potential to
|
||||
// change from different durability
|
||||
item.update_item_state(ability_map, msm);
|
||||
item.apply_durability(ability_map, msm);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Resets durability of item in specified slot
|
||||
pub(super) fn repair_item_at_slot(&mut self, equip_slot: EquipSlot) {
|
||||
pub(super) fn repair_item_at_slot(
|
||||
&mut self,
|
||||
equip_slot: EquipSlot,
|
||||
ability_map: &item::tool::AbilityMap,
|
||||
msm: &item::MaterialStatManifest,
|
||||
) {
|
||||
if let Some(item) = self
|
||||
.slots
|
||||
.iter_mut()
|
||||
.find(|slot| slot.equip_slot == equip_slot)
|
||||
.and_then(|slot| slot.slot.as_mut())
|
||||
{
|
||||
item.reset_durability();
|
||||
item.reset_durability(ability_map, msm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -605,6 +605,10 @@ impl Inventory {
|
||||
|
||||
pub fn equipped_items(&self) -> impl Iterator<Item = &Item> { self.loadout.items() }
|
||||
|
||||
pub fn equipped_items_with_slot(&self) -> impl Iterator<Item = (EquipSlot, &Item)> {
|
||||
self.loadout.items_with_slot()
|
||||
}
|
||||
|
||||
/// Replaces the loadout item (if any) in the given EquipSlot with the
|
||||
/// provided item, returning the item that was previously in the slot.
|
||||
pub fn replace_loadout_item(
|
||||
@ -889,15 +893,21 @@ impl Inventory {
|
||||
}
|
||||
|
||||
/// Resets durability of item in specified slot
|
||||
pub fn repair_item_at_slot(&mut self, slot: Slot) {
|
||||
pub fn repair_item_at_slot(
|
||||
&mut self,
|
||||
slot: Slot,
|
||||
ability_map: &item::tool::AbilityMap,
|
||||
msm: &item::MaterialStatManifest,
|
||||
) {
|
||||
match slot {
|
||||
Slot::Inventory(invslot) => {
|
||||
if let Some(Some(item)) = self.slot_mut(invslot).map(Option::as_mut) {
|
||||
item.reset_durability();
|
||||
item.reset_durability(ability_map, msm);
|
||||
}
|
||||
},
|
||||
Slot::Equip(equip_slot) => {
|
||||
self.loadout.repair_item_at_slot(equip_slot);
|
||||
self.loadout
|
||||
.repair_item_at_slot(equip_slot, ability_map, msm);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1048,7 +1048,7 @@ impl RepairRecipeBook {
|
||||
}
|
||||
}
|
||||
|
||||
inv.repair_item_at_slot(item);
|
||||
inv.repair_item_at_slot(item, ability_map, msm);
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
|
@ -86,6 +86,7 @@ widget_ids! {
|
||||
dismantle_title,
|
||||
dismantle_img,
|
||||
dismantle_txt,
|
||||
repair_buttons[],
|
||||
craft_slots[],
|
||||
modular_art,
|
||||
modular_desc_txt,
|
||||
@ -124,7 +125,7 @@ pub struct CraftingShow {
|
||||
pub crafting_search_key: Option<String>,
|
||||
pub craft_sprite: Option<(Vec3<i32>, SpriteKind)>,
|
||||
pub salvage: bool,
|
||||
pub repair: bool,
|
||||
pub initialize_repair: bool,
|
||||
// TODO: Maybe try to do something that doesn't need to allocate?
|
||||
pub recipe_inputs: HashMap<u32, Slot>,
|
||||
}
|
||||
@ -136,7 +137,7 @@ impl Default for CraftingShow {
|
||||
crafting_search_key: None,
|
||||
craft_sprite: None,
|
||||
salvage: false,
|
||||
repair: false,
|
||||
initialize_repair: false,
|
||||
recipe_inputs: HashMap::new(),
|
||||
}
|
||||
}
|
||||
@ -212,7 +213,6 @@ pub enum CraftingTab {
|
||||
Utility,
|
||||
Glider,
|
||||
Dismantle,
|
||||
Repair,
|
||||
}
|
||||
|
||||
impl CraftingTab {
|
||||
@ -229,7 +229,6 @@ impl CraftingTab {
|
||||
CraftingTab::Bag => "hud-crafting-tabs-bag",
|
||||
CraftingTab::ProcessedMaterial => "hud-crafting-tabs-processed_material",
|
||||
CraftingTab::Dismantle => "hud-crafting-tabs-dismantle",
|
||||
CraftingTab::Repair => "hud-crafting-tabs-repair",
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,14 +246,13 @@ impl CraftingTab {
|
||||
CraftingTab::ProcessedMaterial => imgs.icon_processed_material,
|
||||
// These tabs are never shown, so using not found is fine
|
||||
CraftingTab::Dismantle => imgs.not_found,
|
||||
CraftingTab::Repair => imgs.not_found,
|
||||
}
|
||||
}
|
||||
|
||||
fn satisfies(self, recipe: &Recipe) -> bool {
|
||||
let (item, _count) = &recipe.output;
|
||||
match self {
|
||||
CraftingTab::All | CraftingTab::Dismantle | CraftingTab::Repair => true,
|
||||
CraftingTab::All | CraftingTab::Dismantle => true,
|
||||
CraftingTab::Food => item.tags().contains(&ItemTag::Food),
|
||||
CraftingTab::Armor => match &*item.kind() {
|
||||
ItemKind::Armor(_) => !item.tags().contains(&ItemTag::Bag),
|
||||
@ -325,6 +323,16 @@ impl<'a> Widget for Crafting<'a> {
|
||||
|
||||
let mut events = Vec::new();
|
||||
|
||||
// Handle any initialization
|
||||
// TODO: Replace with struct instead of making assorted booleans once there is
|
||||
// more than 1 field.
|
||||
if self.show.crafting_fields.initialize_repair {
|
||||
state.update(|s| {
|
||||
s.selected_recipe = Some(String::from("veloren.core.pseudo_recipe.repair"))
|
||||
});
|
||||
}
|
||||
self.show.crafting_fields.initialize_repair = false;
|
||||
|
||||
// Tooltips
|
||||
let item_tooltip = ItemTooltip::new(
|
||||
{
|
||||
@ -570,7 +578,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
);
|
||||
pseudo_entries.insert(
|
||||
String::from("veloren.core.pseudo_recipe.repair"),
|
||||
(&repair_recipe, "Repair Equipment", CraftingTab::Repair),
|
||||
(&repair_recipe, "Repair Equipment", CraftingTab::All),
|
||||
);
|
||||
pseudo_entries
|
||||
};
|
||||
@ -1356,6 +1364,13 @@ impl<'a> Widget for Crafting<'a> {
|
||||
s.ids.craft_slots.resize(1, &mut ui.widget_id_generator());
|
||||
});
|
||||
}
|
||||
if state.ids.repair_buttons.len() < 2 {
|
||||
state.update(|s| {
|
||||
s.ids
|
||||
.repair_buttons
|
||||
.resize(2, &mut ui.widget_id_generator());
|
||||
});
|
||||
}
|
||||
|
||||
// Slot for item to be repaired
|
||||
let repair_slot = CraftSlot {
|
||||
@ -1367,7 +1382,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
|
||||
let repair_slot_widget = slot_maker
|
||||
.fabricate(repair_slot, [40.0; 2])
|
||||
.mid_top_with_margin_on(state.ids.align_ing, 20.0)
|
||||
.top_left_with_margins_on(state.ids.align_ing, 20.0, 40.0)
|
||||
.parent(state.ids.align_ing);
|
||||
|
||||
if let Some(item) = repair_slot.item(self.inventory) {
|
||||
@ -1395,16 +1410,85 @@ impl<'a> Widget for Crafting<'a> {
|
||||
.set(state.ids.craft_slots[0], ui);
|
||||
}
|
||||
|
||||
let can_perform = repair_slot.item(self.inventory).map_or(false, |item| {
|
||||
self.client.repair_recipe_book().repair_recipe(item).map_or(
|
||||
false,
|
||||
|recipe| {
|
||||
recipe
|
||||
.inventory_contains_ingredients(item, self.inventory)
|
||||
.is_ok()
|
||||
},
|
||||
let can_repair = |item: &Item| {
|
||||
// Check that item needs to be repaired, and that inventory has sufficient
|
||||
// materials to repair
|
||||
item.durability().map_or(false, |d| d > 0)
|
||||
&& self.client.repair_recipe_book().repair_recipe(item).map_or(
|
||||
false,
|
||||
|recipe| {
|
||||
recipe
|
||||
.inventory_contains_ingredients(item, self.inventory)
|
||||
.is_ok()
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
// Repair equipped button
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(105.0, 25.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label(
|
||||
&self
|
||||
.localized_strings
|
||||
.get_msg("hud-crafting-repair_equipped"),
|
||||
)
|
||||
});
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(self.fonts.cyri.scale(12))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.image_color(TEXT_COLOR)
|
||||
.top_right_with_margins_on(state.ids.align_ing, 20.0, 20.0)
|
||||
.set(state.ids.repair_buttons[0], ui)
|
||||
.was_clicked()
|
||||
{
|
||||
self.inventory
|
||||
.equipped_items_with_slot()
|
||||
.filter(|(_, item)| can_repair(item))
|
||||
.for_each(|(slot, _)| {
|
||||
events.push(Event::RepairItem {
|
||||
slot: Slot::Equip(slot),
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
// Repair all button
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(105.0, 25.0)
|
||||
.hover_image(self.imgs.button_hover)
|
||||
.press_image(self.imgs.button_press)
|
||||
.label(&self.localized_strings.get_msg("hud-crafting-repair_all"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.label_color(TEXT_COLOR)
|
||||
.label_font_size(self.fonts.cyri.scale(12))
|
||||
.label_font_id(self.fonts.cyri.conrod_id)
|
||||
.image_color(TEXT_COLOR)
|
||||
.mid_bottom_with_margin_on(state.ids.repair_buttons[0], -45.0)
|
||||
.set(state.ids.repair_buttons[1], ui)
|
||||
.was_clicked()
|
||||
{
|
||||
self.inventory
|
||||
.equipped_items_with_slot()
|
||||
.filter(|(_, item)| can_repair(item))
|
||||
.for_each(|(slot, _)| {
|
||||
events.push(Event::RepairItem {
|
||||
slot: Slot::Equip(slot),
|
||||
});
|
||||
});
|
||||
self.inventory
|
||||
.slots_with_id()
|
||||
.filter(|(_, item)| item.as_ref().map_or(false, |i| can_repair(i)))
|
||||
.for_each(|(slot, _)| {
|
||||
events.push(Event::RepairItem {
|
||||
slot: Slot::Inventory(slot),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let can_perform = repair_slot
|
||||
.item(self.inventory)
|
||||
.map_or(false, |item| can_repair(item));
|
||||
|
||||
(repair_slot.slot, None, can_perform)
|
||||
},
|
||||
@ -1413,17 +1497,20 @@ impl<'a> Widget for Crafting<'a> {
|
||||
// Craft button
|
||||
if Button::image(self.imgs.button)
|
||||
.w_h(105.0, 25.0)
|
||||
.hover_image(if can_perform {
|
||||
self.imgs.button_hover
|
||||
} else {
|
||||
self.imgs.button
|
||||
.hover_image(
|
||||
can_perform
|
||||
.then_some(self.imgs.button_hover)
|
||||
.unwrap_or(self.imgs.button),
|
||||
)
|
||||
.press_image(
|
||||
can_perform
|
||||
.then_some(self.imgs.button_press)
|
||||
.unwrap_or(self.imgs.button),
|
||||
)
|
||||
.label(&match recipe_kind {
|
||||
RecipeKind::Repair => self.localized_strings.get_msg("hud-crafting-repair"),
|
||||
_ => self.localized_strings.get_msg("hud-crafting-craft"),
|
||||
})
|
||||
.press_image(if can_perform {
|
||||
self.imgs.button_press
|
||||
} else {
|
||||
self.imgs.button
|
||||
})
|
||||
.label(&self.localized_strings.get_msg("hud-crafting-craft"))
|
||||
.label_y(conrod_core::position::Relative::Scalar(1.0))
|
||||
.label_color(if can_perform {
|
||||
TEXT_COLOR
|
||||
|
@ -922,7 +922,6 @@ impl Show {
|
||||
self.bag = open;
|
||||
self.map = false;
|
||||
self.crafting_fields.salvage = false;
|
||||
self.crafting_fields.repair = false;
|
||||
|
||||
if !open {
|
||||
self.crafting = false;
|
||||
@ -947,7 +946,6 @@ impl Show {
|
||||
self.bag = false;
|
||||
self.crafting = false;
|
||||
self.crafting_fields.salvage = false;
|
||||
self.crafting_fields.repair = false;
|
||||
self.social = false;
|
||||
self.quest = false;
|
||||
self.diary = false;
|
||||
@ -984,7 +982,6 @@ impl Show {
|
||||
}
|
||||
self.crafting = open;
|
||||
self.crafting_fields.salvage = false;
|
||||
self.crafting_fields.repair = false;
|
||||
self.crafting_fields.recipe_inputs = HashMap::new();
|
||||
self.bag = open;
|
||||
self.map = false;
|
||||
@ -1004,10 +1001,10 @@ impl Show {
|
||||
self.crafting_fields.craft_sprite,
|
||||
Some((_, SpriteKind::DismantlingBench))
|
||||
) && matches!(tab, CraftingTab::Dismantle);
|
||||
self.crafting_fields.repair = matches!(
|
||||
self.crafting_fields.initialize_repair = matches!(
|
||||
self.crafting_fields.craft_sprite,
|
||||
Some((_, SpriteKind::RepairBench))
|
||||
) && matches!(tab, CraftingTab::Repair);
|
||||
);
|
||||
}
|
||||
|
||||
fn diary(&mut self, open: bool) {
|
||||
@ -1016,7 +1013,6 @@ impl Show {
|
||||
self.quest = false;
|
||||
self.crafting = false;
|
||||
self.crafting_fields.salvage = false;
|
||||
self.crafting_fields.repair = false;
|
||||
self.bag = false;
|
||||
self.map = false;
|
||||
self.diary_fields = diary::DiaryShow::default();
|
||||
@ -1037,7 +1033,6 @@ impl Show {
|
||||
self.quest = false;
|
||||
self.crafting = false;
|
||||
self.crafting_fields.salvage = false;
|
||||
self.crafting_fields.repair = false;
|
||||
self.diary = false;
|
||||
self.want_grab = !self.any_window_requires_cursor();
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ impl BlocksOfInterest {
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::Dismantle)))
|
||||
},
|
||||
Some(SpriteKind::RepairBench) => {
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::Repair)))
|
||||
interactables.push((pos, Interaction::Craft(CraftingTab::All)))
|
||||
},
|
||||
_ => {},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user