Skip to main content

manabrew_engine/ability/effects/
drain_mana_effect.rs

1use super::{resolve_defined_players, EffectContext};
2use crate::ability::ability_ir::DefinedRef;
3use crate::replacement::replacement_handler::{apply_replacements, ReplacementEvent};
4use crate::replacement::ReplacementResult;
5
6/// Mirrors Java's `DrainManaEffect` for "lose all unspent mana" effects.
7/// Struct form of this effect so it can participate in the
8/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
9/// `DrainManaEffect` class extending `SpellAbilityEffect`.
10#[manabrew_engine_macros::spell_effect(DrainManaEffect)]
11fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
12    let controller = sa.activating_player;
13    let defined = sa
14        .ir
15        .defined
16        .as_ref()
17        .and_then(|defined| defined.refs.first())
18        .unwrap_or(&DefinedRef::You)
19        .as_legacy_str();
20
21    let mut drained_total = 0i32;
22    // Collect drained mana colors for DrainMana transfer
23    let mut drained_mana: Vec<u16> = Vec::new();
24
25    let targets = resolve_defined_players(defined, controller, ctx.game);
26    for pid in &targets {
27        if !ctx.game.player(*pid).is_alive() {
28            continue;
29        }
30        // Run LoseMana replacement effects before draining mana.
31        let mut event = ReplacementEvent::LoseMana { player: *pid };
32        let result = apply_replacements(ctx.game, &mut event);
33        if result == ReplacementResult::Skipped || result == ReplacementResult::Replaced {
34            continue;
35        }
36        let pool = &mut ctx.mana_pools[pid.index()];
37        let amount = pool.total_mana();
38        if amount <= 0 {
39            continue;
40        }
41        // Collect colors before draining (for color-preserving transfer)
42        drained_mana.extend(pool.mana_colors());
43        drained_total += amount;
44
45        // Mana burn: if player has ManaBurn static, lose life equal to drained mana
46        if crate::staticability::static_ability_unspent_mana::has_mana_burn(ctx.game, *pid) {
47            ctx.game.player_lose_life(*pid, amount);
48        }
49
50        pool.reset_pool();
51    }
52
53    if sa.ir.drain_mana && drained_total > 0 {
54        // Preserve original colors (mirrors Java behavior)
55        for &color in &drained_mana {
56            ctx.mana_pools[controller.index()].add_mana(crate::mana::Mana::simple(color));
57        }
58    }
59
60    if sa.ir.remember_drained_mana {
61        if let Some(source_id) = sa.source {
62            ctx.game
63                .card_mut(source_id)
64                .remembered_cmc
65                .push(drained_total);
66        }
67    }
68}