mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Fixed sneak toggle, sneaking no longer has sound, rolling can return to sneaking state, sneaking reduces aggro distance
This commit is contained in:
parent
e5cda89192
commit
8c1e1fdc5c
@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- A new secondary charged melee attack for the hammer
|
||||
- Added Dutch translations
|
||||
- Buff system
|
||||
- Sneaking lets you be closer to enemies without being detected
|
||||
|
||||
### Changed
|
||||
|
||||
|
@ -469,6 +469,7 @@ impl From<(&CharacterAbility, AbilityKey)> for CharacterState {
|
||||
timer: Duration::default(),
|
||||
stage_section: StageSection::Buildup,
|
||||
was_wielded: false, // false by default. utils might set it to true
|
||||
was_sneak: false,
|
||||
}),
|
||||
CharacterAbility::ComboMelee {
|
||||
stage_data,
|
||||
|
@ -100,6 +100,10 @@ impl CharacterState {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_stealthy(&self) -> bool {
|
||||
matches!(self, CharacterState::Sneak | CharacterState::Roll(_))
|
||||
}
|
||||
|
||||
pub fn is_attack(&self) -> bool {
|
||||
matches!(self,
|
||||
CharacterState::BasicMelee(_)
|
||||
|
@ -32,6 +32,8 @@ pub struct Data {
|
||||
pub stage_section: StageSection,
|
||||
/// Had weapon
|
||||
pub was_wielded: bool,
|
||||
/// Was sneaking
|
||||
pub was_sneak: bool,
|
||||
}
|
||||
|
||||
impl CharacterBehavior for Data {
|
||||
@ -102,6 +104,8 @@ impl CharacterBehavior for Data {
|
||||
// Done
|
||||
if self.was_wielded {
|
||||
update.character = CharacterState::Wielding;
|
||||
} else if self.was_sneak {
|
||||
update.character = CharacterState::Sneak;
|
||||
} else {
|
||||
update.character = CharacterState::Idle;
|
||||
}
|
||||
|
@ -53,4 +53,10 @@ impl CharacterBehavior for Data {
|
||||
attempt_swap_loadout(data, &mut update);
|
||||
update
|
||||
}
|
||||
|
||||
fn stand(&self, data: &JoinData) -> StateUpdate {
|
||||
let mut update = StateUpdate::from(data);
|
||||
update.character = CharacterState::Idle;
|
||||
update
|
||||
}
|
||||
}
|
||||
|
@ -373,6 +373,11 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
if let CharacterState::Roll(roll) = &mut update.character {
|
||||
roll.was_wielded = true;
|
||||
}
|
||||
} else if data.character.is_stealthy() {
|
||||
update.character = (ability, AbilityKey::Dodge).into();
|
||||
if let CharacterState::Roll(roll) = &mut update.character {
|
||||
roll.was_sneak = true;
|
||||
}
|
||||
} else {
|
||||
update.character = (ability, AbilityKey::Dodge).into();
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ use crate::{
|
||||
group,
|
||||
group::Invite,
|
||||
item::{tool::ToolKind, ItemKind},
|
||||
Agent, Alignment, Body, ControlAction, ControlEvent, Controller, Energy, GroupManip,
|
||||
LightEmitter, Loadout, MountState, Ori, PhysicsState, Pos, Scale, Stats, UnresolvedChatMsg,
|
||||
Vel,
|
||||
Agent, Alignment, Body, CharacterState, ControlAction, ControlEvent, Controller, Energy,
|
||||
GroupManip, LightEmitter, Loadout, MountState, Ori, PhysicsState, Pos, Scale, Stats,
|
||||
UnresolvedChatMsg, Vel,
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
metrics::SysMetrics,
|
||||
@ -60,6 +60,7 @@ impl<'a> System<'a> for Sys {
|
||||
ReadStorage<'a, Invite>,
|
||||
Read<'a, TimeOfDay>,
|
||||
ReadStorage<'a, LightEmitter>,
|
||||
ReadStorage<'a, CharacterState>,
|
||||
);
|
||||
|
||||
#[allow(clippy::or_fun_call)] // TODO: Pending review in #587
|
||||
@ -89,6 +90,7 @@ impl<'a> System<'a> for Sys {
|
||||
invites,
|
||||
time_of_day,
|
||||
light_emitter,
|
||||
char_states,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let start_time = std::time::Instant::now();
|
||||
@ -191,6 +193,7 @@ impl<'a> System<'a> for Sys {
|
||||
const SIGHT_DIST: f32 = 80.0;
|
||||
const MIN_ATTACK_DIST: f32 = 2.0;
|
||||
const MAX_FLEE_DIST: f32 = 20.0;
|
||||
const SNEAK_COEFFICIENT: f32 = 0.25;
|
||||
|
||||
let scale = scales.get(entity).map(|s| s.0).unwrap_or(1.0);
|
||||
|
||||
@ -557,14 +560,21 @@ impl<'a> System<'a> for Sys {
|
||||
if choose_target {
|
||||
// Search for new targets (this looks expensive, but it's only run occasionally)
|
||||
// TODO: Replace this with a better system that doesn't consider *all* entities
|
||||
let closest_entity = (&entities, &positions, &stats, alignments.maybe())
|
||||
let closest_entity = (&entities, &positions, &stats, alignments.maybe(), char_states.maybe())
|
||||
.join()
|
||||
.filter(|(e, e_pos, e_stats, e_alignment)| {
|
||||
((e_pos.0.distance_squared(pos.0) < SEARCH_DIST.powf(2.0) &&
|
||||
.filter(|(e, e_pos, e_stats, e_alignment, char_state)| {
|
||||
let mut search_dist = SEARCH_DIST;
|
||||
let mut listen_dist = LISTEN_DIST;
|
||||
if char_state.map_or(false, |c_s| c_s.is_stealthy()) {
|
||||
// TODO: make sneak more effective based on a stat like e_stats.fitness
|
||||
search_dist *= SNEAK_COEFFICIENT;
|
||||
listen_dist *= SNEAK_COEFFICIENT;
|
||||
}
|
||||
((e_pos.0.distance_squared(pos.0) < search_dist.powf(2.0) &&
|
||||
// Within our view
|
||||
(e_pos.0 - pos.0).try_normalized().map(|v| v.dot(*inputs.look_dir) > 0.15).unwrap_or(true))
|
||||
// Within listen distance
|
||||
|| e_pos.0.distance_squared(pos.0) < LISTEN_DIST.powf(2.0))
|
||||
|| e_pos.0.distance_squared(pos.0) < listen_dist.powf(2.0))
|
||||
&& *e != entity
|
||||
&& !e_stats.is_dead
|
||||
&& alignment
|
||||
@ -572,13 +582,13 @@ impl<'a> System<'a> for Sys {
|
||||
.unwrap_or(false)
|
||||
})
|
||||
// Can we even see them?
|
||||
.filter(|(_, e_pos, _, _)| terrain
|
||||
.filter(|(_, e_pos, _, _, _)| terrain
|
||||
.ray(pos.0 + Vec3::unit_z(), e_pos.0 + Vec3::unit_z())
|
||||
.until(Block::is_opaque)
|
||||
.cast()
|
||||
.0 >= e_pos.0.distance(pos.0))
|
||||
.min_by_key(|(_, e_pos, _, _)| (e_pos.0.distance_squared(pos.0) * 100.0) as i32)
|
||||
.map(|(e, _, _, _)| e);
|
||||
.min_by_key(|(_, e_pos, _, _, _)| (e_pos.0.distance_squared(pos.0) * 100.0) as i32)
|
||||
.map(|(e, _, _, _, _)| e);
|
||||
|
||||
if let Some(target) = closest_entity {
|
||||
agent.activity = Activity::Attack {
|
||||
|
@ -158,8 +158,10 @@ impl MovementEventMapper {
|
||||
if physics_state.on_ground && vel.magnitude() > 0.1
|
||||
|| !previous_state.on_ground && physics_state.on_ground
|
||||
{
|
||||
return if character_state.is_dodge() {
|
||||
return if matches!(character_state, CharacterState::Roll(_)) {
|
||||
SfxEvent::Roll
|
||||
} else if matches!(character_state, CharacterState::Sneak) {
|
||||
SfxEvent::Sneak
|
||||
} else {
|
||||
SfxEvent::Run
|
||||
};
|
||||
|
@ -161,6 +161,7 @@ fn maps_roll() {
|
||||
timer: Duration::default(),
|
||||
stage_section: states::utils::StageSection::Buildup,
|
||||
was_wielded: true,
|
||||
was_sneak: false,
|
||||
}),
|
||||
&PhysicsState {
|
||||
on_ground: true,
|
||||
|
@ -135,6 +135,7 @@ pub enum SfxEvent {
|
||||
Idle,
|
||||
Run,
|
||||
Roll,
|
||||
Sneak,
|
||||
Climb,
|
||||
GliderOpen,
|
||||
Glide,
|
||||
|
Loading…
Reference in New Issue
Block a user