Skip to main content

manabrew_engine/trigger/
trigger_discarded.rs

1use serde::{Deserialize, Serialize};
2
3use crate::event::RunParams;
4use crate::game::GameState;
5use crate::parsing::{keys, Params};
6use crate::spellability::SpellAbility;
7use crate::trigger::TriggerType;
8
9use super::trigger::TriggerBehavior;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct TriggerDiscarded {
13    pub valid_card: Option<crate::parsing::CompiledSelector>,
14    pub valid_player: Option<crate::parsing::CompiledSelector>,
15    pub valid_cause: Option<crate::parsing::CompiledSelector>,
16}
17
18impl TriggerDiscarded {
19    pub fn parse(params: &Params) -> Box<dyn TriggerBehavior> {
20        Box::new(Self {
21            valid_card: params.selector_cloned(keys::VALID_CARD),
22            valid_player: params.selector_cloned(keys::VALID_PLAYER),
23            valid_cause: params.selector_cloned(keys::VALID_CAUSE),
24        })
25    }
26}
27
28#[typetag::serde]
29impl TriggerBehavior for TriggerDiscarded {
30    fn trigger_type(&self) -> TriggerType {
31        TriggerType::Discarded
32    }
33
34    fn perform_test(
35        &self,
36        trigger: &super::trigger::Trigger,
37        params: &RunParams,
38        game: &GameState,
39    ) -> bool {
40        if !trigger.matches_optional_valid_card_filter(&self.valid_card, params.card, game) {
41            return false;
42        }
43        if !trigger.matches_optional_valid_player_filter(&self.valid_player, params.player, game) {
44            return false;
45        }
46        if let Some(filter) = self.valid_cause.as_ref() {
47            let Some(cause_sa) = params.cause.as_ref() else {
48                return false;
49            };
50            let Some(cause_card) = cause_sa.source else {
51                return false;
52            };
53            if !trigger.matches_valid_card_filter(filter, cause_card, game) {
54                return false;
55            }
56        }
57        true
58    }
59
60    fn set_triggering_objects(
61        &self,
62        _trigger: &super::trigger::Trigger,
63        sa: &mut SpellAbility,
64        params: &RunParams,
65        _game: &GameState,
66    ) {
67        // Java: sa.setTriggeringObjectsFrom(runParams, AbilityKey.Card, AbilityKey.Cause);
68        if let Some(card) = params.card {
69            sa.set_triggering_object(crate::ability::AbilityKey::Card, card.0.to_string());
70        }
71        // TODO: AbilityKey.Cause is a SpellAbility in Java, cannot be stored as String easily
72    }
73
74    fn get_important_stack_objects(
75        &self,
76        _trigger: &super::trigger::Trigger,
77        sa: &SpellAbility,
78    ) -> String {
79        // Java: "Discarded: " + Card + ", Cause: " + Cause
80        format!(
81            "Discarded: {}, Cause: {}",
82            sa.get_triggering_object(crate::ability::AbilityKey::Card)
83                .unwrap_or_default(),
84            sa.get_triggering_object(crate::ability::AbilityKey::Cause)
85                .unwrap_or_default()
86        )
87    }
88}