Skip to main content

manabrew_engine/ability/effects/
alter_attribute_effect.rs

1//! AlterAttribute — change a creature's attribute (Plotted, Suspected, etc.).
2//! Ported from Java's AlterAttributeEffect: toggles various card attributes
3//! like Plotted, Harnessed, Solved, Suspected, Saddled, Commander.
4
5use forge_foundation::ZoneType;
6
7use super::EffectContext;
8use crate::ability::ability_ir::DefinedRef;
9use crate::event::RunParams;
10use crate::ids::CardId;
11use crate::trigger::TriggerType;
12
13/// Struct form of this effect so it can participate in the
14/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
15/// `AlterAttributeEffect` class extending `SpellAbilityEffect`.
16#[manabrew_engine_macros::spell_effect(AlterAttributeEffect)]
17fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
18    let activate = sa.ir.alter_attribute_activate;
19    let attributes = &sa.ir.alter_attribute_attributes;
20
21    let targets: Vec<CardId> = if let Some(target) = sa.target_chosen.target_card {
22        vec![target]
23    } else if let Some(source) = sa.source {
24        if let Some(def) = sa.defined_ref() {
25            if matches!(def, DefinedRef::SelfCard) {
26                vec![source]
27            } else {
28                ctx.game.card(source).remembered_cards.clone()
29            }
30        } else {
31            vec![source]
32        }
33    } else {
34        return;
35    };
36
37    for card_id in targets {
38        if ctx.game.card(card_id).zone == ZoneType::None {
39            continue;
40        }
41
42        for attr in attributes {
43            match attr.as_str() {
44                "Harnessed" => {
45                    let val = if activate { "True" } else { "False" };
46                    ctx.game.card_mut(card_id).set_s_var("Harnessed", val);
47                }
48                "Plotted" => {
49                    let val = if activate { "True" } else { "False" };
50                    ctx.game.card_mut(card_id).set_s_var("Plotted", val);
51                }
52                "Solve" | "Solved" => {
53                    let val = if activate { "True" } else { "False" };
54                    ctx.game.card_mut(card_id).set_s_var("Solved", val);
55                    if activate {
56                        ctx.trigger_handler.run_trigger(
57                            TriggerType::CaseSolved,
58                            RunParams {
59                                card: Some(card_id),
60                                player: Some(sa.activating_player),
61                                ..Default::default()
62                            },
63                            false,
64                        );
65                    }
66                }
67                "Suspect" | "Suspected" => {
68                    if activate {
69                        // Suspected creatures have menace and can't block
70                        if !ctx.game.card(card_id).keywords.contains_string("Menace") {
71                            ctx.game.card_mut(card_id).add_intrinsic_keyword("Menace");
72                        }
73                        ctx.game.card_mut(card_id).set_s_var("Suspected", "True");
74                    } else {
75                        ctx.game
76                            .card_mut(card_id)
77                            .remove_intrinsic_keyword("Menace");
78                        ctx.game.card_mut(card_id).remove_s_var("Suspected");
79                    }
80                }
81                "Saddle" | "Saddled" => {
82                    let first_time = !ctx.game.card(card_id).has_s_var("SaddledBy");
83                    let val = if activate { "True" } else { "False" };
84                    ctx.game.card_mut(card_id).set_s_var("Saddled", val);
85                    if activate {
86                        if let Some(source) = sa.source {
87                            ctx.game.card_mut(card_id).add_saddled_by_this_turn(source);
88                        }
89                        ctx.trigger_handler.run_trigger(
90                            TriggerType::BecomesSaddled,
91                            RunParams {
92                                card: Some(card_id),
93                                player: Some(sa.activating_player),
94                                first_time: Some(first_time),
95                                ..Default::default()
96                            },
97                            false,
98                        );
99                    }
100                }
101                "Commander" => {
102                    let val = if activate { "True" } else { "False" };
103                    ctx.game.card_mut(card_id).set_s_var("IsCommander", val);
104                }
105                _ => {}
106            }
107
108            if sa.ir.remember_altered {
109                if let Some(source) = sa.source {
110                    ctx.game.card_mut(source).add_remembered_card(card_id);
111                }
112            }
113        }
114    }
115}