added log! macro
This commit is contained in:
parent
86f9333aec
commit
b45d04b872
5 changed files with 140 additions and 522 deletions
|
|
@ -1,28 +1,22 @@
|
|||
use bevy_ecs::prelude::*;
|
||||
use macros::LogMessage;
|
||||
use rand::Rng as _;
|
||||
|
||||
use crate::{
|
||||
effect::{Effects, TurnLimitedEffect},
|
||||
hierarchy::{HierarchyBuilder, Parent},
|
||||
log::Logger,
|
||||
metrics::Metrics,
|
||||
passives::{Education, FactionUpgrades, Merits},
|
||||
player::{
|
||||
stats::{
|
||||
AdditiveBonus, AmmoControl, ClipSize, Clips, CritRate, DamageBonus, Dexterity,
|
||||
EffectiveStat, SimpleStatBonus, SimpleStatBundle, SimpleStatEffective, Speed,
|
||||
WeaponAccuracy,
|
||||
SimpleStatBonus, SimpleStatBundle, SimpleStatEffective, WeaponAccuracy,
|
||||
},
|
||||
BodyPart, Current, CurrentTarget, InitiateHit, Player, Weapons,
|
||||
Current, Weapons,
|
||||
},
|
||||
Id, Name, Rng, Stages,
|
||||
Id, Name, Stages,
|
||||
};
|
||||
|
||||
use self::{
|
||||
bonus::{FirstTurnBonus, MultiTurnBonus, TurnTriggeredBonus},
|
||||
temp::{NonTargeted, Uses},
|
||||
};
|
||||
use self::bonus::{FirstTurnBonus, MultiTurnBonus, TurnTriggeredBonus};
|
||||
|
||||
pub mod bonus;
|
||||
pub mod temp;
|
||||
|
|
@ -685,203 +679,6 @@ fn unset_current(weapon_q: Query<Entity, (With<Current>, With<Weapon>)>, mut com
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Move all mitigation aspects of this into the player system
|
||||
pub fn use_damaging_weapon(
|
||||
mut rng: ResMut<Rng>,
|
||||
weapon_q: Query<
|
||||
(
|
||||
Entity,
|
||||
&DamageStat,
|
||||
&SimpleStatEffective<WeaponAccuracy>,
|
||||
&SimpleStatEffective<DamageBonus>,
|
||||
&SimpleStatEffective<CritRate>,
|
||||
Has<NonTargeted>,
|
||||
),
|
||||
(With<Weapon>, With<Current>, Without<NeedsReload>),
|
||||
>,
|
||||
player_q: Query<
|
||||
(
|
||||
Entity,
|
||||
&EffectiveStat<Speed>,
|
||||
&SimpleStatEffective<CritRate>,
|
||||
&SimpleStatEffective<WeaponAccuracy>,
|
||||
&SimpleStatEffective<DamageBonus>,
|
||||
),
|
||||
(With<Player>, With<Current>),
|
||||
>,
|
||||
target_q: Query<(Entity, &EffectiveStat<Dexterity>), With<CurrentTarget>>,
|
||||
(mut ammo_q, mut temp_q): (
|
||||
Query<(
|
||||
&mut Ammo,
|
||||
&SimpleStatEffective<Clips>,
|
||||
&RateOfFire,
|
||||
&SimpleStatEffective<AmmoControl>,
|
||||
)>,
|
||||
Query<&mut Uses>,
|
||||
),
|
||||
mut hit_events: EventWriter<InitiateHit>,
|
||||
(mut logger, mut commands, metrics): (Logger, Commands, Res<Metrics>),
|
||||
) {
|
||||
let Ok((weapon, dmg, acc, dmg_bonus, crit, non_targeted)) = weapon_q.get_single() else {
|
||||
return;
|
||||
};
|
||||
let (player, player_spd, player_crit, acc_bonus, p_dmg_bonus) = player_q.single();
|
||||
let (target, target_dex) = target_q.single();
|
||||
|
||||
if let Ok(mut uses) = temp_q.get_mut(weapon) {
|
||||
uses.0 -= 1;
|
||||
if uses.0 == 0 {
|
||||
commands.entity(weapon).remove::<Usable>();
|
||||
}
|
||||
}
|
||||
|
||||
let spd_dex_ratio = (player_spd.value / target_dex.value).clamp(1.0 / 64.0, 64.0);
|
||||
let base_hit_chance = if spd_dex_ratio < 1.0 {
|
||||
0.5 * (8.0 * spd_dex_ratio.sqrt() - 1.0) / 7.0
|
||||
} else {
|
||||
1.0 - 0.5 * (8.0 / spd_dex_ratio.sqrt() - 1.0) / 7.0
|
||||
};
|
||||
|
||||
let mut acc_eff = acc + acc_bonus;
|
||||
|
||||
let mut ammo = ammo_q
|
||||
.get_mut(weapon)
|
||||
.ok()
|
||||
.map(|(ammo, clips, rof, ammo_ctrl)| {
|
||||
let ammo_ctrl = 1.0 - (ammo_ctrl).value;
|
||||
let rof_eff = ((rof.0[0] as f32) * ammo_ctrl)..((rof.0[1] as f32) * ammo_ctrl);
|
||||
(ammo, clips, rof_eff)
|
||||
});
|
||||
|
||||
enum MultiAttack {
|
||||
Blindfire,
|
||||
Rage(usize),
|
||||
Fury(usize),
|
||||
DoubleTap { fired_first: bool },
|
||||
}
|
||||
|
||||
let mut multi_attack_proc = None;
|
||||
let crit = player_crit + crit;
|
||||
|
||||
loop {
|
||||
let rounds = ammo.as_mut().map(|(ref mut ammo, clips, rof)| {
|
||||
let rounds = (rng.gen_range(rof.clone()).round() as u16).clamp(1, ammo.0);
|
||||
metrics.increment_counter(player, "rounds_fired", rounds.into());
|
||||
metrics.increment_counter(weapon, "rounds_fired", rounds.into());
|
||||
ammo.0 -= rounds;
|
||||
if ammo.0 == 0 {
|
||||
if clips.value == 0 {
|
||||
commands.entity(weapon).remove::<Usable>();
|
||||
} else {
|
||||
commands.entity(weapon).insert(NeedsReload);
|
||||
}
|
||||
}
|
||||
rounds
|
||||
});
|
||||
|
||||
let hit_chance = if base_hit_chance < 0.5 {
|
||||
base_hit_chance + acc_eff.value * base_hit_chance
|
||||
} else {
|
||||
base_hit_chance + acc_eff.value * (1.0 - base_hit_chance)
|
||||
};
|
||||
|
||||
if hit_chance <= 1.0 && !rng.gen_bool(hit_chance as f64) {
|
||||
logger.log(|| MissTarget {
|
||||
weapon,
|
||||
actor: player,
|
||||
recipient: target,
|
||||
rounds,
|
||||
});
|
||||
metrics.increment_counter(player, "miss", 1);
|
||||
metrics.increment_counter(weapon, "miss", 1);
|
||||
|
||||
if multi_attack_proc.is_none() {
|
||||
return;
|
||||
};
|
||||
} else {
|
||||
let body_part = if !non_targeted {
|
||||
rng.sample(crit)
|
||||
} else {
|
||||
BodyPart::Stomach
|
||||
};
|
||||
|
||||
hit_events.send(InitiateHit {
|
||||
body_part,
|
||||
weapon,
|
||||
rounds,
|
||||
dmg: dmg.0,
|
||||
dmg_bonus_weapon: dmg_bonus.value,
|
||||
dmg_bonus_player: p_dmg_bonus.value,
|
||||
hit_chance,
|
||||
crit_rate: crit.value,
|
||||
});
|
||||
}
|
||||
|
||||
match multi_attack_proc {
|
||||
Some(MultiAttack::Blindfire) => acc_eff.value -= 5.0 / 50.0,
|
||||
Some(MultiAttack::Rage(turns @ 1..)) => {
|
||||
multi_attack_proc = Some(MultiAttack::Rage(turns - 1))
|
||||
}
|
||||
Some(MultiAttack::Fury(turns @ 1..)) => {
|
||||
multi_attack_proc = Some(MultiAttack::Fury(turns - 1))
|
||||
}
|
||||
Some(MultiAttack::DoubleTap { fired_first: false }) => {
|
||||
multi_attack_proc = Some(MultiAttack::DoubleTap { fired_first: true })
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
/*
|
||||
let hit_chance = if base_hit_chance < 0.5 {
|
||||
base_hit_chance + acc_eff.value * base_hit_chance
|
||||
} else {
|
||||
base_hit_chance + acc_eff.value * (1.0 - base_hit_chance)
|
||||
};
|
||||
|
||||
if hit_chance <= 1.0 && !rng.gen_bool(hit_chance as f64) {
|
||||
logger.log(|| MissTarget {
|
||||
weapon,
|
||||
actor: player,
|
||||
recipient: target,
|
||||
rounds: rounds.map(|(rounds, _)| rounds),
|
||||
});
|
||||
metrics.increment_counter(player, "miss", 1);
|
||||
metrics.increment_counter(weapon, "miss", 1);
|
||||
return;
|
||||
}
|
||||
|
||||
let crit = player_crit + crit;
|
||||
|
||||
let body_part = if !non_targeted {
|
||||
rng.sample(crit)
|
||||
} else {
|
||||
BodyPart::Stomach
|
||||
};
|
||||
|
||||
let def_str_ratio = (target_def.value / player_str.value).clamp(1.0 / 32.0, 14.0);
|
||||
let mitigation = if def_str_ratio < 1.0 {
|
||||
0.5 * def_str_ratio.log(32.0) + 0.5
|
||||
} else {
|
||||
0.5 * def_str_ratio.log(14.0) + 0.5
|
||||
};
|
||||
|
||||
let dmg_intrinsic = 7.0 * (player_str.value / 10.0).log10().powi(2)
|
||||
+ 27.0 * (player_str.value / 10.0).log10()
|
||||
+ 30.0;
|
||||
|
||||
init_hit.send(InitiateHit {
|
||||
body_part,
|
||||
weapon,
|
||||
rounds: rounds.map(|(rounds, _)| rounds),
|
||||
crit_rate: crit.value,
|
||||
dmg: dmg.0,
|
||||
dmg_bonus_weapon: (dmg_bonus + p_dmg_bonus).value,
|
||||
dmg_intrinsic,
|
||||
def_mitigation: mitigation,
|
||||
hit_chance,
|
||||
}); */
|
||||
}
|
||||
|
||||
fn reload_weapon(
|
||||
mut weapon_q: Query<
|
||||
(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue