mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'knightresspaladin/fix-death-by-heal' into 'master'
Fix Bug Causing Healing Aura to Occasionally Kill Its User See merge request veloren/veloren!2646
This commit is contained in:
commit
09eff33562
@ -1443,8 +1443,8 @@ impl CharacterAbility {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
||||
fn from((ability, ability_info): (&CharacterAbility, AbilityInfo)) -> Self {
|
||||
impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
||||
fn from((ability, ability_info, data): (&CharacterAbility, AbilityInfo, &JoinData)) -> Self {
|
||||
match ability {
|
||||
CharacterAbility::BasicMelee {
|
||||
buildup_duration,
|
||||
@ -1923,6 +1923,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
||||
range: *range,
|
||||
ability_info,
|
||||
scales_with_combo: *scales_with_combo,
|
||||
combo_at_cast: data.combo.counter(),
|
||||
specifier: *specifier,
|
||||
},
|
||||
timer: Duration::default(),
|
||||
|
@ -34,6 +34,8 @@ pub struct StaticData {
|
||||
pub ability_info: AbilityInfo,
|
||||
/// Whether the aura's effect scales with the user's current combo
|
||||
pub scales_with_combo: bool,
|
||||
/// Combo at the time the aura is first cast
|
||||
pub combo_at_cast: u32,
|
||||
/// Used to specify aura to the frontend
|
||||
pub specifier: Specifier,
|
||||
}
|
||||
@ -76,7 +78,6 @@ impl CharacterBehavior for Data {
|
||||
targets,
|
||||
);
|
||||
if self.static_data.scales_with_combo {
|
||||
let combo = data.combo.counter();
|
||||
match aura.aura_kind {
|
||||
AuraKind::Buff {
|
||||
kind: _,
|
||||
@ -84,12 +85,13 @@ impl CharacterBehavior for Data {
|
||||
category: _,
|
||||
source: _,
|
||||
} => {
|
||||
data.strength *= 1.0 + (combo as f32).log(2.0_f32);
|
||||
data.strength *=
|
||||
1.0 + (self.static_data.combo_at_cast.max(1) as f32).log(2.0);
|
||||
},
|
||||
}
|
||||
update.server_events.push_front(ServerEvent::ComboChange {
|
||||
entity: data.entity,
|
||||
change: -(combo as i32),
|
||||
change: -(self.static_data.combo_at_cast as i32),
|
||||
});
|
||||
}
|
||||
update.server_events.push_front(ServerEvent::Aura {
|
||||
|
@ -237,7 +237,7 @@ impl Body {
|
||||
}
|
||||
|
||||
/// Handles updating `Components` to move player based on state of `JoinData`
|
||||
pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
pub fn handle_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) {
|
||||
let submersion = data
|
||||
.physics
|
||||
.in_liquid()
|
||||
@ -262,7 +262,7 @@ pub fn handle_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
|
||||
/// Updates components to move player as if theyre on ground or in air
|
||||
#[allow(clippy::assign_op_pattern)] // TODO: Pending review in #587
|
||||
fn basic_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
fn basic_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) {
|
||||
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
|
||||
|
||||
let accel = if data.physics.on_ground.is_some() {
|
||||
@ -303,7 +303,11 @@ fn basic_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
}
|
||||
|
||||
/// Handles forced movement
|
||||
pub fn handle_forced_movement(data: &JoinData, update: &mut StateUpdate, movement: ForcedMovement) {
|
||||
pub fn handle_forced_movement(
|
||||
data: &JoinData<'_>,
|
||||
update: &mut StateUpdate,
|
||||
movement: ForcedMovement,
|
||||
) {
|
||||
match movement {
|
||||
ForcedMovement::Forward { strength } => {
|
||||
let strength = strength * data.stats.move_speed_modifier * data.stats.friction_modifier;
|
||||
@ -345,7 +349,7 @@ pub fn handle_forced_movement(data: &JoinData, update: &mut StateUpdate, movemen
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, efficiency: f32) {
|
||||
pub fn handle_orientation(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) {
|
||||
if let Some(dir) = (is_strafing(data, update) || update.character.is_attack())
|
||||
.then(|| data.inputs.look_dir.to_horizontal().unwrap_or_default())
|
||||
.or_else(|| Dir::from_unnormalized(data.inputs.move_dir.into()))
|
||||
@ -361,7 +365,12 @@ pub fn handle_orientation(data: &JoinData, update: &mut StateUpdate, efficiency:
|
||||
}
|
||||
|
||||
/// Updates components to move player as if theyre swimming
|
||||
fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, submersion: f32) -> bool {
|
||||
fn swim_move(
|
||||
data: &JoinData<'_>,
|
||||
update: &mut StateUpdate,
|
||||
efficiency: f32,
|
||||
submersion: f32,
|
||||
) -> bool {
|
||||
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
|
||||
if let Some(force) = data.body.swim_thrust() {
|
||||
let force = efficiency * force;
|
||||
@ -399,7 +408,7 @@ fn swim_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32, submers
|
||||
}
|
||||
|
||||
/// Updates components to move entity as if it's flying
|
||||
pub fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) -> bool {
|
||||
pub fn fly_move(data: &JoinData<'_>, update: &mut StateUpdate, efficiency: f32) -> bool {
|
||||
let efficiency = efficiency * data.stats.move_speed_modifier * data.stats.friction_modifier;
|
||||
|
||||
let glider = match data.character {
|
||||
@ -466,14 +475,14 @@ pub fn fly_move(data: &JoinData, update: &mut StateUpdate, efficiency: f32) -> b
|
||||
|
||||
/// Checks if an input related to an attack is held. If one is, moves entity
|
||||
/// into wielding state
|
||||
pub fn handle_wield(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn handle_wield(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.controller.queued_inputs.keys().any(|i| i.is_ability()) {
|
||||
attempt_wield(data, update);
|
||||
}
|
||||
}
|
||||
|
||||
/// If a tool is equipped, goes into Equipping state, otherwise goes to Idle
|
||||
pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_wield(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
// Closure to get equip time provided an equip slot if a tool is equipped in
|
||||
// equip slot
|
||||
let equip_time = |equip_slot| {
|
||||
@ -511,32 +520,32 @@ pub fn attempt_wield(data: &JoinData, update: &mut StateUpdate) {
|
||||
}
|
||||
|
||||
/// Checks that player can `Sit` and updates `CharacterState` if so
|
||||
pub fn attempt_sit(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_sit(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() {
|
||||
update.character = CharacterState::Sit;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attempt_dance(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_dance(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() && data.body.is_humanoid() {
|
||||
update.character = CharacterState::Dance;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attempt_talk(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_talk(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() {
|
||||
update.character = CharacterState::Talk;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attempt_sneak(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_sneak(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.physics.on_ground.is_some() && data.body.is_humanoid() {
|
||||
update.character = CharacterState::Sneak;
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that player can `Climb` and updates `CharacterState` if so
|
||||
pub fn handle_climb(data: &JoinData, update: &mut StateUpdate) -> bool {
|
||||
pub fn handle_climb(data: &JoinData<'_>, update: &mut StateUpdate) -> bool {
|
||||
if data.inputs.climb.is_some()
|
||||
&& data.physics.on_wall.is_some()
|
||||
&& data.physics.on_ground.is_none()
|
||||
@ -557,7 +566,7 @@ pub fn handle_climb(data: &JoinData, update: &mut StateUpdate) -> bool {
|
||||
}
|
||||
|
||||
/// Checks that player can Swap Weapons and updates `Loadout` if so
|
||||
pub fn attempt_swap_equipped_weapons(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_swap_equipped_weapons(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data
|
||||
.inventory
|
||||
.equipped(EquipSlot::InactiveMainhand)
|
||||
@ -573,7 +582,7 @@ pub fn attempt_swap_equipped_weapons(data: &JoinData, update: &mut StateUpdate)
|
||||
|
||||
/// Handles inventory manipulations that affect the loadout
|
||||
pub fn handle_manipulate_loadout(
|
||||
data: &JoinData,
|
||||
data: &JoinData<'_>,
|
||||
update: &mut StateUpdate,
|
||||
inv_action: InventoryAction,
|
||||
) {
|
||||
@ -619,7 +628,7 @@ pub fn handle_manipulate_loadout(
|
||||
}
|
||||
|
||||
/// Checks that player can wield the glider and updates `CharacterState` if so
|
||||
pub fn attempt_glide_wield(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_glide_wield(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if data.inventory.equipped(EquipSlot::Glider).is_some()
|
||||
&& !data
|
||||
.physics
|
||||
@ -633,7 +642,7 @@ pub fn attempt_glide_wield(data: &JoinData, update: &mut StateUpdate) {
|
||||
}
|
||||
|
||||
/// Checks that player can jump and sends jump event if so
|
||||
pub fn handle_jump(data: &JoinData, update: &mut StateUpdate, strength: f32) -> bool {
|
||||
pub fn handle_jump(data: &JoinData<'_>, update: &mut StateUpdate, strength: f32) -> bool {
|
||||
(input_is_pressed(data, InputKind::Jump) && data.physics.on_ground.is_some())
|
||||
.then(|| data.body.jump_impulse())
|
||||
.flatten()
|
||||
@ -646,7 +655,7 @@ pub fn handle_jump(data: &JoinData, update: &mut StateUpdate, strength: f32) ->
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
||||
fn handle_ability(data: &JoinData<'_>, update: &mut StateUpdate, input: InputKind) {
|
||||
let hands = get_hands(data);
|
||||
|
||||
// Mouse1 and Skill1 always use the MainHand slot
|
||||
@ -699,12 +708,13 @@ fn handle_ability(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
||||
matches!(equip_slot, EquipSlot::ActiveOffhand),
|
||||
input,
|
||||
),
|
||||
data,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_ability_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn handle_ability_input(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if let Some(input) = data
|
||||
.controller
|
||||
.queued_inputs
|
||||
@ -715,7 +725,7 @@ pub fn handle_ability_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_input(data: &JoinData, update: &mut StateUpdate, input: InputKind) {
|
||||
pub fn handle_input(data: &JoinData<'_>, update: &mut StateUpdate, input: InputKind) {
|
||||
match input {
|
||||
InputKind::Primary | InputKind::Secondary | InputKind::Ability(_) => {
|
||||
handle_ability(data, update, input)
|
||||
@ -729,7 +739,7 @@ pub fn handle_input(data: &JoinData, update: &mut StateUpdate, input: InputKind)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attempt_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn attempt_input(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
// TODO: look into using first() when it becomes stable
|
||||
if let Some(input) = data.controller.queued_inputs.keys().next() {
|
||||
handle_input(data, update, *input);
|
||||
@ -737,7 +747,7 @@ pub fn attempt_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
}
|
||||
|
||||
/// Checks that player can block, then attempts to block
|
||||
pub fn handle_block_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn handle_block_input(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
let can_block =
|
||||
|equip_slot| matches!(unwrap_tool_data(data, equip_slot), Some(tool) if tool.can_block());
|
||||
let hands = get_hands(data);
|
||||
@ -750,6 +760,7 @@ pub fn handle_block_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
update.character = CharacterState::from((
|
||||
&ability,
|
||||
AbilityInfo::from_input(data, false, InputKind::Roll),
|
||||
data,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -757,13 +768,14 @@ pub fn handle_block_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
|
||||
/// Checks that player can perform a dodge, then
|
||||
/// attempts to perform their dodge ability
|
||||
pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
pub fn handle_dodge_input(data: &JoinData<'_>, update: &mut StateUpdate) {
|
||||
if input_is_pressed(data, InputKind::Roll) && data.body.is_humanoid() {
|
||||
let ability = CharacterAbility::default_roll().adjusted_by_skills(data.skill_set, None);
|
||||
if ability.requirements_paid(data, update) {
|
||||
update.character = CharacterState::from((
|
||||
&ability,
|
||||
AbilityInfo::from_input(data, false, InputKind::Roll),
|
||||
data,
|
||||
));
|
||||
if let CharacterState::ComboMelee(c) = data.character {
|
||||
if let CharacterState::Roll(roll) = &mut update.character {
|
||||
@ -783,7 +795,7 @@ pub fn handle_dodge_input(data: &JoinData, update: &mut StateUpdate) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_strafing(data: &JoinData, update: &StateUpdate) -> bool {
|
||||
pub fn is_strafing(data: &JoinData<'_>, update: &StateUpdate) -> bool {
|
||||
// TODO: Don't always check `character.is_aimed()`, allow the frontend to
|
||||
// control whether the player strafes during an aimed `CharacterState`.
|
||||
(update.character.is_aimed() || update.should_strafe) && data.body.can_strafe()
|
||||
@ -797,7 +809,7 @@ pub fn unwrap_tool_data<'a>(data: &'a JoinData, equip_slot: EquipSlot) -> Option
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_hands(data: &JoinData) -> (Option<Hands>, Option<Hands>) {
|
||||
pub fn get_hands(data: &JoinData<'_>) -> (Option<Hands>, Option<Hands>) {
|
||||
let hand = |slot| {
|
||||
if let Some(ItemKind::Tool(tool)) = data.inventory.equipped(slot).map(|i| i.kind()) {
|
||||
Some(tool.hands)
|
||||
@ -813,7 +825,7 @@ pub fn get_hands(data: &JoinData) -> (Option<Hands>, Option<Hands>) {
|
||||
|
||||
/// Returns (critical chance, critical multiplier) which is calculated from
|
||||
/// equipped weapon and equipped armor respectively
|
||||
pub fn get_crit_data(data: &JoinData, ai: AbilityInfo) -> (f32, f32) {
|
||||
pub fn get_crit_data(data: &JoinData<'_>, ai: AbilityInfo) -> (f32, f32) {
|
||||
const DEFAULT_CRIT_CHANCE: f32 = 0.1;
|
||||
|
||||
let crit_chance = ai
|
||||
@ -838,7 +850,7 @@ pub fn get_crit_data(data: &JoinData, ai: AbilityInfo) -> (f32, f32) {
|
||||
}
|
||||
|
||||
/// Returns buff strength from the weapon used in the ability
|
||||
pub fn get_buff_strength(data: &JoinData, ai: AbilityInfo) -> f32 {
|
||||
pub fn get_buff_strength(data: &JoinData<'_>, ai: AbilityInfo) -> f32 {
|
||||
ai.hand
|
||||
.map(|hand| match hand {
|
||||
HandInfo::TwoHanded | HandInfo::MainHand => EquipSlot::ActiveMainhand,
|
||||
@ -855,21 +867,25 @@ pub fn get_buff_strength(data: &JoinData, ai: AbilityInfo) -> f32 {
|
||||
.unwrap_or(1.0)
|
||||
}
|
||||
|
||||
pub fn handle_state_interrupt(data: &JoinData, update: &mut StateUpdate, attacks_interrupt: bool) {
|
||||
pub fn handle_state_interrupt(
|
||||
data: &JoinData<'_>,
|
||||
update: &mut StateUpdate,
|
||||
attacks_interrupt: bool,
|
||||
) {
|
||||
if attacks_interrupt {
|
||||
handle_ability_input(data, update);
|
||||
}
|
||||
handle_dodge_input(data, update);
|
||||
}
|
||||
|
||||
pub fn input_is_pressed(data: &JoinData, input: InputKind) -> bool {
|
||||
pub fn input_is_pressed(data: &JoinData<'_>, input: InputKind) -> bool {
|
||||
data.controller.queued_inputs.contains_key(&input)
|
||||
}
|
||||
|
||||
/// Checked `Duration` addition. Computes `timer` + `dt`, applying relevant stat
|
||||
/// attack modifiers and `other_modifiers`, returning None if overflow occurred.
|
||||
pub fn checked_tick_attack(
|
||||
data: &JoinData,
|
||||
data: &JoinData<'_>,
|
||||
timer: Duration,
|
||||
other_modifier: Option<f32>,
|
||||
) -> Option<Duration> {
|
||||
@ -880,7 +896,7 @@ pub fn checked_tick_attack(
|
||||
/// Ticks `timer` by `dt`, applying relevant stat attack modifiers and
|
||||
/// `other_modifier`. Returns `Duration::default()` if overflow occurs
|
||||
pub fn tick_attack_or_default(
|
||||
data: &JoinData,
|
||||
data: &JoinData<'_>,
|
||||
timer: Duration,
|
||||
other_modifier: Option<f32>,
|
||||
) -> Duration {
|
||||
@ -926,7 +942,7 @@ pub enum MovementDirection {
|
||||
}
|
||||
|
||||
impl MovementDirection {
|
||||
pub fn get_2d_dir(self, data: &JoinData) -> Vec2<f32> {
|
||||
pub fn get_2d_dir(self, data: &JoinData<'_>) -> Vec2<f32> {
|
||||
use MovementDirection::*;
|
||||
match self {
|
||||
Look => data
|
||||
@ -951,7 +967,7 @@ pub struct AbilityInfo {
|
||||
}
|
||||
|
||||
impl AbilityInfo {
|
||||
pub fn from_input(data: &JoinData, from_offhand: bool, input: InputKind) -> Self {
|
||||
pub fn from_input(data: &JoinData<'_>, from_offhand: bool, input: InputKind) -> Self {
|
||||
let tool_data = if from_offhand {
|
||||
unwrap_tool_data(data, EquipSlot::ActiveOffhand)
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user