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