fixed first round effect and migrated logging
This commit is contained in:
parent
b45d04b872
commit
e7d6b74aab
10 changed files with 539 additions and 222 deletions
236
src/log.rs
236
src/log.rs
|
|
@ -1,7 +1,6 @@
|
|||
use std::sync::Mutex;
|
||||
|
||||
use bevy_ecs::{prelude::*, system::SystemParam};
|
||||
use macros::LogMessage;
|
||||
|
||||
use crate::{
|
||||
entity_registry::EntityRegistry,
|
||||
|
|
@ -9,7 +8,7 @@ use crate::{
|
|||
player::stats::{
|
||||
AdditiveBonus, BaselineStat, CritRate, DamageBonus, Defence, Dexterity, EffectiveStat,
|
||||
MultiplicativeBonus, SimpleStatBaseline, SimpleStatBonus, SimpleStatEffective,
|
||||
SimpleStatMarker, Speed, StatMarker, StatType, Strength, WeaponAccuracy,
|
||||
SimpleStatMarker, Speed, StatMarker, Strength, WeaponAccuracy,
|
||||
},
|
||||
weapon::WeaponVerb,
|
||||
Stages,
|
||||
|
|
@ -19,14 +18,11 @@ use crate::{
|
|||
pub struct Logging(pub bool);
|
||||
|
||||
#[derive(Event)]
|
||||
struct LogEvent(Mutex<Option<Box<dyn LogMessage>>>);
|
||||
struct LogEvent(Mutex<Option<DynamicLogMessage>>);
|
||||
|
||||
impl<T> From<T> for LogEvent
|
||||
where
|
||||
T: LogMessage,
|
||||
{
|
||||
fn from(value: T) -> Self {
|
||||
Self(Mutex::new(Some(Box::new(value))))
|
||||
impl From<DynamicLogMessage> for LogEvent {
|
||||
fn from(value: DynamicLogMessage) -> Self {
|
||||
LogEvent(Mutex::new(Some(value)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -53,6 +49,8 @@ pub enum LogValue<'a> {
|
|||
Debug(&'a (dyn std::fmt::Debug + Send + Sync)),
|
||||
Player(Entity),
|
||||
Weapon(Entity),
|
||||
Array(Vec<LogValue<'a>>),
|
||||
Map(Vec<(&'static str, LogValue<'a>)>),
|
||||
}
|
||||
|
||||
impl<'a> From<String> for LogValue<'a> {
|
||||
|
|
@ -61,6 +59,12 @@ impl<'a> From<String> for LogValue<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for LogValue<'static> {
|
||||
fn from(value: &'a str) -> Self {
|
||||
Self::String(value.to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<f32> for LogValue<'a> {
|
||||
fn from(value: f32) -> Self {
|
||||
Self::Float(value)
|
||||
|
|
@ -103,6 +107,24 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, V> From<Vec<V>> for LogValue<'a>
|
||||
where
|
||||
V: Into<LogValue<'a>>,
|
||||
{
|
||||
fn from(value: Vec<V>) -> Self {
|
||||
LogValue::Array(value.into_iter().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, V> From<Vec<(&'static str, V)>> for LogValue<'a>
|
||||
where
|
||||
V: Into<LogValue<'a>>,
|
||||
{
|
||||
fn from(value: Vec<(&'static str, V)>) -> Self {
|
||||
LogValue::Map(value.into_iter().map(|(k, v)| (k, v.into())).collect())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
impl<'a> LogValue<'a> {
|
||||
fn to_value(&self, entity_registry: &EntityRegistry) -> serde_json::Value {
|
||||
|
|
@ -125,11 +147,19 @@ impl<'a> LogValue<'a> {
|
|||
LogValue::Entity(id) => {
|
||||
serde_json::to_value(entity_registry.0.get(id).unwrap()).unwrap()
|
||||
}
|
||||
LogValue::Array(items) => serde_json::Value::Array(
|
||||
items.iter().map(|v| v.to_value(entity_registry)).collect(),
|
||||
),
|
||||
LogValue::Map(map) => serde_json::Value::Object(
|
||||
map.iter()
|
||||
.map(|(k, v)| ((*k).to_owned(), v.to_value(entity_registry)))
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LogMessage: Send + Sync + 'static {
|
||||
trait LogMessage: Send + Sync + 'static {
|
||||
fn tag(&self) -> &'static str;
|
||||
|
||||
fn entries(&self) -> Vec<(&'static str, LogValue<'_>)>;
|
||||
|
|
@ -137,7 +167,7 @@ pub trait LogMessage: Send + Sync + 'static {
|
|||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct Log {
|
||||
pub entries: Vec<Box<dyn LogMessage>>,
|
||||
entries: Vec<DynamicLogMessage>,
|
||||
|
||||
pub expanded: bool,
|
||||
}
|
||||
|
|
@ -158,6 +188,10 @@ impl Log {
|
|||
).collect::<Vec<_>>()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.entries.clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Log {
|
||||
|
|
@ -184,6 +218,7 @@ impl std::fmt::Display for Log {
|
|||
LogValue::Player(id) | LogValue::Weapon(id) | LogValue::Entity(id) => {
|
||||
write!(f, "{:?}", id)?
|
||||
}
|
||||
LogValue::Array(_) | LogValue::Map(_) => (),
|
||||
};
|
||||
|
||||
if fields.peek().is_some() {
|
||||
|
|
@ -391,10 +426,9 @@ pub struct Logger<'w> {
|
|||
}
|
||||
|
||||
impl<'w> Logger<'w> {
|
||||
pub fn log<B, M>(&mut self, body: B)
|
||||
pub fn log<B>(&mut self, body: B)
|
||||
where
|
||||
B: FnOnce() -> M,
|
||||
M: LogMessage,
|
||||
B: FnOnce() -> DynamicLogMessage,
|
||||
{
|
||||
if self.logging.0 {
|
||||
self.event_writer.send(body().into());
|
||||
|
|
@ -408,99 +442,9 @@ fn logging_enabled(logging: Res<Logging>) -> bool {
|
|||
|
||||
fn append_log_messages(mut events: EventReader<LogEvent>, mut log: ResMut<Log>) {
|
||||
for event in events.read() {
|
||||
log.entries.push(event.0.lock().unwrap().take().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(macros::LogMessage)]
|
||||
struct StatChange {
|
||||
#[log(player)]
|
||||
target: Entity,
|
||||
#[log(debug)]
|
||||
stat: StatType,
|
||||
|
||||
#[log(debug)]
|
||||
effects_add: Vec<(&'static str, f32)>,
|
||||
|
||||
#[log(debug)]
|
||||
effects_mult: Vec<(&'static str, f32)>,
|
||||
|
||||
baseline: f32,
|
||||
|
||||
effective: f32,
|
||||
}
|
||||
|
||||
fn log_stat_changes<Stat: StatMarker>(
|
||||
stat_q: Query<
|
||||
(Entity, &BaselineStat<Stat>, &EffectiveStat<Stat>, &Children),
|
||||
Changed<EffectiveStat<Stat>>,
|
||||
>,
|
||||
add_q: Query<&AdditiveBonus<Stat>>,
|
||||
mult_q: Query<&MultiplicativeBonus<Stat>>,
|
||||
mut logger: Logger,
|
||||
) {
|
||||
for (player, baseline, effective, children) in stat_q.iter() {
|
||||
let effects_add = add_q
|
||||
.iter_many(children.get())
|
||||
.map(|eff| (eff.label, eff.value))
|
||||
.collect();
|
||||
let effects_mult = mult_q
|
||||
.iter_many(children.get())
|
||||
.map(|eff| (eff.label, eff.value))
|
||||
.collect();
|
||||
|
||||
logger.log(|| StatChange {
|
||||
target: player,
|
||||
stat: Stat::stat_type(),
|
||||
effects_add,
|
||||
effects_mult,
|
||||
baseline: baseline.value,
|
||||
effective: effective.value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn log_simple_stat_changes<Stat: SimpleStatMarker>(
|
||||
stat_q: Query<
|
||||
(
|
||||
Entity,
|
||||
&SimpleStatBaseline<Stat>,
|
||||
&SimpleStatEffective<Stat>,
|
||||
&Children,
|
||||
),
|
||||
Changed<SimpleStatEffective<Stat>>,
|
||||
>,
|
||||
bonus_q: Query<&SimpleStatBonus<Stat>>,
|
||||
mut logger: Logger,
|
||||
) where
|
||||
Stat::ValueType: Into<LogValue<'static>>,
|
||||
Stat::BonusType: std::fmt::Debug,
|
||||
{
|
||||
#[derive(LogMessage)]
|
||||
struct AppliedBonus {
|
||||
#[log(debug)]
|
||||
target: Entity,
|
||||
#[log(display)]
|
||||
stat: &'static str,
|
||||
baseline: LogValue<'static>,
|
||||
effective: LogValue<'static>,
|
||||
#[log(debug)]
|
||||
bonuses: Vec<(&'static str, String)>,
|
||||
}
|
||||
|
||||
for (target, baseline, effective, children) in stat_q.iter() {
|
||||
let bonuses = bonus_q
|
||||
.iter_many(children.get())
|
||||
.map(|eff| (eff.label, format!("{:?}", eff.value)))
|
||||
.collect();
|
||||
|
||||
logger.log(|| AppliedBonus {
|
||||
target,
|
||||
stat: std::any::type_name::<Stat>(),
|
||||
baseline: baseline.value.into(),
|
||||
effective: effective.value.into(),
|
||||
bonuses,
|
||||
});
|
||||
if let Some(entry) = event.0.lock().unwrap().take() {
|
||||
log.entries.push(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,18 +491,94 @@ macro_rules! log_values {
|
|||
(@ { $(,)* $($out:expr),* } $label:ident: %$val:expr, $($rest:tt)*) => {
|
||||
$crate::log_values!(@ { $($out),*, (stringify!($label),$crate::log::LogValue::String(format!("{}",$val))) } $($rest)*)
|
||||
};
|
||||
(@ { $(,)* $($out:expr),* } $value:ident, $($rest:tt)*) => {
|
||||
$crate::log_values!(@ { $($out),*, (stringify!($value),$value.into()) } $($rest)*)
|
||||
};
|
||||
(@ { $(,)* $($out:expr),* } ?$value:ident, $($rest:tt)*) => {
|
||||
$crate::log_values!(@ { $($out),*, (stringify!($value),$crate::log::LogValue::String(format!("{:?}",$val))) } $($rest)*)
|
||||
};
|
||||
(@ { $(,)* $($out:expr),* } %$value:ident, $($rest:tt)*) => {
|
||||
$crate::log_values!(@ { $($out),*, (stringify!($value),$crate::log::LogValue::String(format!("{}",$val))) } $($rest)*)
|
||||
};
|
||||
|
||||
($($args:tt)* ) => {
|
||||
$crate::log_values!(@ { } $($args)*,)
|
||||
};
|
||||
}
|
||||
|
||||
fn log_stat_changes<Stat: StatMarker>(
|
||||
stat_q: Query<
|
||||
(Entity, &BaselineStat<Stat>, &EffectiveStat<Stat>, &Children),
|
||||
Changed<EffectiveStat<Stat>>,
|
||||
>,
|
||||
add_q: Query<&AdditiveBonus<Stat>>,
|
||||
mult_q: Query<&MultiplicativeBonus<Stat>>,
|
||||
mut logger: Logger,
|
||||
) {
|
||||
for (player, baseline, effective, children) in stat_q.iter() {
|
||||
let effects_add: Vec<_> = add_q
|
||||
.iter_many(children.get())
|
||||
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
||||
.collect();
|
||||
let effects_mult: Vec<_> = mult_q
|
||||
.iter_many(children.get())
|
||||
.map(|bonus| (bonus.label, 100.0 * bonus.value))
|
||||
.collect();
|
||||
|
||||
log!(logger, "stat_change", {
|
||||
target: player,
|
||||
stat: ?Stat::stat_type(),
|
||||
effects_add,
|
||||
effects_mult,
|
||||
baseline: baseline.value,
|
||||
effective: effective.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn log_simple_stat_changes<Stat: SimpleStatMarker>(
|
||||
stat_q: Query<
|
||||
(
|
||||
Entity,
|
||||
&SimpleStatBaseline<Stat>,
|
||||
&SimpleStatEffective<Stat>,
|
||||
&Children,
|
||||
),
|
||||
Changed<SimpleStatEffective<Stat>>,
|
||||
>,
|
||||
bonus_q: Query<&SimpleStatBonus<Stat>>,
|
||||
mut logger: Logger,
|
||||
) where
|
||||
Stat::ValueType: Into<LogValue<'static>>,
|
||||
Stat::BonusType: Into<LogValue<'static>>,
|
||||
{
|
||||
for (target, baseline, effective, children) in stat_q.iter() {
|
||||
let bonuses: Vec<_> = bonus_q
|
||||
.iter_many(children.get())
|
||||
.map(|bonus| (bonus.label, Stat::denormalise_bonus(bonus.value)))
|
||||
.collect();
|
||||
|
||||
log!(logger, "applied_bonus", {
|
||||
target,
|
||||
stat: std::any::type_name::<Stat>(),
|
||||
baseline: Stat::denormalise_value(baseline.value),
|
||||
effective: Stat::denormalise_value(effective.value),
|
||||
bonuses
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn configure(stages: &mut Stages) {
|
||||
stages.world.insert_resource(Log::default());
|
||||
stages.world.insert_resource(Logging(false));
|
||||
stages.add_event::<LogEvent>();
|
||||
|
||||
stages.post_turn.add_systems(append_log_messages);
|
||||
stages
|
||||
.post_turn
|
||||
.add_systems(append_log_messages.run_if(logging_enabled));
|
||||
stages
|
||||
.post_fight
|
||||
.add_systems(append_log_messages.run_if(logging_enabled));
|
||||
stages.turn.add_systems(
|
||||
(
|
||||
log_stat_changes::<Strength>,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue