feat: added puncture and penetrate
This commit is contained in:
parent
451efd2bb7
commit
6c3c50689a
4 changed files with 104 additions and 59 deletions
|
|
@ -1,7 +1,7 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use proxisim_models::bundle::{
|
||||
armour::{ArmourBodyPart, ArmourBodyParts},
|
||||
bonus::DamageMitigationBonus,
|
||||
bonus::{ArmourBypassBonus, DamageMitigationBonus},
|
||||
player::{
|
||||
Attacker, BodyPart, ChooseWeapon, CombatTurns, Current, CurrentTarget, Defeated, Defender,
|
||||
FightEndType, Health, PartDamageBonus, Player, PlayerStrategy, Weapons,
|
||||
|
|
@ -188,10 +188,11 @@ pub fn use_damaging_weapon(
|
|||
),
|
||||
(With<CurrentTarget>, Without<Current>),
|
||||
>,
|
||||
(armour_q, damage_q, mut mitigation_q): (
|
||||
(armour_q, damage_q, mut mitigation_q, bypass_q): (
|
||||
Query<&ArmourBodyPart>,
|
||||
Query<(Entity, &DeferredDamage)>,
|
||||
Query<Option<&mut DamageMitigationBonus>>,
|
||||
Query<(&ArmourBypassBonus)>,
|
||||
),
|
||||
(damage_proc_q, part_bonus_q): (Query<&DamageProcEffect>, Query<&PartDamageBonus>),
|
||||
(mut ammo_q, mut temp_q): (
|
||||
|
|
@ -368,8 +369,8 @@ pub fn use_damaging_weapon(
|
|||
metrics.increment_counter(Some(weapon), "hit", 1);
|
||||
|
||||
let armour_parts = armour_q.get(armour_parts.0[body_part.into()]).unwrap();
|
||||
let piece = rng.sample(armour_parts);
|
||||
let armour_mitigation = piece.map_or(0.0, |p| p.armour_value);
|
||||
let mut piece = rng.sample(armour_parts);
|
||||
let mut armour_mitigation = piece.map_or(0.0, |p| p.armour_value);
|
||||
|
||||
// NOTE: Proxima's simulator seems to have the damage spread be between 95% and 105%,
|
||||
// but from my brief tests it seems that 100% to 110% lines up better, at least for h2h.
|
||||
|
|
@ -384,66 +385,83 @@ pub fn use_damaging_weapon(
|
|||
}
|
||||
}
|
||||
|
||||
let bonus_mitigation = match piece {
|
||||
Some(piece) => {
|
||||
if let Some(mut mitigation) = mitigation_q.get_mut(piece.armour).unwrap() {
|
||||
match mitigation.as_mut() {
|
||||
DamageMitigationBonus::Impregnable { mitigation }
|
||||
if *slot == WeaponSlot::Melee =>
|
||||
{
|
||||
*mitigation
|
||||
}
|
||||
DamageMitigationBonus::Impenetrable { mitigation }
|
||||
if rounds.is_some() =>
|
||||
{
|
||||
*mitigation
|
||||
}
|
||||
DamageMitigationBonus::Insurmountable { mitigation } => {
|
||||
if health.0 as f32 / target_max_health.value as f32 <= 0.25 {
|
||||
*mitigation
|
||||
} else {
|
||||
0.0
|
||||
let bonus_mitigation = 'block: {
|
||||
match piece {
|
||||
Some(part) => {
|
||||
for bypass in bypass_q.iter_many(children) {
|
||||
match bypass {
|
||||
ArmourBypassBonus::Penetrate { mitigation } => {
|
||||
armour_mitigation *= 1.0 - mitigation;
|
||||
}
|
||||
ArmourBypassBonus::Puncture { chance } => {
|
||||
if *chance >= 1.0 || rng.random_bool(*chance as f64) {
|
||||
armour_mitigation = 0.0;
|
||||
piece = None;
|
||||
break 'block 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
DamageMitigationBonus::Impassable { chance } => {
|
||||
if *chance >= 1.0 || rng.random_bool(*chance as f64) {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
DamageMitigationBonus::Kinetokinesis { mitigation } => {
|
||||
commands.entity(piece.armour).insert(
|
||||
DamageMitigationBonus::ActiveKinetokinesis {
|
||||
mitigation: *mitigation,
|
||||
remaining_turns: 10,
|
||||
},
|
||||
);
|
||||
0.0
|
||||
}
|
||||
DamageMitigationBonus::ActiveKinetokinesis {
|
||||
mitigation,
|
||||
remaining_turns,
|
||||
} => {
|
||||
*remaining_turns -= 1;
|
||||
}
|
||||
|
||||
if *remaining_turns == 0 {
|
||||
commands.entity(piece.armour).insert(
|
||||
DamageMitigationBonus::Kinetokinesis {
|
||||
if let Some(mut mitigation) = mitigation_q.get_mut(part.armour).unwrap() {
|
||||
match mitigation.as_mut() {
|
||||
DamageMitigationBonus::Impregnable { mitigation }
|
||||
if *slot == WeaponSlot::Melee =>
|
||||
{
|
||||
*mitigation
|
||||
}
|
||||
DamageMitigationBonus::Impenetrable { mitigation }
|
||||
if rounds.is_some() =>
|
||||
{
|
||||
*mitigation
|
||||
}
|
||||
DamageMitigationBonus::Insurmountable { mitigation } => {
|
||||
if health.0 as f32 / target_max_health.value as f32 <= 0.25 {
|
||||
*mitigation
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
DamageMitigationBonus::Impassable { chance } => {
|
||||
if *chance >= 1.0 || rng.random_bool(*chance as f64) {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
DamageMitigationBonus::Kinetokinesis { mitigation } => {
|
||||
commands.entity(part.armour).insert(
|
||||
DamageMitigationBonus::ActiveKinetokinesis {
|
||||
mitigation: *mitigation,
|
||||
remaining_turns: 10,
|
||||
},
|
||||
);
|
||||
0.0
|
||||
}
|
||||
DamageMitigationBonus::ActiveKinetokinesis {
|
||||
mitigation,
|
||||
remaining_turns,
|
||||
} => {
|
||||
*remaining_turns -= 1;
|
||||
|
||||
*mitigation
|
||||
if *remaining_turns == 0 {
|
||||
commands.entity(part.armour).insert(
|
||||
DamageMitigationBonus::Kinetokinesis {
|
||||
mitigation: *mitigation,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
*mitigation
|
||||
}
|
||||
_ => 0.0,
|
||||
}
|
||||
_ => 0.0,
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
None => 0.0,
|
||||
}
|
||||
None => 0.0,
|
||||
};
|
||||
|
||||
// TODO: special ammo
|
||||
|
|
@ -503,7 +521,7 @@ pub fn use_damaging_weapon(
|
|||
bonus.spawn(target, &mut effects, &mut rng.0);
|
||||
}
|
||||
}
|
||||
DamageProcEffect::DamageOverTimer { value, kind } => {
|
||||
DamageProcEffect::DamageOverTime { value, kind } => {
|
||||
let chance = (value / 100.0) as f64;
|
||||
if chance > 1.0 || rng.random_bool(chance) {
|
||||
match kind {
|
||||
|
|
@ -562,8 +580,8 @@ pub fn use_damaging_weapon(
|
|||
}
|
||||
}
|
||||
|
||||
// Technically only douple tap and blindfire have this condition, but we can run into with
|
||||
// invalid bonus/weapon combinations without checking this for all bonuses
|
||||
// Technically only douple tap and blindfire have this condition, but we can run into
|
||||
// panics with invalid bonus/weapon combinations without checking this for all bonuses
|
||||
if ammo.as_ref().is_some_and(|(a, _, _)| a.0 == 0) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -679,5 +697,7 @@ pub(crate) fn configure(stages: &mut Stages) {
|
|||
.before(change_roles),
|
||||
);
|
||||
stages.post_fight.add_systems(record_post_fight_stats);
|
||||
stages.restore.add_systems(restore_initial_state);
|
||||
stages
|
||||
.restore
|
||||
.add_systems((restore_initial_state, restore_health));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue