Merge branch 'sam/potion-tweaks' into 'master'

Potion tweaks

See merge request veloren/veloren!2976
This commit is contained in:
Samuel Keiffer 2021-10-31 21:12:08 +00:00
commit e692f49463
4 changed files with 90 additions and 91 deletions

View File

@ -2,14 +2,15 @@ use crate::{
comp::{
self,
inventory::item::{armor::Protection, ItemKind},
Inventory,
CharacterState, Inventory,
},
states,
util::Dir,
};
use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
use std::ops::Mul;
use std::{ops::Mul, time::Duration};
use vek::*;
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
@ -52,6 +53,52 @@ pub enum PoiseState {
KnockedDown,
}
impl PoiseState {
pub fn poise_effect(&self, was_wielded: bool) -> (Option<CharacterState>, Option<f32>) {
use states::{
stunned::{Data, StaticData},
utils::StageSection,
};
// charstate_parameters is Option<(buildup_duration, recover_duration,
// movement_speed)>
let (charstate_parameters, impulse) = match self {
PoiseState::Normal => (None, None),
PoiseState::Interrupted => (
Some((Duration::from_millis(125), Duration::from_millis(125), 0.80)),
None,
),
PoiseState::Stunned => (
Some((Duration::from_millis(300), Duration::from_millis(300), 0.65)),
Some(5.0),
),
PoiseState::Dazed => (
Some((Duration::from_millis(600), Duration::from_millis(250), 0.45)),
Some(10.0),
),
PoiseState::KnockedDown => (
Some((Duration::from_millis(750), Duration::from_millis(500), 0.4)),
Some(10.0),
),
};
(
charstate_parameters.map(|(buildup_duration, recover_duration, movement_speed)| {
CharacterState::Stunned(Data {
static_data: StaticData {
buildup_duration,
recover_duration,
movement_speed,
poise_state: *self,
},
timer: Duration::default(),
stage_section: StageSection::Buildup,
was_wielded,
})
}),
impulse,
)
}
}
impl Poise {
/// Maximum value allowed for poise before scaling
const MAX_POISE: u16 = u16::MAX - 1;

View File

@ -7,8 +7,7 @@ use common::{
comp::{
self, character_state::OutputEvents, inventory::item::MaterialStatManifest, Beam, Body,
CharacterState, Combo, Controller, Density, Energy, Health, Inventory, InventoryManip,
Mass, Melee, Mounting, Ori, PhysicsState, Poise, PoiseState, Pos, SkillSet, StateUpdate,
Stats, Vel,
Mass, Melee, Mounting, Ori, PhysicsState, Poise, Pos, SkillSet, StateUpdate, Stats, Vel,
},
event::{EventBus, LocalEvent, ServerEvent},
outcome::Outcome,
@ -21,7 +20,6 @@ use common::{
uid::Uid,
};
use common_ecs::{Job, Origin, Phase, System};
use std::time::Duration;
#[derive(SystemData)]
pub struct ReadData<'a> {
@ -142,92 +140,22 @@ impl<'a> System<'a> for Sys {
let was_wielded = char_state.is_wield();
let poise_state = poise.poise_state();
let pos = pos.0;
match poise_state {
PoiseState::Normal => {},
PoiseState::Interrupted => {
poise.reset();
*char_state = CharacterState::Stunned(common::states::stunned::Data {
static_data: common::states::stunned::StaticData {
buildup_duration: Duration::from_millis(125),
recover_duration: Duration::from_millis(125),
movement_speed: 0.80,
poise_state,
},
timer: Duration::default(),
stage_section: common::states::utils::StageSection::Buildup,
was_wielded,
});
outcomes.push(Outcome::PoiseChange {
pos,
state: PoiseState::Interrupted,
});
},
PoiseState::Stunned => {
poise.reset();
*char_state = CharacterState::Stunned(common::states::stunned::Data {
static_data: common::states::stunned::StaticData {
buildup_duration: Duration::from_millis(300),
recover_duration: Duration::from_millis(300),
movement_speed: 0.65,
poise_state,
},
timer: Duration::default(),
stage_section: common::states::utils::StageSection::Buildup,
was_wielded,
});
outcomes.push(Outcome::PoiseChange {
pos,
state: PoiseState::Stunned,
});
if let (Some(stunned_state), impulse_strength) =
poise_state.poise_effect(was_wielded)
{
// Reset poise if there is some stunned state to apply
poise.reset();
*char_state = stunned_state;
outcomes.push(Outcome::PoiseChange {
pos,
state: poise_state,
});
if let Some(impulse_strength) = impulse_strength {
server_emitter.emit(ServerEvent::Knockback {
entity,
impulse: 5.0 * *poise.knockback(),
impulse: impulse_strength * *poise.knockback(),
});
},
PoiseState::Dazed => {
poise.reset();
*char_state = CharacterState::Stunned(common::states::stunned::Data {
static_data: common::states::stunned::StaticData {
buildup_duration: Duration::from_millis(600),
recover_duration: Duration::from_millis(250),
movement_speed: 0.45,
poise_state,
},
timer: Duration::default(),
stage_section: common::states::utils::StageSection::Buildup,
was_wielded,
});
outcomes.push(Outcome::PoiseChange {
pos,
state: PoiseState::Dazed,
});
server_emitter.emit(ServerEvent::Knockback {
entity,
impulse: 10.0 * *poise.knockback(),
});
},
PoiseState::KnockedDown => {
poise.reset();
*char_state = CharacterState::Stunned(common::states::stunned::Data {
static_data: common::states::stunned::StaticData {
buildup_duration: Duration::from_millis(750),
recover_duration: Duration::from_millis(500),
movement_speed: 0.4,
poise_state,
},
timer: Duration::default(),
stage_section: common::states::utils::StageSection::Buildup,
was_wielded,
});
outcomes.push(Outcome::PoiseChange {
pos,
state: PoiseState::KnockedDown,
});
server_emitter.emit(ServerEvent::Knockback {
entity,
impulse: 10.0 * *poise.knockback(),
});
},
}
}
}

View File

@ -1095,14 +1095,35 @@ pub fn handle_teleport_to(server: &Server, entity: EcsEntity, target: Uid, max_r
pub fn handle_entity_attacked_hook(server: &Server, entity: EcsEntity) {
let ecs = &server.state.ecs();
let server_eventbus = ecs.read_resource::<EventBus<ServerEvent>>();
let mut outcomes = ecs.write_resource::<Vec<Outcome>>();
if let Some(mut char_state) = ecs.write_storage::<CharacterState>().get_mut(entity) {
if let (Some(mut char_state), Some(mut poise), Some(pos)) = (
ecs.write_storage::<CharacterState>().get_mut(entity),
ecs.write_storage::<Poise>().get_mut(entity),
ecs.read_storage::<Pos>().get(entity),
) {
// Interrupt sprite interaction and item use if any attack is applied to entity
if matches!(
*char_state,
CharacterState::SpriteInteract(_) | CharacterState::UseItem(_)
) {
*char_state = CharacterState::Idle(common::states::idle::Data { is_sneaking: false });
let poise_state = comp::poise::PoiseState::Dazed;
let was_wielded = char_state.is_wield();
if let (Some(stunned_state), impulse_strength) = poise_state.poise_effect(was_wielded) {
// Reset poise if there is some stunned state to apply
poise.reset();
*char_state = stunned_state;
outcomes.push(Outcome::PoiseChange {
pos: pos.0,
state: poise_state,
});
if let Some(impulse_strength) = impulse_strength {
server_eventbus.emit_now(ServerEvent::Knockback {
entity,
impulse: impulse_strength * *poise.knockback(),
});
}
}
}
}

View File

@ -1173,9 +1173,12 @@ fn consumable_bags(economy: Option<&trade::SiteInformation>, rng: &mut impl Rng)
.and_then(|e| e.unconsumed_stock.get(&Good::Food))
.copied()
.map_or(Some(10_000.0), |food| Some(food.max(10_000.0)));
// Reduce amount of potions so merchants do not oversupply potions.
// TODO: Maybe remove when merchants and their inventories are rtsim?
let mut potions = economy
.and_then(|e| e.unconsumed_stock.get(&Good::Potions))
.copied();
.copied()
.map(|potions| potions.powf(0.25));
let goods = [
(Good::Food, &mut food, &mut bag3),