Skip to main content

manabrew_engine/ability/effects/
make_card_effect.rs

1//! MakeCard — conjure a card with specific properties (digital-only, Arena).
2//! Ported from Java's MakeCardEffect: creates a real card (not a token) from
3//! a named card, spellbook, or choices, and places it in a zone.
4
5use forge_foundation::ZoneType;
6
7use super::EffectContext;
8use crate::ids::CardId;
9use crate::parsing::keys;
10
11/// Struct form of this effect so it can participate in the
12/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
13/// `MakeCardEffect` class extending `SpellAbilityEffect`.
14#[manabrew_engine_macros::spell_effect(MakeCardEffect)]
15fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
16    let source = match sa.source {
17        Some(s) => s,
18        None => return,
19    };
20    let controller = sa.activating_player;
21
22    // Determine target zone
23    let zone = sa.ir.zone.unwrap_or(ZoneType::Library);
24
25    // Get card name(s) to conjure
26    let names: Vec<String> = if let Some(name) = sa.ir.name_text.as_deref() {
27        if name == "ChosenName" {
28            // Use named card from source
29            if let Some(chosen) = ctx.game.card(source).get_s_var("ChosenName") {
30                vec![chosen.to_string()]
31            } else {
32                vec![]
33            }
34        } else {
35            vec![name.to_string()]
36        }
37    } else if let Some(names_str) = sa.ir.names_text.as_deref() {
38        names_str
39            .split(',')
40            .map(|s| s.trim().replace(';', ","))
41            .collect()
42    } else {
43        // Spellbook/Choices — digital-only card generation
44        vec![]
45    };
46
47    let amount = super::resolve_numeric_svar(ctx.game, sa, "Amount", 1).max(1);
48
49    for name in &names {
50        for _ in 0..amount {
51            // Create a minimal card instance representing the conjured card
52            let mut card = crate::card::Card::new(
53                CardId(0),
54                name.clone(),
55                controller,
56                forge_foundation::CardTypeLine::parse(""),
57                forge_foundation::ManaCost::parse(""),
58                forge_foundation::ColorSet::COLORLESS,
59                None,
60                None,
61                vec![],
62                vec![],
63            );
64            card.set_controller(controller);
65
66            if sa.param_is_true(keys::TAPPED) {
67                card.set_tapped(true);
68            }
69            if sa.param_is_true(keys::FACE_DOWN) {
70                card.set_face_down(true);
71            }
72
73            let card_id = ctx.game.create_card(card);
74            let old_zone = ctx.game.card(card_id).zone;
75            ctx.move_card(card_id, zone, controller);
76            super::emit_zone_trigger(ctx.trigger_handler, card_id, old_zone, zone);
77
78            if sa.param_is_true(keys::REMEMBER_MADE) {
79                ctx.game.card_mut(source).add_remembered_card(card_id);
80            }
81            if sa.param_is_true(keys::IMPRINT_MADE) {
82                ctx.game.card_mut(source).add_imprinted_card(card_id);
83            }
84        }
85    }
86
87    // Shuffle library if cards went there without a specific position
88    if zone == ZoneType::Library && sa.library_position().is_none() {
89        ctx.game
90            .shuffle_zone_cards(ZoneType::Library, controller, ctx.rng);
91    }
92}