#[macro_export]
macro_rules! effect {
($id:expr, $kind:expr, { $( $ev:ident $( ( $ord:expr ) )? => $fn:path ),* $(,)? }) => {
$crate::battle::stack::event::Effect {
id: $id,
kind: $kind,
hooks: &[ $(
$crate::battle::stack::event::EventHook {
event: $crate::battle::stack::event::Event::$ev,
call: $fn,
order: $crate::effect!(@ord $( $ord )?),
priority: 0,
sub_order: None,
},
)* ],
}
};
(@ord $o:expr) => { $o };
(@ord) => { u32::MAX };
}
#[cfg(test)]
mod tests {
use crate::battle::stack::ctx::{BattleCtx, EffectProvider};
use crate::battle::stack::event::{
EffectId, EffectType, Event, HandlerResult, RelayVar,
};
use crate::battle::BattlerRef;
fn noop<P: EffectProvider + ?Sized>(
_c: &mut BattleCtx<'_, P>,
_r: RelayVar,
_t: BattlerRef,
_s: BattlerRef,
_e: EffectId,
) -> HandlerResult {
HandlerResult::Unchanged
}
use crate::battle::stack::tests_support::TProvider;
#[test]
fn effect_macro_builds_expected_hooks() {
let eff = effect!(EffectId(0x10), EffectType::Move, {
DamagingHit => noop::<TProvider>,
Residual(20) => noop::<TProvider>,
});
assert_eq!(eff.id, EffectId(0x10));
assert_eq!(eff.kind, EffectType::Move);
assert_eq!(eff.hooks.len(), 2);
assert_eq!(eff.hooks[0].event, Event::DamagingHit);
assert_eq!(eff.hooks[0].order, u32::MAX);
assert_eq!(eff.hooks[0].priority, 0);
assert_eq!(eff.hooks[0].sub_order, None);
assert_eq!(eff.hooks[1].event, Event::Residual);
assert_eq!(eff.hooks[1].order, 20);
}
#[test]
fn relay_typed_accessors_and_scale() {
assert_eq!(RelayVar::Int(7).as_int(), 7);
assert_eq!(RelayVar::Unit.as_int(), 0);
assert_eq!(RelayVar::Damage(40).as_damage(), 40);
assert_eq!(RelayVar::Int(0).as_damage(), 0);
assert_eq!(RelayVar::Accuracy(200).as_accuracy(), 200);
assert!(RelayVar::Bool(true).as_bool());
assert!(!RelayVar::Bool(false).as_bool());
assert!(!RelayVar::Unit.as_bool());
assert_eq!(RelayVar::Int(10).scale(3, 2), RelayVar::Int(15));
assert_eq!(RelayVar::Damage(40).scale(3, 2), RelayVar::Damage(60));
assert_eq!(RelayVar::Damage(100).scale(1, 2), RelayVar::Damage(50));
assert_eq!(RelayVar::Int(10).scale(2, 0), RelayVar::Int(20));
assert_eq!(RelayVar::Unit.scale(3, 2), RelayVar::Unit);
}
}