manabrew_engine/ability/effects/
earthbend_effect.rs1use forge_foundation::{CoreType, ZoneType};
6
7use super::EffectContext;
8use crate::ids::CardId;
9use crate::parsing::Params;
10use crate::trigger::handler::DelayedTrigger;
11use crate::trigger::{parse_trigger, TriggerType};
12
13pub fn build_spell_ability(sa: &mut crate::spellability::SpellAbility) {
17 use crate::parsing::Params;
18 use crate::spellability::TargetRestrictions;
19
20 let params = Params::from_raw("ValidTgts$ Land.YouCtrl | TgtPrompt$ land you control");
22 if let Some(tr) = TargetRestrictions::new(¶ms) {
23 sa.target_restrictions = Some(tr);
24 }
25}
26
27#[manabrew_engine_macros::spell_effect(EarthbendEffect)]
31fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
32 let num = super::resolve_numeric_svar(ctx.game, sa, "Num", 1).max(0);
33
34 let targets: Vec<CardId> = if let Some(target) = sa.target_chosen.target_card {
35 vec![target]
36 } else {
37 return;
38 };
39
40 for card_id in targets {
41 if ctx.game.card(card_id).zone != ZoneType::Battlefield {
42 continue;
43 }
44
45 ctx.game
46 .card_mut(card_id)
47 .capture_changed_characteristics_baseline_if_needed();
48
49 ctx.game.card_mut(card_id).set_base_pt(Some(0), Some(0));
51
52 ctx.game
54 .card_mut(card_id)
55 .add_type(CoreType::Creature.name());
56
57 if !ctx
59 .game
60 .card(card_id)
61 .keywords
62 .contains_string_ignore_case("Haste")
63 {
64 ctx.game.card_mut(card_id).add_intrinsic_keyword("Haste");
65 }
66
67 let counter_type = super::parse_counter_type("P1P1");
69 ctx.add_counter(
70 card_id,
71 &counter_type,
72 num,
73 sa,
74 crate::event::RunParams::default(),
75 );
76
77 register_return_trigger(ctx, sa, card_id, ZoneType::Graveyard);
78 register_return_trigger(ctx, sa, card_id, ZoneType::Exile);
79 }
80}
81
82fn register_return_trigger(
83 ctx: &mut EffectContext,
84 sa: &crate::spellability::SpellAbility,
85 card_id: CardId,
86 zone: ZoneType,
87) {
88 let trigger_raw = match zone {
89 ZoneType::Graveyard => {
90 "Mode$ ChangesZone | ValidCard$ Card.IsTriggerRemembered | Origin$ Battlefield | Destination$ Graveyard | TriggerDescription$ When it dies or is exiled, return it to the battlefield tapped."
91 }
92 ZoneType::Exile => {
93 "Mode$ Exiled | Origin$ Battlefield | ValidCard$ Card.IsTriggerRemembered | TriggerZones$ Battlefield | TriggerDescription$ When it dies or is exiled, return it to the battlefield tapped."
94 }
95 _ => return,
96 };
97
98 let mut next_id = 0;
99 let Some(trigger) = parse_trigger(trigger_raw, &mut next_id) else {
100 return;
101 };
102 let source_card = sa.source.unwrap_or(card_id);
103 let origin = match zone {
104 ZoneType::Graveyard => "Graveyard",
105 ZoneType::Exile => "Exile",
106 _ => return,
107 };
108 let execute_svar = format!(
109 "DB$ ChangeZone | Defined$ DelayTriggerRemembered | Origin$ {origin} | Destination$ Battlefield | Tapped$ True | GainControl$ You"
110 );
111
112 ctx.trigger_handler
113 .register_delayed_trigger(DelayedTrigger {
114 mode: match zone {
115 ZoneType::Graveyard => TriggerType::ChangesZone,
116 ZoneType::Exile => TriggerType::Exiled,
117 _ => unreachable!(),
118 },
119 trigger_mode: trigger.mode,
120 params: Params::from_raw(trigger_raw),
121 execute_svar,
122 controller: sa.activating_player,
123 source_card,
124 created_turn: ctx.game.turn.turn_number,
125 created_phase: ctx.game.turn.phase,
126 target_card: Some(card_id),
127 remembered_amount: 0,
128 remembered_cards: vec![card_id],
129 remembered_players: Vec::new(),
130 remembered_lki_cards: Vec::new(),
131 sort_after_active: false,
132 trigger_order: None,
133 });
134}