Skip to main content

manabrew_engine/trigger/
trigger_counter_added_once.rs

1use serde::{Deserialize, Serialize};
2
3use crate::event::RunParams;
4use crate::game::GameState;
5use crate::spellability::SpellAbility;
6use crate::trigger::TriggerType;
7
8use super::trigger::TriggerBehavior;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct TriggerCounterAddedOnce {
12    pub valid_card: Option<crate::parsing::CompiledSelector>,
13    pub valid_player: Option<crate::parsing::CompiledSelector>,
14    pub valid_entity: Option<crate::parsing::CompiledSelector>,
15    pub counter_type: Option<String>,
16    pub valid_source: Option<crate::parsing::CompiledSelector>,
17    pub first_time_only: bool,
18}
19
20impl TriggerCounterAddedOnce {
21    pub fn parse(
22        valid_card: Option<crate::parsing::CompiledSelector>,
23        valid_player: Option<crate::parsing::CompiledSelector>,
24        valid_entity: Option<crate::parsing::CompiledSelector>,
25        counter_type: Option<String>,
26        valid_source: Option<crate::parsing::CompiledSelector>,
27        first_time_only: bool,
28    ) -> Box<dyn TriggerBehavior> {
29        Box::new(Self {
30            valid_card,
31            valid_player,
32            valid_entity,
33            counter_type,
34            valid_source,
35            first_time_only,
36        })
37    }
38}
39
40#[typetag::serde]
41impl TriggerBehavior for TriggerCounterAddedOnce {
42    fn trigger_type(&self) -> TriggerType {
43        TriggerType::CounterAddedOnce
44    }
45
46    fn perform_test(
47        &self,
48        trigger: &super::trigger::Trigger,
49        params: &RunParams,
50        game: &GameState,
51    ) -> bool {
52        if !trigger.matches_optional_valid_card_filter(&self.valid_card, params.card, game) {
53            return false;
54        }
55        if let Some(filter) = &self.valid_player {
56            let Some(player) = params.player else {
57                return false;
58            };
59            if !trigger.matches_valid_player_filter(filter, player, game) {
60                return false;
61            }
62        }
63        if let Some(filter) = &self.valid_entity {
64            let matches = params
65                .card
66                .is_some_and(|card| trigger.matches_valid_card_filter(filter, card, game))
67                || params.player.is_some_and(|player| {
68                    trigger.matches_valid_player_filter(filter, player, game)
69                });
70            if !matches {
71                return false;
72            }
73        }
74        if !super::trigger::Trigger::matches_counter_type_filter(
75            &self.counter_type,
76            &params.counter_type,
77        ) {
78            return false;
79        }
80        if let Some(filter) = &self.valid_source {
81            let Some(source) = params.source_player else {
82                return false;
83            };
84            if !trigger.matches_valid_player_filter(filter, source, game) {
85                return false;
86            }
87        }
88        !self.first_time_only || params.first_time == Some(true)
89    }
90
91    fn set_triggering_objects(
92        &self,
93        _trigger: &super::trigger::Trigger,
94        sa: &mut SpellAbility,
95        params: &RunParams,
96        _game: &GameState,
97    ) {
98        if let Some(card) = params.card {
99            sa.set_triggering_object(crate::ability::AbilityKey::Card, card.0.to_string());
100        }
101        if let Some(p) = params.player {
102            sa.set_triggering_object(crate::ability::AbilityKey::Player, p.0.to_string());
103        }
104        if let Some(amount) = params.counter_amount {
105            sa.set_triggering_object(crate::ability::AbilityKey::Amount, amount.to_string());
106        }
107    }
108
109    fn get_important_stack_objects(
110        &self,
111        _trigger: &super::trigger::Trigger,
112        sa: &SpellAbility,
113    ) -> String {
114        let target = sa
115            .trigger_objects
116            .get(&crate::ability::AbilityKey::Card)
117            .or(sa.trigger_objects.get(&crate::ability::AbilityKey::Player));
118        format!(
119            "AddedOnce: {}, Amount: {}",
120            target.cloned().unwrap_or_default(),
121            sa.trigger_objects
122                .get(&crate::ability::AbilityKey::Amount)
123                .cloned()
124                .unwrap_or_default()
125        )
126    }
127}