mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Durability system in place
This commit is contained in:
parent
73cd4e5136
commit
df13741be9
@ -1230,7 +1230,7 @@ fn weapon_rating<T: ItemDesc>(item: &T, _msm: &MaterialStatManifest) -> f32 {
|
||||
const BUFF_STRENGTH_WEIGHT: f32 = 1.5;
|
||||
|
||||
let rating = if let ItemKind::Tool(tool) = &*item.kind() {
|
||||
let stats = tool.stats;
|
||||
let stats = tool.stats(item.stats_durability_multiplier());
|
||||
|
||||
// TODO: Look into changing the 0.5 to reflect armor later maybe?
|
||||
// Since it is only for weapon though, it probably makes sense to leave
|
||||
@ -1361,7 +1361,9 @@ pub fn compute_crit_mult(inventory: Option<&Inventory>, msm: &MaterialStatManife
|
||||
inv.equipped_items()
|
||||
.filter_map(|item| {
|
||||
if let ItemKind::Armor(armor) = &*item.kind() {
|
||||
armor.stats(msm).crit_power
|
||||
armor
|
||||
.stats(msm, item.stats_durability_multiplier())
|
||||
.crit_power
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1379,7 +1381,9 @@ pub fn compute_energy_reward_mod(inventory: Option<&Inventory>, msm: &MaterialSt
|
||||
inv.equipped_items()
|
||||
.filter_map(|item| {
|
||||
if let ItemKind::Armor(armor) = &*item.kind() {
|
||||
armor.stats(msm).energy_reward
|
||||
armor
|
||||
.stats(msm, item.stats_durability_multiplier())
|
||||
.energy_reward
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1397,7 +1401,9 @@ pub fn compute_max_energy_mod(inventory: Option<&Inventory>, msm: &MaterialStatM
|
||||
inv.equipped_items()
|
||||
.filter_map(|item| {
|
||||
if let ItemKind::Armor(armor) = &*item.kind() {
|
||||
armor.stats(msm).energy_max
|
||||
armor
|
||||
.stats(msm, item.stats_durability_multiplier())
|
||||
.energy_max
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1433,7 +1439,7 @@ pub fn stealth_multiplier_from_items(
|
||||
inv.equipped_items()
|
||||
.filter_map(|item| {
|
||||
if let ItemKind::Armor(armor) = &*item.kind() {
|
||||
armor.stats(msm).stealth
|
||||
armor.stats(msm, item.stats_durability_multiplier()).stealth
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1456,7 +1462,9 @@ pub fn compute_protection(
|
||||
inv.equipped_items()
|
||||
.filter_map(|item| {
|
||||
if let ItemKind::Armor(armor) = &*item.kind() {
|
||||
armor.stats(msm).protection
|
||||
armor
|
||||
.stats(msm, item.stats_durability_multiplier())
|
||||
.protection
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
comp::item::{MaterialStatManifest, Rgb},
|
||||
comp::item::{DurabilityMultiplier, MaterialStatManifest, Rgb},
|
||||
terrain::{Block, BlockKind},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -212,8 +212,12 @@ pub struct Armor {
|
||||
impl Armor {
|
||||
pub fn new(kind: ArmorKind, stats: StatsSource) -> Self { Self { kind, stats } }
|
||||
|
||||
pub fn stats(&self, msm: &MaterialStatManifest) -> Stats {
|
||||
match &self.stats {
|
||||
pub fn stats(
|
||||
&self,
|
||||
msm: &MaterialStatManifest,
|
||||
durability_multiplier: DurabilityMultiplier,
|
||||
) -> Stats {
|
||||
let base_stats = match &self.stats {
|
||||
StatsSource::Direct(stats) => *stats,
|
||||
StatsSource::FromSet(set) => {
|
||||
let set_stats = msm.armor_stats(set).unwrap_or_else(Stats::none);
|
||||
@ -237,7 +241,9 @@ impl Armor {
|
||||
|
||||
set_stats * multiplier
|
||||
},
|
||||
}
|
||||
};
|
||||
let DurabilityMultiplier(mult) = durability_multiplier;
|
||||
base_stats * mult
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -396,6 +396,10 @@ pub struct Item {
|
||||
slots: Vec<InvSlot>,
|
||||
item_config: Option<Box<ItemConfig>>,
|
||||
hash: u64,
|
||||
/// Tracks how many deaths occurred while item was equipped, which is
|
||||
/// converted into the items durability. Only tracked for tools and armor
|
||||
/// currently.
|
||||
durability: Option<u32>,
|
||||
}
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
@ -609,7 +613,8 @@ impl TryFrom<(&Item, &AbilityMap, &MaterialStatManifest)> for ItemConfig {
|
||||
};
|
||||
let abilities = if let Some(set_key) = item.ability_spec() {
|
||||
if let Some(set) = ability_map.get_ability_set(&set_key) {
|
||||
set.clone().modified_by_tool(tool)
|
||||
set.clone()
|
||||
.modified_by_tool(tool, item.stats_durability_multiplier())
|
||||
} else {
|
||||
error!(
|
||||
"Custom ability set: {:?} references non-existent set, falling back to \
|
||||
@ -619,7 +624,8 @@ impl TryFrom<(&Item, &AbilityMap, &MaterialStatManifest)> for ItemConfig {
|
||||
tool_default(tool.kind).cloned().unwrap_or_default()
|
||||
}
|
||||
} else if let Some(set) = tool_default(tool.kind) {
|
||||
set.clone().modified_by_tool(tool)
|
||||
set.clone()
|
||||
.modified_by_tool(tool, item.stats_durability_multiplier())
|
||||
} else {
|
||||
error!(
|
||||
"No ability set defined for tool: {:?}, falling back to default ability set.",
|
||||
@ -785,6 +791,7 @@ impl Item {
|
||||
// These fields are updated immediately below
|
||||
item_config: None,
|
||||
hash: 0,
|
||||
durability: None,
|
||||
};
|
||||
item.update_item_state(ability_map, msm);
|
||||
item
|
||||
@ -1089,7 +1096,7 @@ impl Item {
|
||||
ItemBase::Modular(mod_base) => {
|
||||
// TODO: Try to move further upward
|
||||
let msm = MaterialStatManifest::load().read();
|
||||
mod_base.kind(self.components(), &msm)
|
||||
mod_base.kind(self.components(), &msm, self.stats_durability_multiplier())
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -1188,6 +1195,18 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stats_durability_multiplier(&self) -> DurabilityMultiplier {
|
||||
const MAX_DURABILITY: u32 = 8;
|
||||
let durability = self.durability.map_or(0, |x| x.clamp(0, MAX_DURABILITY));
|
||||
const DURABILITY_THRESHOLD: u32 = 4;
|
||||
const MIN_FRAC: f32 = 0.25;
|
||||
let mult = durability.saturating_sub(DURABILITY_THRESHOLD) as f32
|
||||
/ (MAX_DURABILITY - DURABILITY_THRESHOLD) as f32
|
||||
* (1.0 - MIN_FRAC)
|
||||
+ MIN_FRAC;
|
||||
DurabilityMultiplier(mult)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn create_test_item_from_kind(kind: ItemKind) -> Self {
|
||||
let ability_map = &AbilityMap::load().read();
|
||||
@ -1211,10 +1230,9 @@ pub trait ItemDesc {
|
||||
fn num_slots(&self) -> u16;
|
||||
fn item_definition_id(&self) -> ItemDefinitionId<'_>;
|
||||
fn tags(&self) -> Vec<ItemTag>;
|
||||
|
||||
fn is_modular(&self) -> bool;
|
||||
|
||||
fn components(&self) -> &[Item];
|
||||
fn stats_durability_multiplier(&self) -> DurabilityMultiplier;
|
||||
|
||||
fn tool_info(&self) -> Option<ToolKind> {
|
||||
if let ItemKind::Tool(tool) = &*self.kind() {
|
||||
@ -1243,6 +1261,10 @@ impl ItemDesc for Item {
|
||||
fn is_modular(&self) -> bool { self.is_modular() }
|
||||
|
||||
fn components(&self) -> &[Item] { self.components() }
|
||||
|
||||
fn stats_durability_multiplier(&self) -> DurabilityMultiplier {
|
||||
self.stats_durability_multiplier()
|
||||
}
|
||||
}
|
||||
|
||||
impl ItemDesc for ItemDef {
|
||||
@ -1265,6 +1287,8 @@ impl ItemDesc for ItemDef {
|
||||
fn is_modular(&self) -> bool { false }
|
||||
|
||||
fn components(&self) -> &[Item] { &[] }
|
||||
|
||||
fn stats_durability_multiplier(&self) -> DurabilityMultiplier { DurabilityMultiplier(1.0) }
|
||||
}
|
||||
|
||||
impl Component for Item {
|
||||
@ -1278,6 +1302,9 @@ impl Component for ItemDrop {
|
||||
type Storage = DenseVecStorage<Self>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct DurabilityMultiplier(pub f32);
|
||||
|
||||
impl<'a, T: ItemDesc + ?Sized> ItemDesc for &'a T {
|
||||
fn description(&self) -> &str { (*self).description() }
|
||||
|
||||
@ -1296,6 +1323,10 @@ impl<'a, T: ItemDesc + ?Sized> ItemDesc for &'a T {
|
||||
fn is_modular(&self) -> bool { (*self).is_modular() }
|
||||
|
||||
fn components(&self) -> &[Item] { (*self).components() }
|
||||
|
||||
fn stats_durability_multiplier(&self) -> DurabilityMultiplier {
|
||||
(*self).stats_durability_multiplier()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all item asset specifiers
|
||||
|
@ -1,7 +1,8 @@
|
||||
use super::{
|
||||
armor,
|
||||
tool::{self, AbilityMap, AbilitySpec, Hands},
|
||||
Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, Material, Quality, ToolKind,
|
||||
tool::{self, AbilityMap, AbilitySpec, Hands, Tool},
|
||||
DurabilityMultiplier, Item, ItemBase, ItemDef, ItemDesc, ItemKind, ItemTag, Material, Quality,
|
||||
ToolKind,
|
||||
};
|
||||
use crate::{
|
||||
assets::{self, Asset, AssetExt, AssetHandle},
|
||||
@ -98,8 +99,17 @@ impl ModularBase {
|
||||
hand_restriction.unwrap_or(Hands::One)
|
||||
}
|
||||
|
||||
pub fn kind(&self, components: &[Item], msm: &MaterialStatManifest) -> Cow<ItemKind> {
|
||||
fn resolve_stats(components: &[Item], msm: &MaterialStatManifest) -> tool::Stats {
|
||||
pub(super) fn kind(
|
||||
&self,
|
||||
components: &[Item],
|
||||
msm: &MaterialStatManifest,
|
||||
durability_multiplier: DurabilityMultiplier,
|
||||
) -> Cow<ItemKind> {
|
||||
fn resolve_stats(
|
||||
components: &[Item],
|
||||
msm: &MaterialStatManifest,
|
||||
durability_multiplier: DurabilityMultiplier,
|
||||
) -> tool::Stats {
|
||||
components
|
||||
.iter()
|
||||
.filter_map(|comp| {
|
||||
@ -110,6 +120,7 @@ impl ModularBase {
|
||||
}
|
||||
})
|
||||
.fold(tool::Stats::one(), |a, b| a * b)
|
||||
* durability_multiplier
|
||||
}
|
||||
|
||||
let toolkind = components
|
||||
@ -124,11 +135,11 @@ impl ModularBase {
|
||||
.unwrap_or(ToolKind::Empty);
|
||||
|
||||
match self {
|
||||
ModularBase::Tool => Cow::Owned(ItemKind::Tool(tool::Tool {
|
||||
kind: toolkind,
|
||||
hands: Self::resolve_hands(components),
|
||||
stats: resolve_stats(components, msm),
|
||||
})),
|
||||
ModularBase::Tool => Cow::Owned(ItemKind::Tool(Tool::new(
|
||||
toolkind,
|
||||
Self::resolve_hands(components),
|
||||
resolve_stats(components, msm, durability_multiplier),
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,14 +3,13 @@
|
||||
|
||||
use crate::{
|
||||
assets::{self, Asset, AssetExt, AssetHandle},
|
||||
comp::{ability::Stance, skills::Skill, CharacterAbility, SkillSet},
|
||||
comp::{
|
||||
ability::Stance, item::DurabilityMultiplier, skills::Skill, CharacterAbility, SkillSet,
|
||||
},
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub},
|
||||
time::Duration,
|
||||
};
|
||||
use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Sub};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
|
||||
pub enum ToolKind {
|
||||
@ -171,9 +170,11 @@ impl Add<Stats> for Stats {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign<Stats> for Stats {
|
||||
fn add_assign(&mut self, other: Stats) { *self = *self + other; }
|
||||
}
|
||||
|
||||
impl Sub<Stats> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
@ -190,6 +191,7 @@ impl Sub<Stats> for Stats {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<Stats> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
@ -206,9 +208,29 @@ impl Mul<Stats> for Stats {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MulAssign<Stats> for Stats {
|
||||
fn mul_assign(&mut self, other: Stats) { *self = *self * other; }
|
||||
}
|
||||
|
||||
impl Mul<DurabilityMultiplier> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, value: DurabilityMultiplier) -> Self {
|
||||
let DurabilityMultiplier(value) = value;
|
||||
Self {
|
||||
equip_time_secs: self.equip_time_secs / value.max(0.01),
|
||||
power: self.power * value,
|
||||
effect_power: self.effect_power * value,
|
||||
speed: self.speed * value,
|
||||
crit_chance: self.crit_chance * value,
|
||||
range: self.range * value,
|
||||
energy_efficiency: self.energy_efficiency * value,
|
||||
buff_strength: self.buff_strength * value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<f32> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
@ -225,15 +247,12 @@ impl Div<f32> for Stats {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl DivAssign<usize> for Stats {
|
||||
fn div_assign(&mut self, scalar: usize) { *self = *self / (scalar as f32); }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Tool {
|
||||
pub kind: ToolKind,
|
||||
pub hands: Hands,
|
||||
pub stats: Stats,
|
||||
stats: Stats,
|
||||
// TODO: item specific abilities
|
||||
}
|
||||
|
||||
@ -259,24 +278,9 @@ impl Tool {
|
||||
}
|
||||
}
|
||||
|
||||
// Keep power between 0.5 and 2.00
|
||||
pub fn base_power(&self) -> f32 { self.stats.power }
|
||||
|
||||
pub fn base_effect_power(&self) -> f32 { self.stats.effect_power }
|
||||
|
||||
/// 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 }
|
||||
|
||||
pub fn base_range(&self) -> f32 { self.stats.range }
|
||||
|
||||
pub fn base_energy_efficiency(&self) -> f32 { self.stats.energy_efficiency }
|
||||
|
||||
pub fn base_buff_strength(&self) -> f32 { self.stats.buff_strength }
|
||||
|
||||
pub fn equip_time(&self) -> Duration { Duration::from_secs_f32(self.stats.equip_time_secs) }
|
||||
pub fn stats(&self, durability_multiplier: DurabilityMultiplier) -> Stats {
|
||||
self.stats * durability_multiplier
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@ -376,10 +380,16 @@ impl AbilityContext {
|
||||
|
||||
impl AbilitySet<AbilityItem> {
|
||||
#[must_use]
|
||||
pub fn modified_by_tool(self, tool: &Tool) -> Self {
|
||||
pub fn modified_by_tool(
|
||||
self,
|
||||
tool: &Tool,
|
||||
durability_multiplier: DurabilityMultiplier,
|
||||
) -> Self {
|
||||
self.map(|a| AbilityItem {
|
||||
id: a.id,
|
||||
ability: a.ability.adjusted_by_stats(tool.stats),
|
||||
ability: a
|
||||
.ability
|
||||
.adjusted_by_stats(tool.stats(durability_multiplier)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -270,7 +270,9 @@ impl Poise {
|
||||
inv.equipped_items()
|
||||
.filter_map(|item| {
|
||||
if let ItemKind::Armor(armor) = &*item.kind() {
|
||||
armor.stats(msm).poise_resilience
|
||||
armor
|
||||
.stats(msm, item.stats_durability_multiplier())
|
||||
.poise_resilience
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -335,7 +335,10 @@ pub fn handle_skating(data: &JoinData, update: &mut StateUpdate) {
|
||||
footwear = data.inventory.and_then(|inv| {
|
||||
inv.equipped(EquipSlot::Armor(ArmorSlot::Feet))
|
||||
.map(|armor| match armor.kind().as_ref() {
|
||||
ItemKind::Armor(a) => a.stats(data.msm).ground_contact,
|
||||
ItemKind::Armor(a) => {
|
||||
a.stats(data.msm, armor.stats_durability_multiplier())
|
||||
.ground_contact
|
||||
},
|
||||
_ => Friction::Normal,
|
||||
})
|
||||
});
|
||||
@ -719,7 +722,10 @@ pub fn attempt_wield(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
data.inventory
|
||||
.and_then(|inv| inv.equipped(equip_slot))
|
||||
.and_then(|item| match &*item.kind() {
|
||||
ItemKind::Tool(tool) => Some(tool.equip_time()),
|
||||
ItemKind::Tool(tool) => Some(Duration::from_secs_f32(
|
||||
tool.stats(item.stats_durability_multiplier())
|
||||
.equip_time_secs,
|
||||
)),
|
||||
_ => None,
|
||||
})
|
||||
};
|
||||
@ -1261,7 +1267,7 @@ pub fn get_crit_data(data: &JoinData<'_>, ai: AbilityInfo) -> (f32, f32) {
|
||||
.and_then(|slot| data.inventory.and_then(|inv| inv.equipped(slot)))
|
||||
.and_then(|item| {
|
||||
if let ItemKind::Tool(tool) = &*item.kind() {
|
||||
Some(tool.base_crit_chance())
|
||||
Some(tool.stats(item.stats_durability_multiplier()).crit_chance)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -1282,7 +1288,7 @@ pub fn get_tool_stats(data: &JoinData<'_>, ai: AbilityInfo) -> tool::Stats {
|
||||
.and_then(|slot| data.inventory.and_then(|inv| inv.equipped(slot)))
|
||||
.and_then(|item| {
|
||||
if let ItemKind::Tool(tool) = &*item.kind() {
|
||||
Some(tool.stats)
|
||||
Some(tool.stats(item.stats_durability_multiplier()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1211,7 +1211,9 @@ impl<'a> Widget for Diary<'a> {
|
||||
.inventory
|
||||
.equipped(EquipSlot::ActiveMainhand)
|
||||
.and_then(|item| match &*item.kind() {
|
||||
ItemKind::Tool(tool) => Some(tool.stats),
|
||||
ItemKind::Tool(tool) => {
|
||||
Some(tool.stats(item.stats_durability_multiplier()))
|
||||
},
|
||||
_ => None,
|
||||
});
|
||||
|
||||
@ -1219,7 +1221,9 @@ impl<'a> Widget for Diary<'a> {
|
||||
.inventory
|
||||
.equipped(EquipSlot::ActiveOffhand)
|
||||
.and_then(|item| match &*item.kind() {
|
||||
ItemKind::Tool(tool) => Some(tool.stats),
|
||||
ItemKind::Tool(tool) => {
|
||||
Some(tool.stats(item.stats_durability_multiplier()))
|
||||
},
|
||||
_ => None,
|
||||
});
|
||||
|
||||
|
@ -102,7 +102,7 @@ pub fn material_kind_text<'a>(kind: &MaterialKind, i18n: &'a Localization) -> Co
|
||||
pub fn stats_count(item: &dyn ItemDesc, msm: &MaterialStatManifest) -> usize {
|
||||
match &*item.kind() {
|
||||
ItemKind::Armor(armor) => {
|
||||
let armor_stats = armor.stats(msm);
|
||||
let armor_stats = armor.stats(msm, item.stats_durability_multiplier());
|
||||
armor_stats.energy_reward.is_some() as usize
|
||||
+ armor_stats.energy_max.is_some() as usize
|
||||
+ armor_stats.stealth.is_some() as usize
|
||||
|
@ -583,7 +583,7 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
// Stats
|
||||
match &*item.kind() {
|
||||
ItemKind::Tool(tool) => {
|
||||
let stats = tool.stats;
|
||||
let stats = tool.stats(item.stats_durability_multiplier());
|
||||
|
||||
// Power
|
||||
widget::Text::new(&format!(
|
||||
@ -671,8 +671,9 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
|
||||
if let Some(equipped_item) = equipped_item {
|
||||
if let ItemKind::Tool(equipped_tool) = &*equipped_item.kind() {
|
||||
let tool_stats = tool.stats;
|
||||
let equipped_tool_stats = equipped_tool.stats;
|
||||
let tool_stats = tool.stats(item.stats_durability_multiplier());
|
||||
let equipped_tool_stats =
|
||||
equipped_tool.stats(equipped_item.stats_durability_multiplier());
|
||||
let diff = tool_stats - equipped_tool_stats;
|
||||
let power_diff =
|
||||
util::comparison(tool_stats.power, equipped_tool_stats.power);
|
||||
@ -756,7 +757,7 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
}
|
||||
},
|
||||
ItemKind::Armor(armor) => {
|
||||
let armor_stats = armor.stats(self.msm);
|
||||
let armor_stats = armor.stats(self.msm, item.stats_durability_multiplier());
|
||||
|
||||
let mut stat_text = |text: String, i: usize| {
|
||||
widget::Text::new(&text)
|
||||
@ -877,7 +878,8 @@ impl<'a> Widget for ItemTooltip<'a> {
|
||||
|
||||
if let Some(equipped_item) = equipped_item {
|
||||
if let ItemKind::Armor(equipped_armor) = &*equipped_item.kind() {
|
||||
let equipped_stats = equipped_armor.stats(self.msm);
|
||||
let equipped_stats = equipped_armor
|
||||
.stats(self.msm, equipped_item.stats_durability_multiplier());
|
||||
let diff = armor_stats - equipped_stats;
|
||||
let protection_diff = util::option_comparison(
|
||||
&armor_stats.protection,
|
||||
|
Loading…
Reference in New Issue
Block a user