manabrew_engine/trigger/
trigger_counter_added_once.rs1use 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 ¶ms.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}