refactor: split up core attacking system
This commit is contained in:
parent
1c7a5d1e1b
commit
9b720facf8
1 changed files with 273 additions and 187 deletions
|
|
@ -1,6 +1,6 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use bevy_ecs::{prelude::*, system::SystemParam};
|
||||
use proxisim_models::bundle::{
|
||||
armour::{ArmourBodyPart, ArmourBodyParts},
|
||||
armour::{ArmourBodyPart, ArmourBodyParts, BodyPartCoverage},
|
||||
bonus::{ArmourBypassBonus, DamageMitigationBonus},
|
||||
player::{
|
||||
Attacker, BodyPart, ChooseWeapon, CombatTurns, Current, CurrentTarget, Defeated, Defender,
|
||||
|
|
@ -146,55 +146,217 @@ impl FromWorld for DamageSpread {
|
|||
}
|
||||
}
|
||||
|
||||
// NOTE: unfortunately this function can't really be split into smaller parts due to the existence
|
||||
// of multi turn bonuses
|
||||
#[derive(SystemParam)]
|
||||
struct SharedParams<'w, 's> {
|
||||
commands: Commands<'w, 's>,
|
||||
rng: ResMut<'w, Rng>,
|
||||
effects: Effects<'w, 's>,
|
||||
logger: Logger<'w>,
|
||||
metrics: Res<'w, Metrics>,
|
||||
}
|
||||
|
||||
#[derive(SystemParam)]
|
||||
struct BonusMitigationParams<'w, 's> {
|
||||
bypass_q: Query<'w, 's, &'static ArmourBypassBonus>,
|
||||
mitigation_q: Query<'w, 's, Option<&'static mut DamageMitigationBonus>>,
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn use_damaging_weapon(
|
||||
mut rng: ResMut<Rng>,
|
||||
#[inline(always)]
|
||||
fn check_bonus_mitigation(
|
||||
params: &mut BonusMitigationParams,
|
||||
shared: &mut SharedParams,
|
||||
w_children: &Children,
|
||||
armour_mitigation: &mut f32,
|
||||
piece: &mut Option<&BodyPartCoverage>,
|
||||
slot: WeaponSlot,
|
||||
rounds: &Option<u16>,
|
||||
health: &Health,
|
||||
max_health: &SimpleStatEffective<MaxHealth>,
|
||||
) -> f32 {
|
||||
for bypass in params.bypass_q.iter_many(w_children) {
|
||||
match bypass {
|
||||
ArmourBypassBonus::Penetrate { mitigation } => {
|
||||
*armour_mitigation *= 1.0 - mitigation;
|
||||
}
|
||||
ArmourBypassBonus::Puncture { chance } => {
|
||||
if *chance >= 1.0 || shared.rng.random_bool(*chance as f64) {
|
||||
*armour_mitigation = 0.0;
|
||||
*piece = None;
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(piece) = piece
|
||||
&& let Some(mut mitigation) = params.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 / max_health.value as f32 <= 0.25 {
|
||||
*mitigation
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
DamageMitigationBonus::Impassable { chance } => {
|
||||
if *chance >= 1.0 || shared.rng.random_bool(*chance as f64) {
|
||||
1.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
DamageMitigationBonus::Kinetokinesis { mitigation } => {
|
||||
shared.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 {
|
||||
shared.commands.entity(piece.armour).insert(
|
||||
DamageMitigationBonus::Kinetokinesis {
|
||||
mitigation: *mitigation,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
*mitigation
|
||||
}
|
||||
_ => 0.0,
|
||||
}
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(SystemParam)]
|
||||
struct DeferredDamageParams<'w, 's> {
|
||||
damage_q: Query<'w, 's, (Entity, &'static DeferredDamage)>,
|
||||
}
|
||||
|
||||
/// Checks and applied deferred damage.
|
||||
/// Returns `true` if the attacking player was defeated
|
||||
#[inline(always)]
|
||||
fn check_deferred_damage(
|
||||
deferred: &DeferredDamageParams,
|
||||
shared: &mut SharedParams,
|
||||
player: Entity,
|
||||
player_children: &Children,
|
||||
player_health: &mut Health,
|
||||
is_attacker: bool,
|
||||
target: Entity,
|
||||
) -> bool {
|
||||
for (instance, damage) in deferred.damage_q.iter_many(player_children) {
|
||||
let health_before = player_health.0;
|
||||
player_health.0 = player_health.0.saturating_sub(damage.amount);
|
||||
|
||||
log!(shared.logger, "deferred_damage", {
|
||||
health_before: health_before,
|
||||
health_after: player_health.0,
|
||||
amount: damage.amount,
|
||||
label: damage.label,
|
||||
target: player,
|
||||
});
|
||||
|
||||
shared.commands.entity(instance).despawn();
|
||||
|
||||
if player_health.0 == 0 {
|
||||
shared.commands.entity(player).insert(Defeated);
|
||||
log!(shared.logger, "fight_end", {
|
||||
actor: target,
|
||||
recipient: player,
|
||||
fight_end_type: %if is_attacker {
|
||||
FightEndType::Loss
|
||||
} else {
|
||||
FightEndType::Victory
|
||||
},
|
||||
});
|
||||
shared.metrics.increment_counter(Some(target), "victory", 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
#[derive(SystemParam)]
|
||||
struct EntityParams<'w, 's> {
|
||||
/// The weapon and its related stats
|
||||
weapon_q: Query<
|
||||
'w,
|
||||
's,
|
||||
(
|
||||
Entity,
|
||||
&DamageStat,
|
||||
&SimpleStatEffective<WeaponAccuracy>,
|
||||
&SimpleStatEffective<DamageBonus>,
|
||||
&SimpleStatEffective<CritRate>,
|
||||
&Children,
|
||||
&WeaponSlot,
|
||||
&'static DamageStat,
|
||||
&'static SimpleStatEffective<WeaponAccuracy>,
|
||||
&'static SimpleStatEffective<DamageBonus>,
|
||||
&'static SimpleStatEffective<CritRate>,
|
||||
&'static Children,
|
||||
&'static WeaponSlot,
|
||||
Has<NonTargeted>,
|
||||
),
|
||||
(With<Weapon>, With<Current>, Without<NeedsReload>),
|
||||
>,
|
||||
mut player_q: Query<
|
||||
|
||||
/// The player who's using the weapon and their related stats
|
||||
player_q: Query<
|
||||
'w,
|
||||
's,
|
||||
(
|
||||
Entity,
|
||||
&EffectiveStat<Speed>,
|
||||
&EffectiveStat<Strength>,
|
||||
&SimpleStatEffective<CritRate>,
|
||||
&SimpleStatEffective<WeaponAccuracy>,
|
||||
&SimpleStatEffective<DamageBonus>,
|
||||
&Children,
|
||||
&mut Health,
|
||||
&'static EffectiveStat<Speed>,
|
||||
&'static EffectiveStat<Strength>,
|
||||
&'static SimpleStatEffective<CritRate>,
|
||||
&'static SimpleStatEffective<WeaponAccuracy>,
|
||||
&'static SimpleStatEffective<DamageBonus>,
|
||||
&'static Children,
|
||||
&'static mut Health,
|
||||
Has<Attacker>,
|
||||
),
|
||||
(With<Player>, With<Current>),
|
||||
>,
|
||||
mut target_q: Query<
|
||||
|
||||
/// The player who is targeted with the weapon
|
||||
target_q: Query<
|
||||
'w,
|
||||
's,
|
||||
(
|
||||
Entity,
|
||||
&EffectiveStat<Dexterity>,
|
||||
&EffectiveStat<Defence>,
|
||||
&SimpleStatEffective<MaxHealth>,
|
||||
&ArmourBodyParts,
|
||||
&mut Health,
|
||||
&'static EffectiveStat<Dexterity>,
|
||||
&'static EffectiveStat<Defence>,
|
||||
&'static SimpleStatEffective<MaxHealth>,
|
||||
&'static ArmourBodyParts,
|
||||
&'static mut Health,
|
||||
),
|
||||
(With<CurrentTarget>, Without<Current>),
|
||||
>,
|
||||
(armour_q, damage_q, mut mitigation_q, bypass_q): (
|
||||
Query<&ArmourBodyPart>,
|
||||
Query<(Entity, &DeferredDamage)>,
|
||||
Query<Option<&mut DamageMitigationBonus>>,
|
||||
Query<&ArmourBypassBonus>,
|
||||
}
|
||||
|
||||
// NOTE: unfortunately this function can't really be split into smaller parts due to the existence
|
||||
// of multi turn bonuses
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn use_damaging_weapon(
|
||||
(mut shared, mut bonus_mitigation, deferred): (
|
||||
SharedParams,
|
||||
BonusMitigationParams,
|
||||
DeferredDamageParams,
|
||||
),
|
||||
mut entities: EntityParams,
|
||||
armour_q: Query<&ArmourBodyPart>,
|
||||
(damage_proc_q, part_bonus_q): (Query<&DamageProcEffect>, Query<&PartDamageBonus>),
|
||||
(mut ammo_q, mut temp_q): (
|
||||
Query<(
|
||||
|
|
@ -206,15 +368,10 @@ pub fn use_damaging_weapon(
|
|||
)>,
|
||||
Query<&mut Uses>,
|
||||
),
|
||||
(mut logger, mut commands, dmg_spread, metrics, mut effects): (
|
||||
Logger,
|
||||
Commands,
|
||||
Local<DamageSpread>,
|
||||
Res<Metrics>,
|
||||
Effects,
|
||||
),
|
||||
dmg_spread: Local<DamageSpread>,
|
||||
) {
|
||||
let Ok((weapon, w_dmg, acc, dmg_bonus, crit, children, slot, non_targeted)) = weapon_q.single()
|
||||
let Ok((weapon, w_dmg, acc, dmg_bonus, crit, children, slot, non_targeted)) =
|
||||
entities.weapon_q.single()
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
|
@ -228,44 +385,26 @@ pub fn use_damaging_weapon(
|
|||
p_children,
|
||||
mut p_health,
|
||||
attacker,
|
||||
) = player_q.single_mut().unwrap();
|
||||
) = entities.player_q.single_mut().unwrap();
|
||||
let (target, target_dex, target_def, target_max_health, armour_parts, mut health) =
|
||||
target_q.single_mut().unwrap();
|
||||
entities.target_q.single_mut().unwrap();
|
||||
|
||||
for (instance, damage) in damage_q.iter_many(p_children) {
|
||||
let health_before = p_health.0;
|
||||
p_health.0 = p_health.0.saturating_sub(damage.amount);
|
||||
|
||||
log!(logger, "deferred_damage", {
|
||||
health_before: health_before,
|
||||
health_after: p_health.0,
|
||||
amount: damage.amount,
|
||||
label: damage.label,
|
||||
target: player,
|
||||
});
|
||||
|
||||
commands.entity(instance).despawn();
|
||||
|
||||
if p_health.0 == 0 {
|
||||
commands.entity(player).insert(Defeated);
|
||||
log!(logger, "fight_end", {
|
||||
actor: target,
|
||||
recipient: player,
|
||||
fight_end_type: %if attacker {
|
||||
FightEndType::Loss
|
||||
} else {
|
||||
FightEndType::Victory
|
||||
},
|
||||
});
|
||||
metrics.increment_counter(Some(target), "victory", 1);
|
||||
return;
|
||||
}
|
||||
if check_deferred_damage(
|
||||
&deferred,
|
||||
&mut shared,
|
||||
player,
|
||||
p_children,
|
||||
&mut p_health,
|
||||
attacker,
|
||||
target,
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Ok(mut uses) = temp_q.get_mut(weapon) {
|
||||
uses.0 -= 1;
|
||||
if uses.0 == 0 {
|
||||
commands.entity(weapon).remove::<Usable>();
|
||||
shared.commands.entity(weapon).remove::<Usable>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -314,15 +453,19 @@ pub fn use_damaging_weapon(
|
|||
|
||||
loop {
|
||||
let rounds = ammo.as_mut().map(|(ammo, clips, rof, _)| {
|
||||
let rounds = (rng.random_range(rof.clone()).round() as u16).clamp(1, ammo.0);
|
||||
metrics.increment_counter(Some(player), "rounds_fired", rounds.into());
|
||||
metrics.increment_counter(Some(weapon), "rounds_fired", rounds.into());
|
||||
let rounds = (shared.rng.random_range(rof.clone()).round() as u16).clamp(1, ammo.0);
|
||||
shared
|
||||
.metrics
|
||||
.increment_counter(Some(player), "rounds_fired", rounds.into());
|
||||
shared
|
||||
.metrics
|
||||
.increment_counter(Some(weapon), "rounds_fired", rounds.into());
|
||||
ammo.0 -= rounds;
|
||||
if ammo.0 == 0 {
|
||||
if clips.value == 0 {
|
||||
commands.entity(weapon).remove::<Usable>();
|
||||
shared.commands.entity(weapon).remove::<Usable>();
|
||||
} else {
|
||||
commands.entity(weapon).insert(NeedsReload);
|
||||
shared.commands.entity(weapon).insert(NeedsReload);
|
||||
}
|
||||
}
|
||||
rounds
|
||||
|
|
@ -334,31 +477,31 @@ pub fn use_damaging_weapon(
|
|||
base_hit_chance + acc_eff.value * (1.0 - base_hit_chance)
|
||||
};
|
||||
|
||||
if hit_chance <= 1.0 && !rng.random_bool(hit_chance as f64) {
|
||||
log!(logger, "miss_target", {
|
||||
if hit_chance <= 1.0 && !shared.rng.random_bool(hit_chance as f64) {
|
||||
log!(shared.logger, "miss_target", {
|
||||
weapon: weapon,
|
||||
actor: player,
|
||||
recipient: target,
|
||||
rounds: rounds,
|
||||
hit_chance: hit_chance,
|
||||
});
|
||||
metrics.increment_counter(Some(player), "miss", 1);
|
||||
metrics.increment_counter(Some(weapon), "miss", 1);
|
||||
shared.metrics.increment_counter(Some(player), "miss", 1);
|
||||
shared.metrics.increment_counter(Some(weapon), "miss", 1);
|
||||
|
||||
if multi_attack_proc.is_none() {
|
||||
return;
|
||||
};
|
||||
} else {
|
||||
let body_part = if !non_targeted {
|
||||
rng.sample(crit)
|
||||
shared.rng.sample(crit)
|
||||
} else {
|
||||
BodyPart::Stomach
|
||||
};
|
||||
|
||||
let mult = match body_part {
|
||||
BodyPart::Head | BodyPart::Heart | BodyPart::Throat => {
|
||||
metrics.increment_counter(Some(player), "crit", 1);
|
||||
metrics.increment_counter(Some(weapon), "crit", 1);
|
||||
shared.metrics.increment_counter(Some(player), "crit", 1);
|
||||
shared.metrics.increment_counter(Some(weapon), "crit", 1);
|
||||
1.0
|
||||
}
|
||||
BodyPart::LeftHand
|
||||
|
|
@ -371,17 +514,17 @@ pub fn use_damaging_weapon(
|
|||
BodyPart::Groin | BodyPart::Stomach | BodyPart::Chest => 1.0 / 1.75,
|
||||
};
|
||||
|
||||
metrics.increment_counter(Some(player), "hit", 1);
|
||||
metrics.increment_counter(Some(weapon), "hit", 1);
|
||||
shared.metrics.increment_counter(Some(player), "hit", 1);
|
||||
shared.metrics.increment_counter(Some(weapon), "hit", 1);
|
||||
|
||||
let armour_parts = armour_q.get(armour_parts.0[body_part.into()]).unwrap();
|
||||
let mut piece = rng.sample(armour_parts);
|
||||
let mut piece = shared.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.
|
||||
// It might be better to revivisit this detail later down the line and run more tests.
|
||||
let dmg_spread = rng.sample(dmg_spread.0) / 10.0 + 1.0;
|
||||
let dmg_spread = shared.rng.sample(dmg_spread.0) / 10.0 + 1.0;
|
||||
|
||||
let mut dmg_bonus = dmg_bonus + p_dmg_bonus;
|
||||
|
||||
|
|
@ -391,84 +534,17 @@ pub fn use_damaging_weapon(
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if *remaining_turns == 0 {
|
||||
commands.entity(part.armour).insert(
|
||||
DamageMitigationBonus::Kinetokinesis {
|
||||
mitigation: *mitigation,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
*mitigation
|
||||
}
|
||||
_ => 0.0,
|
||||
}
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
None => 0.0,
|
||||
}
|
||||
};
|
||||
let bonus_mitigation = check_bonus_mitigation(
|
||||
&mut bonus_mitigation,
|
||||
&mut shared,
|
||||
children,
|
||||
&mut armour_mitigation,
|
||||
&mut piece,
|
||||
*slot,
|
||||
&rounds,
|
||||
&health,
|
||||
target_max_health,
|
||||
);
|
||||
|
||||
let spammo_bonus = ammo
|
||||
.as_ref()
|
||||
|
|
@ -498,8 +574,8 @@ pub fn use_damaging_weapon(
|
|||
* dmg_spread;
|
||||
let mut dmg_i = dmg.round() as u32;
|
||||
|
||||
metrics.record_histogram(Some(player), "dmg", dmg_i);
|
||||
metrics.record_histogram(Some(weapon), "dmg", dmg_i);
|
||||
shared.metrics.record_histogram(Some(player), "dmg", dmg_i);
|
||||
shared.metrics.record_histogram(Some(weapon), "dmg", dmg_i);
|
||||
|
||||
if dmg_i > 0 {
|
||||
for effect in damage_proc_q.iter_many(children) {
|
||||
|
|
@ -509,7 +585,7 @@ pub fn use_damaging_weapon(
|
|||
continue;
|
||||
}
|
||||
let chance = (value / 100.0) as f64;
|
||||
if chance > 1.0 || rng.random_bool(chance) {
|
||||
if chance > 1.0 || shared.rng.random_bool(chance) {
|
||||
match bonus {
|
||||
MultiTurnBonus::Blindfire => {
|
||||
multi_attack_proc = Some(MultiAttack::Blindfire)
|
||||
|
|
@ -520,43 +596,53 @@ pub fn use_damaging_weapon(
|
|||
}
|
||||
MultiTurnBonus::Rage => {
|
||||
multi_attack_proc =
|
||||
Some(MultiAttack::Rage(rng.random_range(2..=8)))
|
||||
Some(MultiAttack::Rage(shared.rng.random_range(2..=8)))
|
||||
}
|
||||
MultiTurnBonus::DoubleTap => {
|
||||
multi_attack_proc =
|
||||
Some(MultiAttack::DoubleTap { first_shot: true })
|
||||
}
|
||||
};
|
||||
metrics.increment_counter(Some(player), bonus.counter_label(), 1);
|
||||
metrics.increment_counter(Some(weapon), bonus.counter_label(), 1);
|
||||
shared.metrics.increment_counter(
|
||||
Some(player),
|
||||
bonus.counter_label(),
|
||||
1,
|
||||
);
|
||||
shared.metrics.increment_counter(
|
||||
Some(weapon),
|
||||
bonus.counter_label(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
DamageProcEffect::SelfEffect { value, bonus } => {
|
||||
let chance = (value / 100.0) as f64;
|
||||
if chance > 1.0 || rng.random_bool(chance) {
|
||||
bonus.spawn(player, &mut effects);
|
||||
if chance > 1.0 || shared.rng.random_bool(chance) {
|
||||
bonus.spawn(player, &mut shared.effects);
|
||||
}
|
||||
}
|
||||
DamageProcEffect::OpponentEffect { value, bonus } => {
|
||||
let chance = (value / 100.0) as f64;
|
||||
if chance > 1.0 || rng.random_bool(chance) {
|
||||
bonus.spawn(target, &mut effects, &mut rng.0);
|
||||
if chance > 1.0 || shared.rng.random_bool(chance) {
|
||||
bonus.spawn(target, &mut shared.effects, &mut shared.rng.0);
|
||||
}
|
||||
}
|
||||
DamageProcEffect::DamageOverTime { value, kind } => {
|
||||
let chance = (value / 100.0) as f64;
|
||||
if chance > 1.0 || rng.random_bool(chance) {
|
||||
if chance > 1.0 || shared.rng.random_bool(chance) {
|
||||
match kind {
|
||||
DamageOverTimeType::Bleed => {
|
||||
commands
|
||||
.entity(target)
|
||||
.insert(DamageOverTime::<Bleed>::new(dmg_i));
|
||||
shared.commands.entity(target).insert(DamageOverTime::<
|
||||
Bleed,
|
||||
>::new(
|
||||
dmg_i
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DamageProcEffect::Deadly { chance } => {
|
||||
if chance >= 1.0 || rng.random_bool(chance as f64) {
|
||||
if chance >= 1.0 || shared.rng.random_bool(chance as f64) {
|
||||
dmg = dmg_intrinsic
|
||||
* w_dmg.0
|
||||
* (1.0 + dmg_bonus.value + spammo_bonus + 5.0)
|
||||
|
|
@ -570,15 +656,15 @@ pub fn use_damaging_weapon(
|
|||
}
|
||||
DamageProcEffect::Execute { cutoff } => {
|
||||
if health.0 as f32 / target_max_health.value as f32 <= cutoff {
|
||||
commands.entity(target).insert(Defeated);
|
||||
shared.commands.entity(target).insert(Defeated);
|
||||
let health_before = health.0;
|
||||
health.0 = 0;
|
||||
log!(logger, "executed", {
|
||||
log!(shared.logger, "executed", {
|
||||
actor: player,
|
||||
recipient: target,
|
||||
health_before,
|
||||
});
|
||||
log!(logger, "fight_end", {
|
||||
log!(shared.logger, "fight_end", {
|
||||
actor: player,
|
||||
recipient: target,
|
||||
fight_end_type: %if attacker {
|
||||
|
|
@ -587,7 +673,7 @@ pub fn use_damaging_weapon(
|
|||
FightEndType::Loss
|
||||
},
|
||||
});
|
||||
metrics.increment_counter(Some(player), "victory", 1);
|
||||
shared.metrics.increment_counter(Some(player), "victory", 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -599,7 +685,7 @@ pub fn use_damaging_weapon(
|
|||
|
||||
health.0 = health.0.saturating_sub(dmg_i as u16);
|
||||
|
||||
log!(logger, "hit_target", {
|
||||
log!(shared.logger, "hit_target", {
|
||||
actor: player,
|
||||
acc: acc_eff.value,
|
||||
recipient: target,
|
||||
|
|
@ -624,8 +710,8 @@ pub fn use_damaging_weapon(
|
|||
if health.0 == 0 && !defeated {
|
||||
defeated = true;
|
||||
|
||||
commands.entity(target).insert(Defeated);
|
||||
log!(logger, "fight_end", {
|
||||
shared.commands.entity(target).insert(Defeated);
|
||||
log!(shared.logger, "fight_end", {
|
||||
actor: player,
|
||||
recipient: target,
|
||||
fight_end_type: %if attacker {
|
||||
|
|
@ -634,7 +720,7 @@ pub fn use_damaging_weapon(
|
|||
FightEndType::Loss
|
||||
},
|
||||
});
|
||||
metrics.increment_counter(Some(player), "victory", 1);
|
||||
shared.metrics.increment_counter(Some(player), "victory", 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue