manabrew_engine/trigger/
trigger_taps.rs1use 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::{Trigger, TriggerBehavior};
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct TriggerTaps {
13 pub valid_card: Option<crate::parsing::CompiledSelector>,
14 pub valid_cause: Option<crate::parsing::CompiledSelector>,
15 pub valid_player: Option<crate::parsing::CompiledSelector>,
16 pub attacker: Option<bool>,
17 pub require_first_time: bool,
18}
19
20impl TriggerTaps {
21 pub fn parse(params: &Params) -> Box<dyn TriggerBehavior> {
22 Box::new(Self {
23 valid_card: params.selector_cloned(keys::VALID_CARD),
24 valid_cause: params.selector_cloned(keys::VALID_CAUSE),
25 valid_player: params.selector_cloned(keys::VALID_PLAYER),
26 attacker: params
27 .get(keys::ATTACKER)
28 .map(|v| v.eq_ignore_ascii_case("true")),
29 require_first_time: params.has("FirstTime"),
30 })
31 }
32}
33
34#[typetag::serde]
35impl TriggerBehavior for TriggerTaps {
36 fn trigger_type(&self) -> TriggerType {
37 TriggerType::Taps
38 }
39
40 fn perform_test(&self, trigger: &Trigger, params: &RunParams, game: &GameState) -> bool {
41 if !trigger.matches_optional_valid_card_filter(&self.valid_card, params.card, game) {
42 return false;
43 }
44 if let Some(filter) = self.valid_cause.as_ref() {
45 let Some(cause_sa) = params.cause.as_ref() else {
46 return false;
47 };
48 let Some(cause_card) = cause_sa.source else {
49 return false;
50 };
51 if !trigger.matches_valid_card_filter(filter, cause_card, game) {
52 return false;
53 }
54 }
55 if !trigger.matches_optional_valid_player_filter(&self.valid_player, params.player, game) {
56 return false;
57 }
58 if let Some(expected_attacker) = self.attacker {
59 if params.attacker.is_some() != expected_attacker {
60 return false;
61 }
62 }
63 if self.require_first_time && params.first_time != Some(true) {
64 return false;
65 }
66 true
67 }
68
69 fn set_triggering_objects(
70 &self,
71 _trigger: &Trigger,
72 sa: &mut SpellAbility,
73 params: &RunParams,
74 _game: &GameState,
75 ) {
76 if let Some(card) = params.card {
77 sa.set_triggering_object(crate::ability::AbilityKey::Card, card.0.to_string());
78 }
79 }
80
81 fn get_important_stack_objects(&self, _trigger: &Trigger, sa: &SpellAbility) -> String {
82 format!(
83 "Tapped: {}",
84 sa.trigger_objects
85 .get(&crate::ability::AbilityKey::Card)
86 .map(|s| s.as_str())
87 .unwrap_or("")
88 )
89 }
90}