Vines now ensnare you by applying a buff.

This commit is contained in:
Sam 2021-06-20 00:37:22 -05:00
parent 763461ebef
commit 0a32b676c8
12 changed files with 88 additions and 57 deletions

View File

@ -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}",

View File

@ -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);});

View File

@ -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,
}),
}
}

View File

@ -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,
}
}

View File

@ -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,

View File

@ -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()

View File

@ -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<Fluid>,
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;

View File

@ -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<Vox = Block> + 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;

View File

@ -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),

View File

@ -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")
},

View File

@ -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")),
}
}

View File

@ -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()