use crate::battle::{Battle, BattleRules, BattleState};
use crate::character::Character;
use crate::entropy::Entropy;
use crate::error::WeaselResult;
use crate::event::{Event, EventKind, EventProcessor, EventQueue, EventTrigger, LinkedQueue};
use crate::metric::WriteMetrics;
use crate::status::{Application, AppliedStatus};
#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
use std::any::Any;
use std::fmt::Debug;
pub trait FightRules<R: BattleRules> {
#[cfg(not(feature = "serialization"))]
type Impact: Clone + Debug + Send;
#[cfg(feature = "serialization")]
type Impact: Clone + Debug + Send + Serialize + for<'a> Deserialize<'a>;
#[cfg(not(feature = "serialization"))]
type Potency: Clone + Debug + Send;
#[cfg(feature = "serialization")]
type Potency: Clone + Debug + Send + Serialize + for<'a> Deserialize<'a>;
fn apply_impact(
&self,
_state: &BattleState<R>,
_impact: &Self::Impact,
_event_queue: &mut Option<EventQueue<R>>,
_entropy: &mut Entropy<R>,
_metrics: &mut WriteMetrics<R>,
) {
}
fn apply_status(
&self,
_state: &BattleState<R>,
_character: &dyn Character<R>,
_application: Application<R>,
_event_queue: &mut Option<EventQueue<R>>,
_entropy: &mut Entropy<R>,
_metrics: &mut WriteMetrics<R>,
) {
}
fn update_status(
&self,
_state: &BattleState<R>,
_character: &dyn Character<R>,
_status: &AppliedStatus<R>,
_linked_queue: &mut Option<LinkedQueue<R>>,
_entropy: &mut Entropy<R>,
_metrics: &mut WriteMetrics<R>,
) -> bool {
false
}
fn delete_status(
&self,
_state: &BattleState<R>,
_character: &dyn Character<R>,
_status: &AppliedStatus<R>,
_event_queue: &mut Option<EventQueue<R>>,
_entropy: &mut Entropy<R>,
_metrics: &mut WriteMetrics<R>,
) {
}
}
pub type Impact<R> = <<R as BattleRules>::FR as FightRules<R>>::Impact;
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct ApplyImpact<R: BattleRules> {
#[cfg_attr(
feature = "serialization",
serde(bound(
serialize = "Impact<R>: Serialize",
deserialize = "Impact<R>: Deserialize<'de>"
))
)]
impact: Impact<R>,
}
impl<R: BattleRules> ApplyImpact<R> {
pub fn trigger<'a, P: EventProcessor<R>>(
processor: &'a mut P,
impact: Impact<R>,
) -> ApplyImpactTrigger<'a, R, P> {
ApplyImpactTrigger { processor, impact }
}
pub fn impact(&self) -> &Impact<R> {
&self.impact
}
}
impl<R: BattleRules> std::fmt::Debug for ApplyImpact<R> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "ApplyImpact {{ impact: {:?} }}", self.impact)
}
}
impl<R: BattleRules> Clone for ApplyImpact<R> {
fn clone(&self) -> Self {
Self {
impact: self.impact.clone(),
}
}
}
impl<R: BattleRules + 'static> Event<R> for ApplyImpact<R> {
fn verify(&self, _: &Battle<R>) -> WeaselResult<(), R> {
Ok(())
}
fn apply(&self, battle: &mut Battle<R>, event_queue: &mut Option<EventQueue<R>>) {
battle.rules.fight_rules().apply_impact(
&battle.state,
&self.impact,
event_queue,
&mut battle.entropy,
&mut battle.metrics.write_handle(),
);
}
fn kind(&self) -> EventKind {
EventKind::ApplyImpact
}
fn box_clone(&self) -> Box<dyn Event<R> + Send> {
Box::new(self.clone())
}
fn as_any(&self) -> &dyn Any {
self
}
}
pub struct ApplyImpactTrigger<'a, R, P>
where
R: BattleRules,
P: EventProcessor<R>,
{
processor: &'a mut P,
impact: Impact<R>,
}
impl<'a, R, P> EventTrigger<'a, R, P> for ApplyImpactTrigger<'a, R, P>
where
R: BattleRules + 'static,
P: EventProcessor<R>,
{
fn processor(&'a mut self) -> &'a mut P {
self.processor
}
fn event(&self) -> Box<dyn Event<R> + Send> {
Box::new(ApplyImpact {
impact: self.impact.clone(),
})
}
}