mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Updates from review
This commit is contained in:
parent
53fddba3ef
commit
c449b229d5
@ -10,7 +10,6 @@ BasicBlock(
|
||||
energy_cost: 5,
|
||||
energy_regen: 2.5,
|
||||
can_hold: true,
|
||||
can_use_block_priority: true,
|
||||
blocked_attacks: (
|
||||
melee: true,
|
||||
projectiles: false,
|
||||
|
@ -10,7 +10,6 @@ BasicBlock(
|
||||
energy_cost: 5,
|
||||
energy_regen: 2.5,
|
||||
can_hold: true,
|
||||
can_use_block_priority: true,
|
||||
blocked_attacks: (
|
||||
melee: true,
|
||||
projectiles: false,
|
||||
|
@ -10,7 +10,6 @@ BasicBlock(
|
||||
energy_cost: 0,
|
||||
energy_regen: 0,
|
||||
can_hold: true,
|
||||
can_use_block_priority: true,
|
||||
blocked_attacks: (
|
||||
melee: true,
|
||||
projectiles: true,
|
||||
|
@ -2,7 +2,7 @@ BasicBlock(
|
||||
buildup_duration: 0.45,
|
||||
recover_duration: 0.2,
|
||||
max_angle: 90.0,
|
||||
block_strength: 1.0,
|
||||
block_strength: 1.5,
|
||||
parry_window: (
|
||||
buildup: true,
|
||||
recover: false,
|
||||
@ -10,7 +10,6 @@ BasicBlock(
|
||||
energy_cost: 5.0,
|
||||
energy_regen: 5.0,
|
||||
can_hold: true,
|
||||
can_use_block_priority: true,
|
||||
blocked_attacks: (
|
||||
melee: true,
|
||||
projectiles: true,
|
||||
|
@ -10,7 +10,6 @@ BasicBlock(
|
||||
energy_cost: 5,
|
||||
energy_regen: 2.5,
|
||||
can_hold: true,
|
||||
can_use_block_priority: true,
|
||||
blocked_attacks: (
|
||||
melee: true,
|
||||
projectiles: false,
|
||||
|
@ -10,7 +10,6 @@ BasicBlock(
|
||||
energy_cost: 2.5,
|
||||
energy_regen: 17.5,
|
||||
can_hold: false,
|
||||
can_use_block_priority: false,
|
||||
blocked_attacks: (
|
||||
melee: false,
|
||||
projectiles: true,
|
||||
|
@ -2,7 +2,7 @@ BasicBlock(
|
||||
buildup_duration: 0.4,
|
||||
recover_duration: 0.15,
|
||||
max_angle: 60.0,
|
||||
block_strength: 1.1,
|
||||
block_strength: 1.15,
|
||||
parry_window: (
|
||||
buildup: true,
|
||||
recover: false,
|
||||
@ -10,7 +10,6 @@ BasicBlock(
|
||||
energy_cost: 2.5,
|
||||
energy_regen: 17.5,
|
||||
can_hold: true,
|
||||
can_use_block_priority: true,
|
||||
blocked_attacks: (
|
||||
melee: true,
|
||||
projectiles: false,
|
||||
|
@ -58,8 +58,9 @@ pub const MAX_HEADSHOT_PRECISION: f32 = 1.0;
|
||||
pub const MAX_TOP_HEADSHOT_PRECISION: f32 = 0.5;
|
||||
pub const MAX_BEAM_DUR_PRECISION: f32 = 0.25;
|
||||
pub const MAX_MELEE_POISE_PRECISION: f32 = 0.5;
|
||||
pub const MAX_BLOCK_POISE_COST: f32 = 25.0;
|
||||
pub const MAX_BLOCK_POISE_COST: f32 = 50.0;
|
||||
pub const PARRY_BONUS_MULTIPLIER: f32 = 2.0;
|
||||
pub const BLOCK_STRENGTH_MULTIPLIER: f32 = 5.0;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AttackerInfo<'a> {
|
||||
@ -144,6 +145,7 @@ impl Attack {
|
||||
|
||||
pub fn compute_block_damage_decrement(
|
||||
attacker: Option<&AttackerInfo>,
|
||||
damage_reduction: f32,
|
||||
target: &TargetInfo,
|
||||
source: AttackSource,
|
||||
dir: Dir,
|
||||
@ -157,6 +159,7 @@ impl Attack {
|
||||
if let (Some(char_state), Some(ori), Some(inventory)) =
|
||||
(target.char_state, target.ori, target.inventory)
|
||||
{
|
||||
let damage_value = damage.value * (1.0 - damage_reduction);
|
||||
let block_strength = block_strength(inventory, char_state);
|
||||
if ori.look_vec().angle_between(-dir.with_z(0.0)) < char_state.block_angle()
|
||||
&& block_strength > 0.0
|
||||
@ -164,7 +167,7 @@ impl Attack {
|
||||
if char_state.is_parry(source) {
|
||||
let final_block_strength = block_strength * PARRY_BONUS_MULTIPLIER;
|
||||
let poise_change = Poise::apply_poise_reduction(
|
||||
(damage.value.min(final_block_strength) * MAX_BLOCK_POISE_COST)
|
||||
(damage_value.min(final_block_strength) * MAX_BLOCK_POISE_COST)
|
||||
/ final_block_strength,
|
||||
target.inventory,
|
||||
msm,
|
||||
@ -192,12 +195,11 @@ impl Attack {
|
||||
time,
|
||||
},
|
||||
});
|
||||
damage.value.min(final_block_strength)
|
||||
final_block_strength
|
||||
} else if char_state.is_block(source) {
|
||||
let final_block_strength = block_strength;
|
||||
let poise_change = Poise::apply_poise_reduction(
|
||||
(damage.value.min(final_block_strength) * MAX_BLOCK_POISE_COST)
|
||||
/ final_block_strength,
|
||||
(damage_value.min(block_strength) * MAX_BLOCK_POISE_COST)
|
||||
/ block_strength,
|
||||
target.inventory,
|
||||
msm,
|
||||
target.char_state,
|
||||
@ -218,7 +220,7 @@ impl Attack {
|
||||
time,
|
||||
},
|
||||
});
|
||||
damage.value.min(final_block_strength)
|
||||
block_strength
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
@ -324,6 +326,7 @@ impl Attack {
|
||||
|
||||
let block_damage_decrement = Attack::compute_block_damage_decrement(
|
||||
attacker.as_ref(),
|
||||
damage_reduction,
|
||||
target,
|
||||
attack_source,
|
||||
dir,
|
||||
@ -1124,10 +1127,10 @@ impl Damage {
|
||||
| DamageSource::Energy => {
|
||||
// Precise hit
|
||||
damage += precise_damage;
|
||||
// Block
|
||||
damage -= block_damage_decrement;
|
||||
// Armor
|
||||
damage *= 1.0 - damage_reduction;
|
||||
// Block
|
||||
damage -= f32::min(damage, block_damage_decrement);
|
||||
|
||||
HealthChange {
|
||||
amount: -damage,
|
||||
@ -1561,89 +1564,43 @@ pub fn precision_mult_from_flank(attack_dir: Vec3<f32>, target_ori: Option<&Ori>
|
||||
}
|
||||
|
||||
pub fn block_strength(inventory: &Inventory, char_state: &CharacterState) -> f32 {
|
||||
let equip_slot = if let CharacterState::BasicBlock(data) = char_state {
|
||||
if data.static_data.can_use_block_priority {
|
||||
get_block_equip_slot_by_priority(Some(inventory))
|
||||
} else {
|
||||
get_block_equip_slot_by_tool(Some(inventory), data.static_data.ability_info.tool)
|
||||
}
|
||||
} else {
|
||||
get_block_equip_slot_by_tool(
|
||||
Some(inventory),
|
||||
char_state.ability_info().and_then(|t| t.tool),
|
||||
)
|
||||
};
|
||||
let equip_slot = get_equip_slot_by_tool(
|
||||
Some(inventory),
|
||||
char_state.ability_info().and_then(|t| t.tool),
|
||||
);
|
||||
|
||||
inventory
|
||||
.equipped(equip_slot)
|
||||
inventory.equipped(equip_slot)
|
||||
.map(|item| match &*item.kind() {
|
||||
ItemKind::Tool(tool) => tool.stats(item.stats_durability_multiplier()).power * 10.0,
|
||||
ItemKind::Tool(tool) => tool.stats(item.stats_durability_multiplier()).power,
|
||||
_ => 0.0,
|
||||
})
|
||||
.map_or(0.0, |weapon_block_strength| match char_state {
|
||||
CharacterState::BasicBlock(data) => {
|
||||
weapon_block_strength * data.static_data.block_strength
|
||||
},
|
||||
CharacterState::ComboMelee2(data) => {
|
||||
let capabilities = data.static_data.ability_info.ability_meta.capabilities;
|
||||
.map_or(0.0, |tool_block_strength| match char_state {
|
||||
CharacterState::BasicBlock(data) => data.static_data.block_strength,
|
||||
CharacterState::RiposteMelee(_) => tool_block_strength,
|
||||
_ => char_state
|
||||
.ability_info()
|
||||
.map(|ability| ability.ability_meta.capabilities)
|
||||
.map_or(0.0, |capabilities| {
|
||||
if capabilities.contains(Capability::PARRIES)
|
||||
|| capabilities.contains(Capability::PARRIES_MELEE)
|
||||
{
|
||||
return tool_block_strength;
|
||||
}
|
||||
|
||||
if capabilities.contains(Capability::PARRIES)
|
||||
|| capabilities.contains(Capability::PARRIES_MELEE)
|
||||
{
|
||||
return weapon_block_strength;
|
||||
}
|
||||
if capabilities.contains(Capability::BLOCKS) {
|
||||
return tool_block_strength * 0.5;
|
||||
}
|
||||
|
||||
if capabilities.contains(Capability::BLOCKS) {
|
||||
return weapon_block_strength * 0.5;
|
||||
}
|
||||
|
||||
0.0
|
||||
},
|
||||
CharacterState::RiposteMelee(_) => weapon_block_strength,
|
||||
CharacterState::Idle(_)
|
||||
| CharacterState::Climb(_)
|
||||
| CharacterState::Sit
|
||||
| CharacterState::Dance
|
||||
| CharacterState::Talk
|
||||
| CharacterState::Glide(_)
|
||||
| CharacterState::GlideWield(_)
|
||||
| CharacterState::Stunned(_)
|
||||
| CharacterState::Equipping(_)
|
||||
| CharacterState::Wielding(_)
|
||||
| CharacterState::Roll(_)
|
||||
| CharacterState::BasicMelee(_)
|
||||
| CharacterState::BasicRanged(_)
|
||||
| CharacterState::Boost(_)
|
||||
| CharacterState::DashMelee(_)
|
||||
| CharacterState::ComboMeleeDeprecated(_)
|
||||
| CharacterState::LeapMelee(_)
|
||||
| CharacterState::LeapShockwave(_)
|
||||
| CharacterState::ChargedRanged(_)
|
||||
| CharacterState::ChargedMelee(_)
|
||||
| CharacterState::RepeaterRanged(_)
|
||||
| CharacterState::Shockwave(_)
|
||||
| CharacterState::BasicBeam(_)
|
||||
| CharacterState::BasicAura(_)
|
||||
| CharacterState::Blink(_)
|
||||
| CharacterState::BasicSummon(_)
|
||||
| CharacterState::SelfBuff(_)
|
||||
| CharacterState::SpriteSummon(_)
|
||||
| CharacterState::UseItem(_)
|
||||
| CharacterState::SpriteInteract(_)
|
||||
| CharacterState::Wallrun(_)
|
||||
| CharacterState::Skate(_)
|
||||
| CharacterState::Music(_)
|
||||
| CharacterState::FinisherMelee(_)
|
||||
| CharacterState::DiveMelee(_)
|
||||
| CharacterState::RapidMelee(_) => 0.0,
|
||||
})
|
||||
0.0
|
||||
}),
|
||||
} * BLOCK_STRENGTH_MULTIPLIER)
|
||||
}
|
||||
|
||||
pub fn get_block_equip_slot_by_priority(inventory: Option<&Inventory>) -> EquipSlot {
|
||||
pub fn get_equip_slot_by_block_priority(inventory: Option<&Inventory>) -> EquipSlot {
|
||||
inventory
|
||||
.map(get_weapon_kinds)
|
||||
.map_or(
|
||||
EquipSlot::ActiveOffhand,
|
||||
EquipSlot::ActiveMainhand,
|
||||
|weapon_kinds| match weapon_kinds {
|
||||
(Some(mainhand), Some(offhand)) => {
|
||||
if mainhand.block_priority() >= offhand.block_priority() {
|
||||
@ -1654,19 +1611,19 @@ pub fn get_block_equip_slot_by_priority(inventory: Option<&Inventory>) -> EquipS
|
||||
},
|
||||
(Some(_), None) => EquipSlot::ActiveMainhand,
|
||||
(None, Some(_)) => EquipSlot::ActiveOffhand,
|
||||
(None, None) => EquipSlot::ActiveOffhand,
|
||||
(None, None) => EquipSlot::ActiveMainhand,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_block_equip_slot_by_tool(
|
||||
pub fn get_equip_slot_by_tool(
|
||||
inventory: Option<&Inventory>,
|
||||
tool_kind: Option<ToolKind>,
|
||||
) -> EquipSlot {
|
||||
inventory
|
||||
.map(get_weapon_kinds)
|
||||
.map_or(
|
||||
EquipSlot::ActiveOffhand,
|
||||
EquipSlot::ActiveMainhand,
|
||||
|weapon_kinds| match weapon_kinds {
|
||||
(mainhand, Some(_)) => {
|
||||
if mainhand == tool_kind {
|
||||
|
@ -196,7 +196,7 @@ impl ActiveAbilities {
|
||||
|
||||
match ability {
|
||||
Ability::ToolGuard => {
|
||||
let equip_slot = combat::get_block_equip_slot_by_priority(inv);
|
||||
let equip_slot = combat::get_equip_slot_by_block_priority(inv);
|
||||
ability_set(equip_slot)
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
@ -393,7 +393,7 @@ impl Ability {
|
||||
};
|
||||
|
||||
match self {
|
||||
Ability::ToolGuard => ability_set(combat::get_block_equip_slot_by_priority(inv))
|
||||
Ability::ToolGuard => ability_set(combat::get_equip_slot_by_block_priority(inv))
|
||||
.and_then(|abilities| {
|
||||
abilities
|
||||
.guard(skillset, context)
|
||||
@ -521,7 +521,7 @@ impl SpecifiedAbility {
|
||||
ability_set(EquipSlot::ActiveMainhand)
|
||||
.map(|abilities| ability_id(self, &abilities.secondary))
|
||||
}),
|
||||
Ability::ToolGuard => ability_set(combat::get_block_equip_slot_by_priority(inv))
|
||||
Ability::ToolGuard => ability_set(combat::get_equip_slot_by_block_priority(inv))
|
||||
.and_then(|abilities| abilities.guard.as_ref().map(|a| ability_id(self, a)))
|
||||
.or_else(|| {
|
||||
ability_set(EquipSlot::ActiveMainhand)
|
||||
@ -756,7 +756,6 @@ pub enum CharacterAbility {
|
||||
energy_cost: f32,
|
||||
energy_regen: f32,
|
||||
can_hold: bool,
|
||||
can_use_block_priority: bool,
|
||||
blocked_attacks: AttackFilters,
|
||||
#[serde(default)]
|
||||
meta: AbilityMeta,
|
||||
@ -1277,19 +1276,18 @@ impl CharacterAbility {
|
||||
ref mut recover_duration,
|
||||
// Do we want angle to be adjusted by range?
|
||||
max_angle: _,
|
||||
// Block strength explicitly not modified by power, that will be a separate stat
|
||||
block_strength: _,
|
||||
ref mut block_strength,
|
||||
parry_window: _,
|
||||
ref mut energy_cost,
|
||||
energy_regen: _,
|
||||
can_hold: _,
|
||||
can_use_block_priority: _,
|
||||
blocked_attacks: _,
|
||||
meta: _,
|
||||
} => {
|
||||
*buildup_duration /= stats.speed;
|
||||
*recover_duration /= stats.speed;
|
||||
*energy_cost /= stats.energy_efficiency;
|
||||
*block_strength *= stats.power;
|
||||
},
|
||||
Roll {
|
||||
ref mut energy_cost,
|
||||
@ -2348,7 +2346,6 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
||||
energy_cost,
|
||||
energy_regen,
|
||||
can_hold,
|
||||
can_use_block_priority,
|
||||
blocked_attacks,
|
||||
meta: _,
|
||||
} => CharacterState::BasicBlock(basic_block::Data {
|
||||
@ -2361,7 +2358,6 @@ impl From<(&CharacterAbility, AbilityInfo, &JoinData<'_>)> for CharacterState {
|
||||
energy_cost: *energy_cost,
|
||||
energy_regen: *energy_regen,
|
||||
can_hold: *can_hold,
|
||||
can_use_block_priority: *can_use_block_priority,
|
||||
blocked_attacks: *blocked_attacks,
|
||||
ability_info,
|
||||
},
|
||||
@ -3005,9 +3001,7 @@ bitflags::bitflags! {
|
||||
// If more are ever needed, first check if any not used anymore, as some were only used in intermediary stages so may be free
|
||||
pub struct Capability: u8 {
|
||||
// The ability will parry all blockable attacks in the buildup portion
|
||||
const PARRIES = 0b01000000;
|
||||
// There used to be a capability here, to keep ordering the same below this is now a placeholder
|
||||
const PLACEHOLDER = 0b00000001;
|
||||
const PARRIES = 0b00000001;
|
||||
// Allows blocking to interrupt the ability at any point
|
||||
const BLOCK_INTERRUPT = 0b00000010;
|
||||
// When the ability is in the buildup section, it counts as a block with 50% DR
|
||||
|
@ -354,57 +354,20 @@ impl CharacterState {
|
||||
data.static_data.blocked_attacks.applies(attack_source)
|
||||
&& matches!(
|
||||
self.stage_section(),
|
||||
Some(StageSection::Buildup | StageSection::Action),
|
||||
Some(StageSection::Buildup | StageSection::Action)
|
||||
)
|
||||
},
|
||||
CharacterState::ComboMelee2(data) => {
|
||||
data.static_data
|
||||
.ability_info
|
||||
.ability_meta
|
||||
.capabilities
|
||||
.contains(Capability::BLOCKS)
|
||||
&& matches!(
|
||||
self.stage_section(),
|
||||
Some(StageSection::Buildup | StageSection::Action),
|
||||
)
|
||||
},
|
||||
CharacterState::Idle(_)
|
||||
| CharacterState::Climb(_)
|
||||
| CharacterState::Sit
|
||||
| CharacterState::Dance
|
||||
| CharacterState::Talk
|
||||
| CharacterState::Glide(_)
|
||||
| CharacterState::GlideWield(_)
|
||||
| CharacterState::Stunned(_)
|
||||
| CharacterState::Equipping(_)
|
||||
| CharacterState::Wielding(_)
|
||||
| CharacterState::Roll(_)
|
||||
| CharacterState::BasicMelee(_)
|
||||
| CharacterState::BasicRanged(_)
|
||||
| CharacterState::Boost(_)
|
||||
| CharacterState::DashMelee(_)
|
||||
| CharacterState::ComboMeleeDeprecated(_)
|
||||
| CharacterState::LeapMelee(_)
|
||||
| CharacterState::LeapShockwave(_)
|
||||
| CharacterState::ChargedRanged(_)
|
||||
| CharacterState::ChargedMelee(_)
|
||||
| CharacterState::RepeaterRanged(_)
|
||||
| CharacterState::Shockwave(_)
|
||||
| CharacterState::BasicBeam(_)
|
||||
| CharacterState::BasicAura(_)
|
||||
| CharacterState::Blink(_)
|
||||
| CharacterState::BasicSummon(_)
|
||||
| CharacterState::SelfBuff(_)
|
||||
| CharacterState::SpriteSummon(_)
|
||||
| CharacterState::UseItem(_)
|
||||
| CharacterState::SpriteInteract(_)
|
||||
| CharacterState::Wallrun(_)
|
||||
| CharacterState::Skate(_)
|
||||
| CharacterState::Music(_)
|
||||
| CharacterState::FinisherMelee(_)
|
||||
| CharacterState::DiveMelee(_)
|
||||
| CharacterState::RiposteMelee(_)
|
||||
| CharacterState::RapidMelee(_) => false,
|
||||
_ => self
|
||||
.ability_info()
|
||||
.map(|ability| ability.ability_meta.capabilities)
|
||||
.map_or(false, |capabilities| {
|
||||
capabilities.contains(Capability::BLOCKS)
|
||||
&& matches!(
|
||||
self.stage_section(),
|
||||
Some(StageSection::Buildup | StageSection::Action)
|
||||
)
|
||||
&& matches!(attack_source, AttackSource::Melee)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,6 @@ pub struct StaticData {
|
||||
pub energy_regen: f32,
|
||||
/// Whether block can be held
|
||||
pub can_hold: bool,
|
||||
/// Whether can choose higher priority weapon block
|
||||
pub can_use_block_priority: bool,
|
||||
/// What kinds of attacks the block applies to
|
||||
pub blocked_attacks: AttackFilters,
|
||||
}
|
||||
|
@ -146,14 +146,13 @@ impl CombatEventMapper {
|
||||
previous_state: &PreviousEntityState,
|
||||
inventory: &Inventory,
|
||||
) -> SfxEvent {
|
||||
let hand_info = character_state.ability_info().and_then(|a| a.hand);
|
||||
|
||||
let equip_slot = match hand_info {
|
||||
Some(HandInfo::TwoHanded) => EquipSlot::ActiveMainhand,
|
||||
Some(HandInfo::MainHand) => EquipSlot::ActiveMainhand,
|
||||
Some(HandInfo::OffHand) => EquipSlot::ActiveOffhand,
|
||||
None => EquipSlot::ActiveMainhand,
|
||||
};
|
||||
let equip_slot = character_state
|
||||
.ability_info()
|
||||
.and_then(|ability| ability.hand)
|
||||
.map_or(EquipSlot::ActiveMainhand, |hand| match hand {
|
||||
HandInfo::TwoHanded | HandInfo::MainHand => EquipSlot::ActiveMainhand,
|
||||
HandInfo::OffHand => EquipSlot::ActiveOffhand,
|
||||
});
|
||||
|
||||
if let Some(item) = inventory.equipped(equip_slot) {
|
||||
if let ItemKind::Tool(data) = &*item.kind() {
|
||||
|
Loading…
Reference in New Issue
Block a user