From 0a32b676c84373b9d648f735d9c9066a26d75a21 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 20 Jun 2021 00:37:22 -0500 Subject: [PATCH] Vines now ensnare you by applying a buff. --- assets/voxygen/i18n/en/buff.ron | 2 + common/src/cmd.rs | 1 + common/src/comp/ability.rs | 2 +- common/src/comp/body.rs | 3 + common/src/comp/buff.rs | 9 ++ common/src/states/utils.rs | 2 +- common/systems/src/buff.rs | 89 +++++++++++-------- common/systems/src/phys.rs | 10 +-- .../audio/sfx/event_mapper/movement/tests.rs | 16 ++-- voxygen/src/hud/chat.rs | 2 +- voxygen/src/hud/mod.rs | 3 + voxygen/src/hud/util.rs | 6 +- 12 files changed, 88 insertions(+), 57 deletions(-) diff --git a/assets/voxygen/i18n/en/buff.ron b/assets/voxygen/i18n/en/buff.ron index 1109fc4120..e2c4ed10c6 100644 --- a/assets/voxygen/i18n/en/buff.ron +++ b/assets/voxygen/i18n/en/buff.ron @@ -34,6 +34,8 @@ "buff.desc.frozen": "Your movements and attacks are slowed.", "buff.title.wet": "Wet", "buff.desc.wet": "The ground rejects your feet, making it hard to stop.", + "buff.title.ensnared": "Ensnared", + "buff.desc.ensnared": "Vines grasp at your legs, impeding your movement.", // Buffs stats "buff.stat.health": "Restores {str_total} Health", "buff.stat.increase_max_stamina": "Raises Maximum Stamina by {strength}", diff --git a/common/src/cmd.rs b/common/src/cmd.rs index 0a1b91eba6..c9991a74c2 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -197,6 +197,7 @@ lazy_static! { BuffKind::Crippled => "crippled", BuffKind::Frozen => "frozen", BuffKind::Wet => "wet", + BuffKind::Ensnared => "ensnared", }; let mut buff_parser = HashMap::new(); BuffKind::iter().for_each(|kind| {buff_parser.insert(string_from_buff(kind).to_string(), kind);}); diff --git a/common/src/comp/ability.rs b/common/src/comp/ability.rs index c6e18f530f..72e31105f4 100644 --- a/common/src/comp/ability.rs +++ b/common/src/comp/ability.rs @@ -1822,7 +1822,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState { }, timer: Duration::default(), stage_section: StageSection::Buildup, - achieved_radius: 0, + achieved_radius: summon_distance.0.floor() as i32 - 1, }), } } diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 6c999c3635..7117c1189c 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -659,6 +659,9 @@ impl Body { Body::Object(object::Body::HaniwaSentry) => true, _ => false, }, + BuffKind::Ensnared => { + matches!(self, Body::BipedLarge(b) if matches!(b.species, biped_large::Species::Harvester)) + }, _ => false, } } diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs index 412ab0affa..c0472798a3 100644 --- a/common/src/comp/buff.rs +++ b/common/src/comp/buff.rs @@ -69,6 +69,10 @@ pub enum BuffKind { /// Strength scales the friction you ignore non-linearly. 0.5 is 50% ground /// friction, 1.0 is 33% ground friction. Wet, + /// Makes you move slower. + /// Strength scales the movement speed debuff non-linearly. 0.5 is 50% + /// speed, 1.0 is 33% speed. + Ensnared, } #[cfg(not(target_arch = "wasm32"))] @@ -91,6 +95,7 @@ impl BuffKind { BuffKind::Frenzied => true, BuffKind::Frozen => false, BuffKind::Wet => false, + BuffKind::Ensnared => false, } } @@ -319,6 +324,10 @@ impl Buff { vec![BuffEffect::GroundFriction(1.0 - nn_scaling(data.strength))], data.duration, ), + BuffKind::Ensnared => ( + vec![BuffEffect::MovementSpeed(1.0 - nn_scaling(data.strength))], + data.duration, + ), }; Buff { kind, diff --git a/common/src/states/utils.rs b/common/src/states/utils.rs index 8b96c3ff4c..4027e4eda4 100644 --- a/common/src/states/utils.rs +++ b/common/src/states/utils.rs @@ -592,7 +592,7 @@ pub fn handle_jump(data: &JoinData, update: &mut StateUpdate, strength: f32) -> .map(|impulse| { update.local_events.push_front(LocalEvent::Jump( data.entity, - strength * impulse / data.mass.0, + strength * impulse / data.mass.0 * data.stats.move_speed_modifier, )); }) .is_some() diff --git a/common/systems/src/buff.rs b/common/systems/src/buff.rs index 3275bb60bb..f25dda0a68 100644 --- a/common/systems/src/buff.rs +++ b/common/systems/src/buff.rs @@ -1,11 +1,15 @@ use common::{ comp::{ + buff::{ + Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, + Buffs, + }, fluid_dynamics::{Fluid, LiquidKind}, - Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs, Energy, Health, HealthChange, HealthSource, Inventory, ModifierKind, PhysicsState, Stats, }, event::{EventBus, ServerEvent}, resources::DeltaTime, + terrain::SpriteKind, Damage, DamageSource, }; use common_ecs::{Job, Origin, Phase, System}; @@ -55,25 +59,52 @@ impl<'a> System<'a> for Sys { ) .join() { - let in_fluid = physics_state.and_then(|p| p.in_fluid); - - if matches!( - in_fluid, - Some(Fluid::Liquid { - kind: LiquidKind::Lava, - .. - }) - ) && !buff_comp.contains(BuffKind::Burning) - { - server_emitter.emit(ServerEvent::Buff { - entity, - buff_change: BuffChange::Add(Buff::new( - BuffKind::Burning, - BuffData::new(200.0, None), - vec![BuffCategory::Natural], - BuffSource::World, - )), - }); + // Apply buffs to entity based off of their current physics_state + if let Some(physics_state) = physics_state { + if matches!( + physics_state.on_ground.and_then(|b| b.get_sprite()), + Some(SpriteKind::EnsnaringVines) + ) { + server_emitter.emit(ServerEvent::Buff { + entity, + buff_change: BuffChange::Add(Buff::new( + BuffKind::Ensnared, + BuffData::new(1.5, Some(Duration::from_secs_f32(1.0))), + Vec::new(), + BuffSource::World, + )), + }); + } + if matches!( + physics_state.in_fluid, + Some(Fluid::Liquid { + kind: LiquidKind::Lava, + .. + }) + ) { + server_emitter.emit(ServerEvent::Buff { + entity, + buff_change: BuffChange::Add(Buff::new( + BuffKind::Burning, + BuffData::new(200.0, None), + vec![BuffCategory::Natural], + BuffSource::World, + )), + }); + } else if matches!( + physics_state.in_fluid, + Some(Fluid::Liquid { + kind: LiquidKind::Water, + .. + }) + ) { + if buff_comp.kinds.contains_key(&BuffKind::Burning) { + server_emitter.emit(ServerEvent::Buff { + entity, + buff_change: BuffChange::RemoveByKind(BuffKind::Burning), + }); + } + } } let (buff_comp_kinds, buff_comp_buffs): ( @@ -90,14 +121,14 @@ impl<'a> System<'a> for Sys { if let Some((Some(buff), id)) = ids.get(0).map(|id| (buff_comp_buffs.get_mut(id), id)) { - tick_buff(*id, buff, dt, in_fluid, |id| expired_buffs.push(id)); + tick_buff(*id, buff, dt, |id| expired_buffs.push(id)); } } else { for (id, buff) in buff_comp_buffs .iter_mut() .filter(|(i, _)| ids.iter().any(|id| id == *i)) { - tick_buff(*id, buff, dt, in_fluid, |id| expired_buffs.push(id)); + tick_buff(*id, buff, dt, |id| expired_buffs.push(id)); } } } @@ -257,7 +288,6 @@ fn tick_buff( id: u64, buff: &mut Buff, dt: f32, - in_fluid: Option, mut expire_buff: impl FnMut(u64), ) { // If a buff is recently applied from an aura, do not tick duration @@ -269,19 +299,6 @@ fn tick_buff( return; } if let Some(remaining_time) = &mut buff.time { - // Extinguish Burning buff when in water - if matches!(buff.kind, BuffKind::Burning) - && matches!( - in_fluid, - Some(Fluid::Liquid { - kind: LiquidKind::Water, - .. - }) - ) - { - *remaining_time = Duration::default(); - } - if let Some(new_duration) = remaining_time.checked_sub(Duration::from_secs_f32(dt)) { // The buff still continues. *remaining_time = new_duration; diff --git a/common/systems/src/phys.rs b/common/systems/src/phys.rs index e305270449..a191d36c65 100644 --- a/common/systems/src/phys.rs +++ b/common/systems/src/phys.rs @@ -10,7 +10,7 @@ use common::{ outcome::Outcome, resources::DeltaTime, states, - terrain::{Block, SpriteKind, TerrainGrid}, + terrain::{Block, TerrainGrid}, uid::Uid, util::{Projection, SpatialGrid}, vol::{BaseVol, ReadVol}, @@ -1596,13 +1596,7 @@ fn box_voxel_collision<'a, T: BaseVol + ReadVol>( } } physics_state.on_wall = on_wall; - let fric_mod = read.stats.get(entity).map_or(1.0, |s| s.friction_modifier) - * physics_state - .on_ground - .map_or(1.0, |b| match b.get_sprite() { - Some(SpriteKind::EnsnaringVines) => 5.0, - _ => 1.0, - }); + let fric_mod = read.stats.get(entity).map_or(1.0, |s| s.friction_modifier); if physics_state.on_ground.is_some() || (physics_state.on_wall.is_some() && climbing) { vel.0 *= (1.0 - FRIC_GROUND.min(1.0) * fric_mod).powf(dt.0 * 60.0); physics_state.ground_vel = ground_vel; diff --git a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs index 919c5187ea..047cc80a9f 100644 --- a/voxygen/src/audio/sfx/event_mapper/movement/tests.rs +++ b/voxygen/src/audio/sfx/event_mapper/movement/tests.rs @@ -6,7 +6,7 @@ use common::{ Ori, PhysicsState, }, states, - terrain::BlockKind, + terrain::{Block, BlockKind}, }; use std::time::{Duration, Instant}; @@ -95,7 +95,7 @@ fn maps_idle() { let result = MovementEventMapper::map_movement_event( &CharacterState::Idle {}, &PhysicsState { - on_ground: true, + on_ground: Some(Block::empty()), ..Default::default() }, &PreviousEntityState { @@ -117,7 +117,7 @@ fn maps_run_with_sufficient_velocity() { let result = MovementEventMapper::map_movement_event( &CharacterState::Idle {}, &PhysicsState { - on_ground: true, + on_ground: Some(Block::empty()), ..Default::default() }, &PreviousEntityState { @@ -139,7 +139,7 @@ fn does_not_map_run_with_insufficient_velocity() { let result = MovementEventMapper::map_movement_event( &CharacterState::Idle {}, &PhysicsState { - on_ground: true, + on_ground: Some(Block::empty()), ..Default::default() }, &PreviousEntityState { @@ -194,7 +194,7 @@ fn maps_roll() { was_combo: None, }), &PhysicsState { - on_ground: true, + on_ground: Some(Block::empty()), ..Default::default() }, &PreviousEntityState { @@ -216,7 +216,7 @@ fn maps_land_on_ground_to_run() { let result = MovementEventMapper::map_movement_event( &CharacterState::Idle {}, &PhysicsState { - on_ground: true, + on_ground: Some(Block::empty()), ..Default::default() }, &PreviousEntityState { @@ -296,7 +296,7 @@ fn maps_glider_close_when_landing() { let result = MovementEventMapper::map_movement_event( &CharacterState::Idle {}, &PhysicsState { - on_ground: true, + on_ground: Some(Block::empty()), ..Default::default() }, &PreviousEntityState { @@ -317,7 +317,7 @@ fn maps_glider_close_when_landing() { fn maps_quadrupeds_running() { let result = MovementEventMapper::map_non_humanoid_movement_event( &PhysicsState { - on_ground: true, + on_ground: Some(Block::empty()), ..Default::default() }, Vec3::new(0.5, 0.8, 0.0), diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs index 2b4c70081a..5c7638ee2e 100644 --- a/voxygen/src/hud/chat.rs +++ b/voxygen/src/hud/chat.rs @@ -769,7 +769,7 @@ fn insert_killing_buff(buff: BuffKind, localized_strings: &Localization, templat tracing::error!("Player was killed by a positive buff!"); localized_strings.get("hud.outcome.mysterious") }, - BuffKind::Wet => { + BuffKind::Wet | BuffKind::Ensnared => { tracing::error!("Player was killed by a debuff that doesn't do damage!"); localized_strings.get("hud.outcome.mysterious") }, diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index fa478cb929..5d1b45e4e0 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -3822,6 +3822,7 @@ pub fn get_buff_image(buff: BuffKind, imgs: &Imgs) -> conrod_core::image::Id { BuffKind::Crippled { .. } => imgs.debuff_crippled_0, BuffKind::Frozen { .. } => imgs.debuff_frozen_0, BuffKind::Wet { .. } => imgs.debuff_wet_0, + BuffKind::Ensnared { .. } => imgs.debuff_crippled_0, } } @@ -3844,6 +3845,7 @@ pub fn get_buff_title(buff: BuffKind, localized_strings: &Localization) -> &str BuffKind::Crippled { .. } => localized_strings.get("buff.title.crippled"), BuffKind::Frozen { .. } => localized_strings.get("buff.title.frozen"), BuffKind::Wet { .. } => localized_strings.get("buff.title.wet"), + BuffKind::Ensnared { .. } => localized_strings.get("buff.title.ensnared"), } } @@ -3878,6 +3880,7 @@ pub fn get_buff_desc(buff: BuffKind, data: BuffData, localized_strings: &Localiz BuffKind::Crippled { .. } => Cow::Borrowed(localized_strings.get("buff.desc.crippled")), BuffKind::Frozen { .. } => Cow::Borrowed(localized_strings.get("buff.desc.frozen")), BuffKind::Wet { .. } => Cow::Borrowed(localized_strings.get("buff.desc.wet")), + BuffKind::Ensnared { .. } => Cow::Borrowed(localized_strings.get("buff.desc.ensnared")), } } diff --git a/voxygen/src/hud/util.rs b/voxygen/src/hud/util.rs index c66f332cfd..5f9f15142b 100644 --- a/voxygen/src/hud/util.rs +++ b/voxygen/src/hud/util.rs @@ -132,7 +132,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> String { | BuffKind::Crippled | BuffKind::Frenzied | BuffKind::Frozen - | BuffKind::Wet => continue, + | BuffKind::Wet + | BuffKind::Ensnared => continue, }; write!(&mut description, "{}", buff_desc).unwrap(); @@ -156,7 +157,8 @@ pub fn consumable_desc(effects: &[Effect], i18n: &Localization) -> String { | BuffKind::Crippled | BuffKind::Frenzied | BuffKind::Frozen - | BuffKind::Wet => continue, + | BuffKind::Wet + | BuffKind::Ensnared => continue, } } else if let BuffKind::Saturation | BuffKind::Regeneration = buff.kind { i18n.get("buff.text.every_second").to_string()