mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Diary stats now use real values.
This commit is contained in:
parent
eb0bed39e8
commit
ed38272d23
@ -761,46 +761,29 @@ impl Damage {
|
|||||||
inventory: Option<&Inventory>,
|
inventory: Option<&Inventory>,
|
||||||
stats: Option<&Stats>,
|
stats: Option<&Stats>,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
let inventory_dr = if let Some(inventory) = inventory {
|
let protection = compute_protection(inventory);
|
||||||
let protection = inventory
|
|
||||||
.equipped_items()
|
|
||||||
.filter_map(|item| {
|
|
||||||
if let ItemKind::Armor(armor) = &item.kind() {
|
|
||||||
Some(armor.protection())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map(|protection| match protection {
|
|
||||||
Some(Protection::Normal(protection)) => Some(protection),
|
|
||||||
Some(Protection::Invincible) => None,
|
|
||||||
None => Some(0.0),
|
|
||||||
})
|
|
||||||
.sum::<Option<f32>>();
|
|
||||||
|
|
||||||
let penetration = if let Some(damage) = damage {
|
let penetration = if let Some(damage) = damage {
|
||||||
if let DamageKind::Piercing = damage.kind {
|
if let DamageKind::Piercing = damage.kind {
|
||||||
(damage.value * PIERCING_PENETRATION_FRACTION)
|
(damage.value * PIERCING_PENETRATION_FRACTION)
|
||||||
.min(protection.unwrap_or(0.0))
|
.min(protection.unwrap_or(0.0))
|
||||||
.max(0.0)
|
.max(0.0)
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
|
||||||
|
|
||||||
let protection = protection.map(|p| p - penetration);
|
|
||||||
|
|
||||||
const FIFTY_PERCENT_DR_THRESHOLD: f32 = 60.0;
|
|
||||||
|
|
||||||
match protection {
|
|
||||||
Some(dr) => dr / (FIFTY_PERCENT_DR_THRESHOLD + dr.abs()),
|
|
||||||
None => 1.0,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let protection = protection.map(|p| p - penetration);
|
||||||
|
|
||||||
|
const FIFTY_PERCENT_DR_THRESHOLD: f32 = 60.0;
|
||||||
|
|
||||||
|
let inventory_dr = match protection {
|
||||||
|
Some(dr) => dr / (FIFTY_PERCENT_DR_THRESHOLD + dr.abs()),
|
||||||
|
None => 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
let stats_dr = if let Some(stats) = stats {
|
let stats_dr = if let Some(stats) = stats {
|
||||||
stats.damage_reduction
|
stats.damage_reduction
|
||||||
} else {
|
} else {
|
||||||
@ -1172,3 +1155,25 @@ pub fn compute_stealth_coefficient(inventory: Option<&Inventory>) -> f32 {
|
|||||||
.fold(2.0, |a, b| a + b.max(0.0))
|
.fold(2.0, |a, b| a + b.max(0.0))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the total protection provided from armor. Is used to determine the
|
||||||
|
/// damage reduction applied to damage received by an entity None indicates that
|
||||||
|
/// the armor equipped makes the entity invulnerable
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn compute_protection(inventory: Option<&Inventory>) -> Option<f32> {
|
||||||
|
inventory.map_or(Some(0.0), |inv| {
|
||||||
|
inv.equipped_items()
|
||||||
|
.filter_map(|item| {
|
||||||
|
if let ItemKind::Armor(armor) = &item.kind() {
|
||||||
|
armor.protection()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(|protection| match protection {
|
||||||
|
Protection::Normal(protection) => Some(protection),
|
||||||
|
Protection::Invincible => None,
|
||||||
|
})
|
||||||
|
.sum::<Option<f32>>()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -231,15 +231,14 @@ impl Poise {
|
|||||||
.equipped_items()
|
.equipped_items()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let ItemKind::Armor(armor) = &item.kind() {
|
if let ItemKind::Armor(armor) = &item.kind() {
|
||||||
Some(armor.poise_resilience())
|
armor.poise_resilience()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(|protection| match protection {
|
.map(|protection| match protection {
|
||||||
Some(Protection::Normal(protection)) => Some(protection),
|
Protection::Normal(protection) => Some(protection),
|
||||||
Some(Protection::Invincible) => None,
|
Protection::Invincible => None,
|
||||||
None => Some(0.0),
|
|
||||||
})
|
})
|
||||||
.sum::<Option<f32>>();
|
.sum::<Option<f32>>();
|
||||||
match protection {
|
match protection {
|
||||||
|
@ -18,16 +18,23 @@ use i18n::Localization;
|
|||||||
|
|
||||||
use client::{self, Client};
|
use client::{self, Client};
|
||||||
use common::{
|
use common::{
|
||||||
|
combat,
|
||||||
comp::{
|
comp::{
|
||||||
self,
|
self,
|
||||||
ability::{Ability, ActiveAbilities, AuxiliaryAbility, MAX_ABILITIES},
|
ability::{Ability, ActiveAbilities, AuxiliaryAbility, MAX_ABILITIES},
|
||||||
inventory::{item::tool::ToolKind, slot::EquipSlot},
|
inventory::{
|
||||||
|
item::{
|
||||||
|
tool::{MaterialStatManifest, ToolKind},
|
||||||
|
ItemKind,
|
||||||
|
},
|
||||||
|
slot::EquipSlot,
|
||||||
|
},
|
||||||
skills::{
|
skills::{
|
||||||
self, AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, MiningSkill,
|
self, AxeSkill, BowSkill, ClimbSkill, GeneralSkill, HammerSkill, MiningSkill,
|
||||||
RollSkill, SceptreSkill, Skill, StaffSkill, SwimSkill, SwordSkill, SKILL_MODIFIERS,
|
RollSkill, SceptreSkill, Skill, StaffSkill, SwimSkill, SwordSkill, SKILL_MODIFIERS,
|
||||||
},
|
},
|
||||||
skillset::{SkillGroupKind, SkillSet},
|
skillset::{SkillGroupKind, SkillSet},
|
||||||
Inventory,
|
Body, Energy, Health, Inventory, Poise,
|
||||||
},
|
},
|
||||||
consts::{ENERGY_PER_LEVEL, HP_PER_LEVEL},
|
consts::{ENERGY_PER_LEVEL, HP_PER_LEVEL},
|
||||||
};
|
};
|
||||||
@ -224,6 +231,11 @@ pub struct Diary<'a> {
|
|||||||
skill_set: &'a SkillSet,
|
skill_set: &'a SkillSet,
|
||||||
active_abilities: &'a ActiveAbilities,
|
active_abilities: &'a ActiveAbilities,
|
||||||
inventory: &'a Inventory,
|
inventory: &'a Inventory,
|
||||||
|
health: &'a Health,
|
||||||
|
energy: &'a Energy,
|
||||||
|
poise: &'a Poise,
|
||||||
|
body: &'a Body,
|
||||||
|
msm: &'a MaterialStatManifest,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
item_imgs: &'a ItemImgs,
|
item_imgs: &'a ItemImgs,
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
@ -264,6 +276,11 @@ impl<'a> Diary<'a> {
|
|||||||
skill_set: &'a SkillSet,
|
skill_set: &'a SkillSet,
|
||||||
active_abilities: &'a ActiveAbilities,
|
active_abilities: &'a ActiveAbilities,
|
||||||
inventory: &'a Inventory,
|
inventory: &'a Inventory,
|
||||||
|
health: &'a Health,
|
||||||
|
energy: &'a Energy,
|
||||||
|
poise: &'a Poise,
|
||||||
|
body: &'a Body,
|
||||||
|
msm: &'a MaterialStatManifest,
|
||||||
imgs: &'a Imgs,
|
imgs: &'a Imgs,
|
||||||
item_imgs: &'a ItemImgs,
|
item_imgs: &'a ItemImgs,
|
||||||
fonts: &'a Fonts,
|
fonts: &'a Fonts,
|
||||||
@ -278,6 +295,11 @@ impl<'a> Diary<'a> {
|
|||||||
skill_set,
|
skill_set,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
inventory,
|
inventory,
|
||||||
|
health,
|
||||||
|
energy,
|
||||||
|
poise,
|
||||||
|
body,
|
||||||
|
msm,
|
||||||
imgs,
|
imgs,
|
||||||
item_imgs,
|
item_imgs,
|
||||||
fonts,
|
fonts,
|
||||||
@ -308,21 +330,6 @@ const TREES: [&str; 8] = [
|
|||||||
"Mining",
|
"Mining",
|
||||||
];
|
];
|
||||||
|
|
||||||
const STATS: [&str; 12] = [
|
|
||||||
"Hitpoints",
|
|
||||||
"Energy",
|
|
||||||
"Combat-Rating",
|
|
||||||
"Protection",
|
|
||||||
"Stun-Resistance",
|
|
||||||
"Crit-Power",
|
|
||||||
"Energy Reward",
|
|
||||||
"Stealth",
|
|
||||||
"Weapon Power",
|
|
||||||
"Weapon Speed",
|
|
||||||
"Weapon Poise",
|
|
||||||
"Weapon Crit-Chance",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Possible future sections: Bestiary ("Pokedex" of fought enemies), Weapon and
|
// Possible future sections: Bestiary ("Pokedex" of fought enemies), Weapon and
|
||||||
// armour catalogue, Achievements...
|
// armour catalogue, Achievements...
|
||||||
const SECTIONS: [&str; 3] = ["Abilities", "Skill-Trees", "Stats"];
|
const SECTIONS: [&str; 3] = ["Abilities", "Skill-Trees", "Stats"];
|
||||||
@ -1121,18 +1128,21 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
events
|
events
|
||||||
},
|
},
|
||||||
DiarySection::Stats => {
|
DiarySection::Stats => {
|
||||||
let hp = 100;
|
const STATS: [&str; 13] = [
|
||||||
let energy = 50;
|
"Hitpoints",
|
||||||
let cr = 1;
|
"Energy",
|
||||||
let prot = 1;
|
"Poise",
|
||||||
let stun_res = 1;
|
"Combat-Rating",
|
||||||
let critpwr = 1;
|
"Protection",
|
||||||
let energ_rew = 1;
|
"Stun-Resistance",
|
||||||
let stealth = 1;
|
"Crit-Power",
|
||||||
let wpn_pwr = 1;
|
"Energy Reward",
|
||||||
let wpn_spd = 1;
|
"Stealth",
|
||||||
let wpn_poi = 1;
|
"Weapon Power",
|
||||||
let wpn_crit = 1;
|
"Weapon Speed",
|
||||||
|
"Weapon Poise",
|
||||||
|
"Weapon Crit-Chance",
|
||||||
|
];
|
||||||
|
|
||||||
// Background Art
|
// Background Art
|
||||||
Image::new(self.imgs.book_bg)
|
Image::new(self.imgs.book_bg)
|
||||||
@ -1168,21 +1178,112 @@ impl<'a> Widget for Diary<'a> {
|
|||||||
};
|
};
|
||||||
txt.set(state.ids.stat_names[i], ui);
|
txt.set(state.ids.stat_names[i], ui);
|
||||||
|
|
||||||
|
let main_weap_stats = self
|
||||||
|
.inventory
|
||||||
|
.equipped(EquipSlot::ActiveMainhand)
|
||||||
|
.and_then(|item| match &item.kind {
|
||||||
|
ItemKind::Tool(tool) => {
|
||||||
|
Some(tool.stats.resolve_stats(self.msm, item.components()))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let off_weap_stats = self
|
||||||
|
.inventory
|
||||||
|
.equipped(EquipSlot::ActiveOffhand)
|
||||||
|
.and_then(|item| match &item.kind {
|
||||||
|
ItemKind::Tool(tool) => {
|
||||||
|
Some(tool.stats.resolve_stats(self.msm, item.components()))
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
// Stat values
|
// Stat values
|
||||||
let value = match stat {
|
let value = match stat {
|
||||||
"Hitpoints" => format!("{}", hp),
|
"Hitpoints" => format!("{}", self.health.base_max() as u32),
|
||||||
"Energy" => format!("{}", energy),
|
"Energy" => format!("{}", self.energy.base_max() as u32),
|
||||||
"Combat-Rating" => format!("{}", cr),
|
"Poise" => format!("{}", self.poise.base_max() as u32),
|
||||||
"Protection" => format!("{}", prot),
|
"Combat-Rating" => {
|
||||||
"Stun-Resistance" => format!("{}", stun_res),
|
let cr = combat::combat_rating(
|
||||||
"Crit-Power" => format!("{}", critpwr),
|
self.inventory,
|
||||||
"Energy Reward" => format!("{}", energ_rew),
|
self.health,
|
||||||
"Stealth" => format!("{}", stealth),
|
self.energy,
|
||||||
"Weapon Power" => format!("{}", wpn_pwr),
|
self.poise,
|
||||||
"Weapon Speed" => format!("{}", wpn_spd),
|
self.skill_set,
|
||||||
"Weapon Poise" => format!("{}", wpn_poi),
|
*self.body,
|
||||||
"Weapon Crit-Chance" => format!("{}%", wpn_crit),
|
self.msm,
|
||||||
_ => "".to_string(),
|
);
|
||||||
|
format!("{:.2}", cr)
|
||||||
|
},
|
||||||
|
"Protection" => {
|
||||||
|
let protection = combat::compute_protection(Some(self.inventory));
|
||||||
|
match protection {
|
||||||
|
Some(prot) => format!("{}", prot),
|
||||||
|
None => String::from("Invincible"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Stun-Resistance" => {
|
||||||
|
let stun_res = Poise::compute_poise_damage_reduction(self.inventory);
|
||||||
|
format!("{}%", stun_res * 100.0)
|
||||||
|
},
|
||||||
|
"Crit-Power" => {
|
||||||
|
let critpwr = combat::compute_crit_mult(Some(self.inventory));
|
||||||
|
format!("x{}", critpwr)
|
||||||
|
},
|
||||||
|
"Energy Reward" => {
|
||||||
|
let energy_rew =
|
||||||
|
combat::compute_energy_reward_mod(Some(self.inventory));
|
||||||
|
format!("{:+.0}%", (energy_rew - 1.0) * 100.0)
|
||||||
|
},
|
||||||
|
"Stealth" => {
|
||||||
|
let stealth = combat::compute_stealth_coefficient(Some(self.inventory));
|
||||||
|
format!("{}", stealth)
|
||||||
|
},
|
||||||
|
"Weapon Power" => match (main_weap_stats, off_weap_stats) {
|
||||||
|
(Some(m_stats), Some(o_stats)) => {
|
||||||
|
format!("{} {}", m_stats.power, o_stats.power)
|
||||||
|
},
|
||||||
|
(Some(stats), None) | (None, Some(stats)) => format!("{}", stats.power),
|
||||||
|
_ => String::new(),
|
||||||
|
},
|
||||||
|
"Weapon Speed" => {
|
||||||
|
let spd_fmt = |sp| (sp - 1.0) * 100.0;
|
||||||
|
match (main_weap_stats, off_weap_stats) {
|
||||||
|
(Some(m_stats), Some(o_stats)) => format!(
|
||||||
|
"{:+.0}% {:+.0}%",
|
||||||
|
spd_fmt(m_stats.speed),
|
||||||
|
spd_fmt(o_stats.speed)
|
||||||
|
),
|
||||||
|
(Some(stats), None) | (None, Some(stats)) => {
|
||||||
|
format!("{:+.0}%", spd_fmt(stats.speed))
|
||||||
|
},
|
||||||
|
_ => String::new(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Weapon Poise" => match (main_weap_stats, off_weap_stats) {
|
||||||
|
(Some(m_stats), Some(o_stats)) => {
|
||||||
|
format!("{} {}", m_stats.effect_power, o_stats.effect_power)
|
||||||
|
},
|
||||||
|
(Some(stats), None) | (None, Some(stats)) => {
|
||||||
|
format!("{}", stats.effect_power)
|
||||||
|
},
|
||||||
|
_ => String::new(),
|
||||||
|
},
|
||||||
|
"Weapon Crit-Chance" => {
|
||||||
|
let crit_fmt = |cc| cc * 100.0;
|
||||||
|
match (main_weap_stats, off_weap_stats) {
|
||||||
|
(Some(m_stats), Some(o_stats)) => format!(
|
||||||
|
"{:.1}% {:.1}%",
|
||||||
|
crit_fmt(m_stats.crit_chance),
|
||||||
|
crit_fmt(o_stats.crit_chance)
|
||||||
|
),
|
||||||
|
(Some(stats), None) | (None, Some(stats)) => {
|
||||||
|
format!("{:.1}%", crit_fmt(stats.crit_chance))
|
||||||
|
},
|
||||||
|
_ => String::new(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => String::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut number = Text::new(&value)
|
let mut number = Text::new(&value)
|
||||||
|
@ -3097,10 +3097,22 @@ impl Hud {
|
|||||||
if self.show.diary {
|
if self.show.diary {
|
||||||
let entity = client.entity();
|
let entity = client.entity();
|
||||||
let skill_sets = ecs.read_storage::<comp::SkillSet>();
|
let skill_sets = ecs.read_storage::<comp::SkillSet>();
|
||||||
if let (Some(skill_set), Some(active_abilities), Some(inventory)) = (
|
if let (
|
||||||
|
Some(skill_set),
|
||||||
|
Some(active_abilities),
|
||||||
|
Some(inventory),
|
||||||
|
Some(health),
|
||||||
|
Some(energy),
|
||||||
|
Some(body),
|
||||||
|
Some(poise),
|
||||||
|
) = (
|
||||||
skill_sets.get(entity),
|
skill_sets.get(entity),
|
||||||
active_abilities.get(entity),
|
active_abilities.get(entity),
|
||||||
inventories.get(entity),
|
inventories.get(entity),
|
||||||
|
healths.get(entity),
|
||||||
|
energies.get(entity),
|
||||||
|
bodies.get(entity),
|
||||||
|
poises.get(entity),
|
||||||
) {
|
) {
|
||||||
for event in Diary::new(
|
for event in Diary::new(
|
||||||
&self.show,
|
&self.show,
|
||||||
@ -3108,6 +3120,11 @@ impl Hud {
|
|||||||
skill_set,
|
skill_set,
|
||||||
active_abilities,
|
active_abilities,
|
||||||
inventory,
|
inventory,
|
||||||
|
health,
|
||||||
|
energy,
|
||||||
|
poise,
|
||||||
|
body,
|
||||||
|
&msm,
|
||||||
&self.imgs,
|
&self.imgs,
|
||||||
&self.item_imgs,
|
&self.item_imgs,
|
||||||
&self.fonts,
|
&self.fonts,
|
||||||
|
Loading…
Reference in New Issue
Block a user