manabrew_engine/trigger/
trigger_token_created_once.rs1use serde::{Deserialize, Serialize};
2
3use crate::ability::AbilityKey;
4use crate::event::{AbilityValue, RunParams};
5use crate::game::GameState;
6use crate::parsing::{keys, Params};
7use crate::spellability::SpellAbility;
8use crate::trigger::TriggerType;
9
10use super::trigger::{Trigger, TriggerBehavior};
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct TriggerTokenCreatedOnce {
14 pub valid_card: Option<crate::parsing::CompiledSelector>,
15 pub only_first: Option<crate::parsing::CompiledSelector>,
16}
17
18impl TriggerTokenCreatedOnce {
19 pub fn parse(params: &Params) -> Box<dyn TriggerBehavior> {
20 let valid_card = params.selector_cloned_any(&["ValidToken", keys::VALID_CARD]);
21 let only_first = params.selector_cloned("OnlyFirst");
22 Box::new(Self {
23 valid_card,
24 only_first,
25 })
26 }
27}
28
29#[typetag::serde]
30impl TriggerBehavior for TriggerTokenCreatedOnce {
31 fn trigger_type(&self) -> TriggerType {
32 TriggerType::TokenCreatedOnce
33 }
34
35 fn perform_test(&self, trigger: &Trigger, params: &RunParams, game: &GameState) -> bool {
36 let Some(AbilityValue::Cards(cards)) = params.get_value(AbilityKey::Cards) else {
37 return false;
38 };
39 let any_match = cards.iter().any(|&card_id| {
40 trigger.matches_optional_valid_card_filter(&self.valid_card, Some(card_id), game)
41 });
42 if !any_match {
43 return false;
44 }
45 if let Some(filter) = self.only_first.as_ref() {
46 let Some(AbilityValue::Players(players)) = params.get_value(AbilityKey::FirstTime)
47 else {
48 return false;
49 };
50 if !players
51 .iter()
52 .copied()
53 .any(|pid| trigger.matches_valid_player_filter(filter, pid, game))
54 {
55 return false;
56 }
57 }
58 true
59 }
60
61 fn set_triggering_objects(
62 &self,
63 _trigger: &Trigger,
64 sa: &mut SpellAbility,
65 params: &RunParams,
66 _game: &GameState,
67 ) {
68 if let Some(cards) = params.cards.as_ref() {
70 let csv = cards
71 .iter()
72 .map(|c| c.0.to_string())
73 .collect::<Vec<_>>()
74 .join(",");
75 sa.set_triggering_object(crate::ability::AbilityKey::Cards, &csv);
76 }
77 }
78
79 fn get_important_stack_objects(&self, _trigger: &Trigger, _sa: &SpellAbility) -> String {
80 String::new()
81 }
82}