use serde_string_enum::{
DeserializeLabeledStringEnum,
SerializeLabeledStringEnum,
};
use crate::battle::EventResult;
#[derive(
Debug, Clone, Copy, PartialEq, Eq, SerializeLabeledStringEnum, DeserializeLabeledStringEnum,
)]
pub enum MoveOutcome {
#[string = "Skipped"]
Skipped,
#[string = "Failed"]
Failed,
#[string = "Succeeded"]
Succeeded,
}
impl MoveOutcome {
pub fn succeeded(&self) -> bool {
match self {
Self::Succeeded => true,
_ => false,
}
}
pub fn failed(&self) -> bool {
match self {
Self::Failed => true,
_ => false,
}
}
}
impl From<bool> for MoveOutcome {
fn from(value: bool) -> Self {
if value { Self::Succeeded } else { Self::Failed }
}
}
impl From<MoveOutcomeOnTarget> for MoveOutcome {
fn from(value: MoveOutcomeOnTarget) -> Self {
if value.success() {
MoveOutcome::Succeeded
} else if value.failed() {
MoveOutcome::Failed
} else {
MoveOutcome::Skipped
}
}
}
impl From<EventResult> for MoveOutcome {
fn from(value: EventResult) -> Self {
match value {
EventResult::Fail | EventResult::StopFail => Self::Failed,
EventResult::StopReportFail | EventResult::Stop | EventResult::Skip => Self::Skipped,
EventResult::Advance => Self::Succeeded,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MoveOutcomeOnTarget {
Unknown,
EventResult(EventResult),
HitSubstitute,
Damage(u16),
}
impl MoveOutcomeOnTarget {
fn success(&self) -> bool {
match self {
Self::Unknown | Self::Damage(_) | Self::HitSubstitute => true,
Self::EventResult(result) => result.advance(),
}
}
pub fn hit(&self) -> bool {
self.success()
}
pub fn advance(&self) -> bool {
self.success() && *self != Self::HitSubstitute
}
pub fn failed(&self) -> bool {
match self {
Self::EventResult(result) => result.failed(),
_ => false,
}
}
pub fn report_failure(&self) -> bool {
match self {
Self::EventResult(result) => result.report_failure(),
_ => false,
}
}
pub fn do_not_animate(&self) -> bool {
match self {
Self::EventResult(result) => result.do_not_animate(),
_ => false,
}
}
pub fn damage(&self) -> u16 {
match self {
Self::Damage(damage) => *damage,
_ => 0,
}
}
pub fn combine(&self, other: Self) -> Self {
match (*self, other) {
(Self::Unknown, right) => right,
(left @ _, Self::Unknown) => left,
(Self::HitSubstitute, right) => right,
(Self::EventResult(a), Self::EventResult(b)) => Self::EventResult(a.combine(b)),
(Self::Damage(left), Self::Damage(right)) => Self::Damage(left + right),
(left @ Self::Damage(_), _) => left,
(_, right @ Self::Damage(_)) => right,
(left @ Self::EventResult(result), _) if result.advance() => left,
(Self::EventResult(_), right) => right,
}
}
}
impl Default for MoveOutcomeOnTarget {
fn default() -> Self {
Self::EventResult(EventResult::default())
}
}
impl From<bool> for MoveOutcomeOnTarget {
fn from(value: bool) -> Self {
Self::EventResult(EventResult::from(value))
}
}
impl From<EventResult> for MoveOutcomeOnTarget {
fn from(value: EventResult) -> Self {
Self::EventResult(value)
}
}