mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Addressed review
This commit is contained in:
parent
79812a7326
commit
132f26dbc0
@ -27,20 +27,19 @@ pub enum ArmorKind {
|
||||
|
||||
impl ArmorKind {
|
||||
pub fn has_durability(self) -> bool {
|
||||
use ArmorKind::*;
|
||||
match self {
|
||||
Shoulder => true,
|
||||
Chest => true,
|
||||
Belt => true,
|
||||
Hand => true,
|
||||
Pants => true,
|
||||
Foot => true,
|
||||
Back => true,
|
||||
Ring => false,
|
||||
Neck => false,
|
||||
Head => true,
|
||||
Tabard => false,
|
||||
Bag => false,
|
||||
ArmorKind::Shoulder => true,
|
||||
ArmorKind::Chest => true,
|
||||
ArmorKind::Belt => true,
|
||||
ArmorKind::Hand => true,
|
||||
ArmorKind::Pants => true,
|
||||
ArmorKind::Foot => true,
|
||||
ArmorKind::Back => true,
|
||||
ArmorKind::Ring => false,
|
||||
ArmorKind::Neck => false,
|
||||
ArmorKind::Head => true,
|
||||
ArmorKind::Tabard => false,
|
||||
ArmorKind::Bag => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -262,8 +261,7 @@ impl Armor {
|
||||
set_stats * multiplier
|
||||
},
|
||||
};
|
||||
let DurabilityMultiplier(mult) = durability_multiplier;
|
||||
base_stats * mult
|
||||
base_stats * durability_multiplier.0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -399,7 +399,7 @@ pub struct Item {
|
||||
/// 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>,
|
||||
durability_lost: Option<u32>,
|
||||
}
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
@ -793,9 +793,9 @@ impl Item {
|
||||
// These fields are updated immediately below
|
||||
item_config: None,
|
||||
hash: 0,
|
||||
durability: None,
|
||||
durability_lost: None,
|
||||
};
|
||||
item.durability = item.has_durability().then_some(0);
|
||||
item.durability_lost = item.has_durability().then_some(0);
|
||||
item.update_item_state(ability_map, msm);
|
||||
item
|
||||
}
|
||||
@ -1198,16 +1198,17 @@ impl Item {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn durability(&self) -> Option<u32> { self.durability.map(|x| x.min(Self::MAX_DURABILITY)) }
|
||||
pub fn durability(&self) -> Option<u32> {
|
||||
self.durability_lost.map(|x| x.min(Self::MAX_DURABILITY))
|
||||
}
|
||||
|
||||
pub fn stats_durability_multiplier(&self) -> DurabilityMultiplier {
|
||||
let durability = self
|
||||
.durability
|
||||
.map_or(0, |x| x.clamp(0, Self::MAX_DURABILITY));
|
||||
let durability_lost = self.durability_lost.unwrap_or(0);
|
||||
debug_assert!(durability_lost <= Self::MAX_DURABILITY);
|
||||
const DURABILITY_THRESHOLD: u32 = 4;
|
||||
const MIN_FRAC: f32 = 0.2;
|
||||
let mult = (1.0
|
||||
- durability.saturating_sub(DURABILITY_THRESHOLD) as f32
|
||||
- durability_lost.saturating_sub(DURABILITY_THRESHOLD) as f32
|
||||
/ (Self::MAX_DURABILITY - DURABILITY_THRESHOLD) as f32)
|
||||
* (1.0 - MIN_FRAC)
|
||||
+ MIN_FRAC;
|
||||
@ -1218,13 +1219,22 @@ impl Item {
|
||||
match &*self.kind() {
|
||||
ItemKind::Tool(_) => true,
|
||||
ItemKind::Armor(armor) => armor.kind.has_durability(),
|
||||
_ => false,
|
||||
ItemKind::ModularComponent(_)
|
||||
| ItemKind::Lantern(_)
|
||||
| ItemKind::Glider
|
||||
| ItemKind::Consumable { .. }
|
||||
| ItemKind::Throwable { .. }
|
||||
| ItemKind::Utility { .. }
|
||||
| ItemKind::Ingredient { .. }
|
||||
| ItemKind::TagExamples { .. } => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_durability(&mut self, ability_map: &AbilityMap, msm: &MaterialStatManifest) {
|
||||
if let Some(durability) = &mut self.durability {
|
||||
*durability += 1;
|
||||
pub fn increment_damage(&mut self, ability_map: &AbilityMap, msm: &MaterialStatManifest) {
|
||||
if let Some(durability_lost) = &mut self.durability_lost {
|
||||
if *durability_lost < Self::MAX_DURABILITY {
|
||||
*durability_lost += 1;
|
||||
}
|
||||
}
|
||||
// Update item state after applying durability because stats have potential to
|
||||
// change from different durability
|
||||
@ -1232,23 +1242,23 @@ impl Item {
|
||||
}
|
||||
|
||||
pub fn persistence_durability(&self) -> Option<NonZeroU32> {
|
||||
self.durability.and_then(NonZeroU32::new)
|
||||
self.durability_lost.and_then(NonZeroU32::new)
|
||||
}
|
||||
|
||||
pub fn persistence_set_durability(&mut self, value: Option<NonZeroU32>) {
|
||||
// If changes have been made so that item no longer needs to track durability,
|
||||
// set to None
|
||||
if !self.has_durability() {
|
||||
self.durability = None;
|
||||
self.durability_lost = None;
|
||||
} else {
|
||||
// Set durability to persisted value, and if item previously had no durability,
|
||||
// set to Some(0) so that durability will be tracked
|
||||
self.durability = Some(value.map_or(0, NonZeroU32::get));
|
||||
self.durability_lost = Some(value.map_or(0, NonZeroU32::get));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset_durability(&mut self, ability_map: &AbilityMap, msm: &MaterialStatManifest) {
|
||||
self.durability = self.durability.map(|_| 0);
|
||||
self.durability_lost = self.has_durability().then_some(0);
|
||||
// Update item state after applying durability because stats have potential to
|
||||
// change from different durability
|
||||
self.update_item_state(ability_map, msm);
|
||||
|
@ -146,6 +146,20 @@ impl Stats {
|
||||
let diminished = (self.buff_strength - base + 1.0).log(5.0);
|
||||
base + diminished
|
||||
}
|
||||
|
||||
pub fn with_durability_mult(&self, dur_mult: DurabilityMultiplier) -> Self {
|
||||
let less_scaled = dur_mult.0 * 0.5 + 0.5;
|
||||
Self {
|
||||
equip_time_secs: self.equip_time_secs / less_scaled.max(0.01),
|
||||
power: self.power * dur_mult.0,
|
||||
effect_power: self.effect_power * dur_mult.0,
|
||||
speed: self.speed * less_scaled,
|
||||
crit_chance: self.crit_chance * dur_mult.0,
|
||||
range: self.range * dur_mult.0,
|
||||
energy_efficiency: self.energy_efficiency * dur_mult.0,
|
||||
buff_strength: self.buff_strength * dur_mult.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Asset for Stats {
|
||||
@ -213,25 +227,6 @@ 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;
|
||||
let less_scaled = value * 0.5 + 0.5;
|
||||
Self {
|
||||
equip_time_secs: self.equip_time_secs / less_scaled.max(0.01),
|
||||
power: self.power * value,
|
||||
effect_power: self.effect_power * value,
|
||||
speed: self.speed * less_scaled,
|
||||
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;
|
||||
|
||||
@ -249,6 +244,12 @@ impl Div<f32> for Stats {
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<DurabilityMultiplier> for Stats {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, value: DurabilityMultiplier) -> Self { self.with_durability_mult(value) }
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Tool {
|
||||
pub kind: ToolKind,
|
||||
|
@ -424,19 +424,16 @@ impl Loadout {
|
||||
}
|
||||
|
||||
/// Increments durability by 1 of all valid items
|
||||
pub(super) fn apply_durability(
|
||||
pub(super) fn damage_items(
|
||||
&mut self,
|
||||
ability_map: &item::tool::AbilityMap,
|
||||
msm: &item::MaterialStatManifest,
|
||||
) {
|
||||
self.slots
|
||||
.iter_mut()
|
||||
.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(ability_map, msm);
|
||||
}
|
||||
})
|
||||
.filter_map(|slot| slot.slot.as_mut())
|
||||
.filter(|item| item.has_durability())
|
||||
.for_each(|item| item.increment_damage(ability_map, msm));
|
||||
}
|
||||
|
||||
/// Resets durability of item in specified slot
|
||||
|
@ -884,12 +884,12 @@ impl Inventory {
|
||||
}
|
||||
|
||||
/// Increments durability of all valid items equipped in loaodut by 1
|
||||
pub fn apply_durability(
|
||||
pub fn damage_items(
|
||||
&mut self,
|
||||
ability_map: &item::tool::AbilityMap,
|
||||
msm: &item::MaterialStatManifest,
|
||||
) {
|
||||
self.loadout.apply_durability(ability_map, msm)
|
||||
self.loadout.damage_items(ability_map, msm)
|
||||
}
|
||||
|
||||
/// Resets durability of item in specified slot
|
||||
@ -901,7 +901,7 @@ impl Inventory {
|
||||
) {
|
||||
match slot {
|
||||
Slot::Inventory(invslot) => {
|
||||
if let Some(Some(item)) = self.slot_mut(invslot).map(Option::as_mut) {
|
||||
if let Some(Some(item)) = self.slot_mut(invslot) {
|
||||
item.reset_durability(ability_map, msm);
|
||||
}
|
||||
},
|
||||
|
@ -14,7 +14,7 @@ use crate::{
|
||||
};
|
||||
use hashbrown::HashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{borrow::Cow, ops::Mul, sync::Arc};
|
||||
use std::{borrow::Cow, sync::Arc};
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum RecipeInput {
|
||||
@ -517,13 +517,11 @@ impl assets::Compound for RecipeBook {
|
||||
cache: assets::AnyCache,
|
||||
specifier: &assets::SharedString,
|
||||
) -> Result<Self, assets::BoxedError> {
|
||||
#[inline]
|
||||
fn load_item_def(spec: &(String, u32)) -> Result<(Arc<ItemDef>, u32), assets::Error> {
|
||||
let def = Arc::<ItemDef>::load_cloned(&spec.0)?;
|
||||
Ok((def, spec.1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn load_recipe_input(
|
||||
(input, amount, is_mod_comp): &(RawRecipeInput, u32, bool),
|
||||
) -> Result<(RecipeInput, u32, bool), assets::Error> {
|
||||
@ -835,7 +833,6 @@ impl assets::Compound for ComponentRecipeBook {
|
||||
cache: assets::AnyCache,
|
||||
specifier: &assets::SharedString,
|
||||
) -> Result<Self, assets::BoxedError> {
|
||||
#[inline]
|
||||
fn create_recipe_key(raw_recipe: &RawComponentRecipe) -> ComponentKey {
|
||||
match &raw_recipe.output {
|
||||
RawComponentOutput::ToolPrimaryComponent { toolkind, item: _ } => {
|
||||
@ -853,7 +850,6 @@ impl assets::Compound for ComponentRecipeBook {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn load_recipe(raw_recipe: &RawComponentRecipe) -> Result<ComponentRecipe, assets::Error> {
|
||||
let output = match &raw_recipe.output {
|
||||
RawComponentOutput::ToolPrimaryComponent { toolkind: _, item } => {
|
||||
@ -979,18 +975,20 @@ impl RepairRecipe {
|
||||
inventory_contains_ingredients(self.inputs(item), inv, 1)
|
||||
}
|
||||
|
||||
pub fn inputs(&self, item: &Item) -> impl ExactSizeIterator<Item = (&RecipeInput, u32)> {
|
||||
pub fn inputs(&self, item: &Item) -> impl Iterator<Item = (&RecipeInput, u32)> {
|
||||
let item_durability = item.durability().unwrap_or(0);
|
||||
// TODO: Figure out how to avoid vec collection to maintain exact size iterator
|
||||
self.inputs.iter().filter_map(move |(input, original_amount)| {
|
||||
let amount = original_amount.mul(item_durability).div_floor(Item::MAX_DURABILITY);
|
||||
// If original repair recipe consumed ingredients, but item not damaged enough to actually need to consume item, remove item as requirement.
|
||||
if *original_amount > 0 && amount == 0 {
|
||||
None
|
||||
} else {
|
||||
Some((input, amount))
|
||||
}
|
||||
}).collect::<Vec<_>>().into_iter()
|
||||
self.inputs
|
||||
.iter()
|
||||
.filter_map(move |(input, original_amount)| {
|
||||
let amount = (original_amount * item_durability) / Item::MAX_DURABILITY;
|
||||
// If original repair recipe consumed ingredients, but item not damaged enough
|
||||
// to actually need to consume item, remove item as requirement.
|
||||
if *original_amount > 0 && amount == 0 {
|
||||
None
|
||||
} else {
|
||||
Some((input, amount))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -1068,7 +1066,6 @@ impl assets::Compound for RepairRecipeBook {
|
||||
cache: assets::AnyCache,
|
||||
specifier: &assets::SharedString,
|
||||
) -> Result<Self, assets::BoxedError> {
|
||||
#[inline]
|
||||
fn load_recipe_input(
|
||||
(input, amount): &(RawRecipeInput, u32),
|
||||
) -> Result<(RecipeInput, u32), assets::Error> {
|
||||
|
@ -515,7 +515,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, last_change: Healt
|
||||
if let Some(mut inventory) = state.ecs().write_storage::<Inventory>().get_mut(entity) {
|
||||
let ability_map = state.ecs().read_resource::<AbilityMap>();
|
||||
let msm = state.ecs().read_resource::<MaterialStatManifest>();
|
||||
inventory.apply_durability(&ability_map, &msm);
|
||||
inventory.damage_items(&ability_map, &msm);
|
||||
}
|
||||
|
||||
if should_delete {
|
||||
|
@ -1747,7 +1747,7 @@ impl<'a> Widget for Crafting<'a> {
|
||||
None => None,
|
||||
} {
|
||||
if let Some(recipe) = self.client.repair_recipe_book().repair_recipe(item) {
|
||||
iter_d = recipe.inputs(item);
|
||||
iter_d = recipe.inputs(item).collect::<Vec<_>>().into_iter();
|
||||
&mut iter_d as &mut dyn ExactSizeIterator<Item = _>
|
||||
} else {
|
||||
iter_b = core::iter::empty();
|
||||
|
Loading…
Reference in New Issue
Block a user