manabrew_engine/ability/effects/
change_combatants_effect.rs1use forge_foundation::ZoneType;
7
8use super::EffectContext;
9use crate::ability::api_type::ApiType;
10use crate::parsing::keys;
11
12#[manabrew_engine_macros::spell_effect(ChangeCombatantsEffect)]
16fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
17 let targets: Vec<crate::ids::CardId> = if sa.uses_targeting() {
18 sa.target_chosen.target_card.into_iter().collect()
19 } else {
20 sa.source.into_iter().collect()
21 };
22
23 for card_id in targets {
24 if ctx.game.card(card_id).zone != ZoneType::Battlefield {
25 continue;
26 }
27 if sa.ir.optional_present {
28 let card_name = ctx.game.card(card_id).card_name.clone();
29 let accepted = ctx.agents[sa.activating_player.index()].confirm_action(
30 sa.activating_player,
31 Some("ChangeCombatants"),
32 &format!("Reselect the defender of {card_name}?"),
33 &[],
34 Some(card_id),
35 Some(ApiType::ChangeCombatants),
36 );
37 if !accepted {
38 continue;
39 }
40 }
41
42 let original_defender = ctx
43 .combat
44 .as_deref()
45 .and_then(|combat| {
46 combat
47 .attackers
48 .iter()
49 .find(|(attacker, _)| *attacker == card_id)
50 })
51 .map(|(_, defender)| *defender);
52
53 if sa.param_is_true(keys::REMOVE_FROM_COMBAT) {
54 if let Some(combat) = ctx.combat.as_deref_mut() {
55 combat.remove_from_combat(card_id, ctx.game);
56 } else {
57 ctx.game.card_mut(card_id).clear_attacking_player();
58 }
59 }
60 if super::add_to_combat(ctx, sa, card_id, keys::ATTACKING) {
61 let new_defender_player = ctx
62 .combat
63 .as_deref()
64 .and_then(|combat| {
65 combat
66 .attackers
67 .iter()
68 .find(|(attacker, _)| *attacker == card_id)
69 })
70 .map(|(_, defender)| defender.controlling_player(ctx.game));
71
72 for entry in ctx.game.stack.iter_mut() {
73 if !entry.spell_ability.is_trigger {
74 continue;
75 }
76 if entry.spell_ability.source != Some(card_id) {
77 continue;
78 }
79 if !entry
80 .spell_ability
81 .trigger_objects
82 .contains_key(&crate::ability::AbilityKey::Attacker)
83 {
84 continue;
85 }
86
87 if let Some(original) = original_defender {
88 match original {
89 crate::combat::DefenderId::Player(pid) => {
90 entry.set_triggering_object(
91 crate::ability::AbilityKey::OriginalDefender,
92 &pid.0.to_string(),
93 );
94 }
95 crate::combat::DefenderId::Permanent(cid) => {
96 entry.set_triggering_object(
97 crate::ability::AbilityKey::OriginalDefender,
98 &cid.0.to_string(),
99 );
100 }
101 }
102 }
103 if let Some(defending_player) = new_defender_player {
104 entry.update_triggering_object(
105 "DefendingPlayer",
106 &defending_player.0.to_string(),
107 );
108 }
109 }
110 }
111 }
112}