Merge branch 'holychowders/streamline_stealth_coefficient' into 'master'

Distinguish armor and sneaking stealth; Show stealth as percentage in Stats UI.

Closes #1525

See merge request veloren/veloren!3352
This commit is contained in:
Samuel Keiffer 2022-05-10 11:41:49 +00:00
commit 1bd33bb997
4 changed files with 45 additions and 30 deletions

View File

@ -26,6 +26,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [Server] Kick clients who send messages on the wrong stream
- Reworked Merchant trade price calculation, Merchants offer more wares
- Enable new giant trees, changed what entities spawn at them
- Stealth is now shown as a percentage in Stats Diary UI
- Stealth effects from sneaking and armor are evaluated independently. Armor now has effects even when not sneaking
### Removed

View File

@ -1164,13 +1164,26 @@ pub fn compute_max_energy_mod(inventory: Option<&Inventory>) -> f32 {
})
}
/// Computes the sneak coefficient from armor. Agent perception distances are
/// divided by the resulting f32.
/// Returns a value to be included as a multiplicative factor in perception
/// distance checks.
#[cfg(not(target_arch = "wasm32"))]
pub fn compute_stealth_coefficient(inventory: Option<&Inventory>) -> f32 {
// Starts with a value of 2.0 when summing the stats from each armor piece, and
// defaults to a value of 2.0 if no inventory is equipped
inventory.map_or(2.0, |inv| {
pub fn perception_dist_multiplier_from_stealth(
inventory: Option<&Inventory>,
character_state: Option<&CharacterState>,
) -> f32 {
const SNEAK_MULTIPLIER: f32 = 0.7;
let item_stealth_multiplier = stealth_multiplier_from_items(inventory);
let is_sneaking = character_state.map_or(false, |state| state.is_stealthy());
let multiplier = item_stealth_multiplier * if is_sneaking { SNEAK_MULTIPLIER } else { 1.0 };
multiplier.clamp(0.0, 1.0)
}
#[cfg(not(target_arch = "wasm32"))]
pub fn stealth_multiplier_from_items(inventory: Option<&Inventory>) -> f32 {
let stealth_sum = inventory.map_or(0.0, |inv| {
inv.equipped_items()
.filter_map(|item| {
if let ItemKind::Armor(armor) = &item.kind() {
@ -1179,8 +1192,10 @@ pub fn compute_stealth_coefficient(inventory: Option<&Inventory>) -> f32 {
None
}
})
.fold(2.0, |a, b| a + b.max(0.0))
})
.sum()
});
(1.0 / (1.0 + stealth_sum)).clamp(0.0, 1.0)
}
/// Computes the total protection provided from armor. Is used to determine the

View File

@ -20,7 +20,7 @@ use crate::{
},
};
use common::{
combat::compute_stealth_coefficient,
combat::perception_dist_multiplier_from_stealth,
comp::{
self,
agent::{
@ -2429,26 +2429,17 @@ impl<'a> AgentData<'a> {
other_pos: &Pos,
read_data: &ReadData,
) -> bool {
let other_stealth_coefficient = {
let is_other_stealthy = read_data
.char_states
.get(other)
.map_or(false, CharacterState::is_stealthy);
let other_stealth_multiplier = {
let other_inventory = read_data.inventories.get(other);
let other_char_state = read_data.char_states.get(other);
if is_other_stealthy {
// TODO: We shouldn't have to check CharacterState. This should be factored in
// by the function (such as the one we're calling below) that supposedly
// computes a coefficient given stealthy-ness.
compute_stealth_coefficient(read_data.inventories.get(other))
} else {
1.0
}
perception_dist_multiplier_from_stealth(other_inventory, other_char_state)
};
let dist_sqrd = other_pos.0.distance_squared(self.pos.0);
let within_sight_dist = {
let sight_dist = agent.psyche.sight_dist / other_stealth_coefficient;
let sight_dist = agent.psyche.sight_dist * other_stealth_multiplier;
let dist_sqrd = other_pos.0.distance_squared(self.pos.0);
dist_sqrd < sight_dist.powi(2)
};
@ -2458,7 +2449,7 @@ impl<'a> AgentData<'a> {
let other_body = read_data.bodies.get(other);
within_sight_dist
(within_sight_dist)
&& within_fov
&& entities_have_line_of_sight(self.pos, self.body, other_pos, other_body, read_data)
}

View File

@ -1112,7 +1112,7 @@ impl<'a> Widget for Diary<'a> {
"Stun-Resistance",
"Crit-Power",
"Energy Reward",
"Stealth",
"Stealth (Items)",
"Weapon Power",
"Weapon Speed",
"Weapon Poise",
@ -1206,9 +1206,16 @@ impl<'a> Widget for Diary<'a> {
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!("{:.2}", stealth)
"Stealth (Items)" => {
let stealth_perception_multiplier =
combat::perception_dist_multiplier_from_stealth(
Some(self.inventory),
None,
);
let txt =
format!("{:+.1}%", (1.0 - stealth_perception_multiplier) * 100.0);
txt
},
"Weapon Power" => match (main_weap_stats, off_weap_stats) {
(Some(m_stats), Some(o_stats)) => {