Updates from review

This commit is contained in:
danielkenji83 2024-02-17 19:09:32 -03:00
parent 53fddba3ef
commit c449b229d5
12 changed files with 68 additions and 164 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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