mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Distinguish stealth from armor and stealth from sneaking. Also fixes #1525.
- Armor and sneaking have exclusive effects on overall stealth, rather than armor taking effect only while sneaking. Gameplay: - Agents factor in stealth from armor in all cases, not only when sneaking. - Max stealth takes place when sneaking (final multiplier of `0.7`) and with stealth from armor up to `0.7` (`0.3` multiplier), resulting in a max distance modifier of about `0.5`, approximately what it was previously. - Min stealth score from armor is now 0 instead of 2. Internals: - Stealth getter accounts for sneaking in final calculation, not just armor. - Prevents potential division by zero. - Stealth getter returns value that should be multiplied instead of divided. - Legitimized stealth as a score between 0 and 1. Notes: - FIXME: Someone more familiar with the different armor types may want to adjust their stealths. - Armor stealths seem to be valued between `0.0` and `1.0`, and I've reinforced this in the code. However, it is possible, particularly for the `Dragonscale` armors, to cumulatively reach a value of `2.0`.
This commit is contained in:
parent
e5a840534b
commit
e473c47bcf
@ -34,6 +34,9 @@ use std::{ops::MulAssign, time::Duration};
|
|||||||
#[cfg(not(target_arch = "wasm32"))] use vek::*;
|
#[cfg(not(target_arch = "wasm32"))] use vek::*;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
|
||||||
|
const STEALTH_SUM_FROM_ITEMS_MAX: f32 = 0.3;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum GroupTarget {
|
pub enum GroupTarget {
|
||||||
InGroup,
|
InGroup,
|
||||||
@ -1164,13 +1167,48 @@ pub fn compute_max_energy_mod(inventory: Option<&Inventory>) -> f32 {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the sneak coefficient from armor. Agent perception distances are
|
pub fn is_stealth_from_items_maxed(inventory: Option<&Inventory>) -> bool {
|
||||||
/// divided by the resulting f32.
|
let sum = compute_stealth_sum_from_items(inventory);
|
||||||
|
|
||||||
|
sum >= STEALTH_SUM_FROM_ITEMS_MAX
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a value to be included as a multiplicative factor in perception
|
||||||
|
/// distance checks.
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn compute_stealth_coefficient(inventory: Option<&Inventory>) -> f32 {
|
pub fn perception_dist_multiplier_from_stealth(
|
||||||
// Starts with a value of 2.0 when summing the stats from each armor piece, and
|
inventory: Option<&Inventory>,
|
||||||
// defaults to a value of 2.0 if no inventory is equipped
|
character_state: Option<&CharacterState>,
|
||||||
inventory.map_or(2.0, |inv| {
|
) -> f32 {
|
||||||
|
const SNEAK_MULTIPLIER: f32 = 0.7;
|
||||||
|
const STEALTH_SUM_FROM_ITEMS_MIN: f32 = 0.0;
|
||||||
|
const MULTIPLIER_FROM_ITEMS_MAX: f32 = 0.7;
|
||||||
|
const MULTIPLIER_FROM_ITEMS_MIN: f32 = 1.0;
|
||||||
|
|
||||||
|
let stealth_sum = compute_stealth_sum_from_items(inventory);
|
||||||
|
let is_sneaking = character_state.map_or(false, |state| state.is_stealthy());
|
||||||
|
|
||||||
|
let mut multiplier;
|
||||||
|
|
||||||
|
if stealth_sum > STEALTH_SUM_FROM_ITEMS_MAX {
|
||||||
|
multiplier = MULTIPLIER_FROM_ITEMS_MAX;
|
||||||
|
} else if stealth_sum < STEALTH_SUM_FROM_ITEMS_MIN {
|
||||||
|
multiplier = MULTIPLIER_FROM_ITEMS_MIN;
|
||||||
|
} else {
|
||||||
|
multiplier = 1.0 - stealth_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_sneaking {
|
||||||
|
multiplier *= SNEAK_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiplier
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns sum of stealth from items equipped.
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn compute_stealth_sum_from_items(inventory: Option<&Inventory>) -> f32 {
|
||||||
|
inventory.map_or(0.0, |inv| {
|
||||||
inv.equipped_items()
|
inv.equipped_items()
|
||||||
.filter_map(|item| {
|
.filter_map(|item| {
|
||||||
if let ItemKind::Armor(armor) = &item.kind() {
|
if let ItemKind::Armor(armor) = &item.kind() {
|
||||||
@ -1179,7 +1217,7 @@ pub fn compute_stealth_coefficient(inventory: Option<&Inventory>) -> f32 {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.fold(2.0, |a, b| a + b.max(0.0))
|
.fold(0.0, |a, b| a + b)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
combat::compute_stealth_coefficient,
|
combat::perception_dist_multiplier_from_stealth,
|
||||||
comp::{
|
comp::{
|
||||||
self,
|
self,
|
||||||
agent::{
|
agent::{
|
||||||
@ -2429,26 +2429,17 @@ impl<'a> AgentData<'a> {
|
|||||||
other_pos: &Pos,
|
other_pos: &Pos,
|
||||||
read_data: &ReadData,
|
read_data: &ReadData,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let other_stealth_coefficient = {
|
let other_stealth_multiplier = {
|
||||||
let is_other_stealthy = read_data
|
let other_inventory = read_data.inventories.get(other);
|
||||||
.char_states
|
let other_char_state = read_data.char_states.get(other);
|
||||||
.get(other)
|
|
||||||
.map_or(false, CharacterState::is_stealthy);
|
|
||||||
|
|
||||||
if is_other_stealthy {
|
perception_dist_multiplier_from_stealth(other_inventory, other_char_state)
|
||||||
// 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
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let dist_sqrd = other_pos.0.distance_squared(self.pos.0);
|
|
||||||
|
|
||||||
let within_sight_dist = {
|
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)
|
dist_sqrd < sight_dist.powi(2)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2458,7 +2449,7 @@ impl<'a> AgentData<'a> {
|
|||||||
|
|
||||||
let other_body = read_data.bodies.get(other);
|
let other_body = read_data.bodies.get(other);
|
||||||
|
|
||||||
within_sight_dist
|
(within_sight_dist)
|
||||||
&& within_fov
|
&& within_fov
|
||||||
&& entities_have_line_of_sight(self.pos, self.body, other_pos, other_body, read_data)
|
&& entities_have_line_of_sight(self.pos, self.body, other_pos, other_body, read_data)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user