Skip to main content

manabrew_engine/ability/effects/
detain_effect.rs

1use forge_foundation::ZoneType;
2
3use super::{matches_valid_cards_for_sa, EffectContext};
4use crate::ids::CardId;
5
6/// `SP$ Detain` — detain target creature(s). Detained creatures can't attack,
7/// block, or activate abilities until the controller's next turn.
8///
9/// Mirrors Java's `DetainEffect.java`.
10///
11/// # Card script examples
12/// ```text
13/// A:SP$ Detain | ValidTgts$ Creature
14/// A:SP$ Detain | Defined$ Targeted
15/// ```
16/// Struct form of this effect so it can participate in the
17/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
18/// `DetainEffect` class extending `SpellAbilityEffect`.
19#[manabrew_engine_macros::spell_effect(DetainEffect)]
20fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
21    // Targeted mode
22    if let Some(target) = sa.target_chosen.target_card {
23        if ctx.game.card(target).zone == ZoneType::Battlefield {
24            ctx.game.card_mut(target).set_detained(true);
25        }
26        return;
27    }
28
29    // Defined$ mode (e.g. DetainAll pattern)
30    if let Some(valid_filter) = sa.ir.valid_cards_text.as_deref() {
31        let valid_selector = sa.ir.valid_cards_selector.as_ref();
32        let player_ids = ctx.game.player_order.clone();
33        let mut targets: Vec<CardId> = Vec::new();
34        for &pid in &player_ids {
35            let zone_cards = ctx.game.cards_in_zone(ZoneType::Battlefield, pid).to_vec();
36            for cid in zone_cards {
37                if matches_valid_cards_for_sa(
38                    ctx.game,
39                    sa,
40                    ctx.game.card(cid),
41                    valid_selector,
42                    valid_filter,
43                ) {
44                    targets.push(cid);
45                }
46            }
47        }
48        for cid in targets {
49            if ctx.game.card(cid).zone == ZoneType::Battlefield {
50                ctx.game.card_mut(cid).set_detained(true);
51            }
52        }
53        return;
54    }
55
56    // Defined$ Self
57    if let Some(source) = sa.source {
58        if ctx.game.card(source).zone == ZoneType::Battlefield {
59            ctx.game.card_mut(source).set_detained(true);
60        }
61    }
62}