manabrew_engine/ability/effects/
unlock_door_effect.rs1use forge_foundation::ZoneType;
6
7use super::EffectContext;
8use crate::event::RunParams;
9use crate::ids::CardId;
10use crate::spellability::SpellAbilityMode;
11use crate::trigger::TriggerType;
12
13fn unlocked_room_count(ctx: &EffectContext, card_id: CardId) -> i32 {
14 let card = ctx.game.card(card_id);
15 if let Some(count) = card
17 .svars
18 .get("UnlockedRoomCount")
19 .and_then(|v| v.parse::<i32>().ok())
20 {
21 return count;
22 }
23 if card.zone == ZoneType::Battlefield && card.type_line.has_subtype("Room") {
29 return 1;
30 }
31 0
32}
33
34#[manabrew_engine_macros::spell_effect(UnlockDoorEffect)]
38fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
39 let targets: Vec<CardId> = if let Some(target) = sa.target_chosen.target_card {
40 vec![target]
41 } else if let Some(source) = sa.source {
42 vec![source]
43 } else {
44 return;
45 };
46
47 let mode = sa.ir.mode.as_ref().unwrap_or(&SpellAbilityMode::ThisDoor);
48
49 for card_id in targets {
50 if ctx.game.card(card_id).zone != ZoneType::Battlefield {
51 continue;
52 }
53
54 let before = unlocked_room_count(ctx, card_id);
55 let mut after = before;
56 let mut unlocked = false;
57 match mode {
58 SpellAbilityMode::ThisDoor => {
59 ctx.game.card_mut(card_id).set_s_var("DoorUnlocked", "True");
60 if before < 2 {
61 after = before + 1;
62 unlocked = true;
63 }
64 }
65 SpellAbilityMode::Unlock => {
66 ctx.game.card_mut(card_id).set_s_var("DoorUnlocked", "True");
67 if before < 2 {
68 after = before + 1;
69 unlocked = true;
70 }
71 }
72 SpellAbilityMode::LockOrUnlock => {
73 let is_locked = ctx
74 .game
75 .card(card_id)
76 .svars
77 .get("DoorUnlocked")
78 .is_none_or(|v| v != "True");
79 if is_locked {
80 ctx.game.card_mut(card_id).set_s_var("DoorUnlocked", "True");
81 if before < 2 {
82 after = before + 1;
83 unlocked = true;
84 }
85 } else {
86 ctx.game.card_mut(card_id).remove_s_var("DoorUnlocked");
87 after = before.saturating_sub(1);
88 }
89 }
90 _ => {}
91 }
92
93 if after != before {
94 ctx.game
95 .card_mut(card_id)
96 .set_s_var("UnlockedRoomCount", after.to_string());
97 }
98
99 if unlocked {
100 ctx.trigger_handler.run_trigger(
101 TriggerType::UnlockDoor,
102 RunParams {
103 card: Some(card_id),
104 player: Some(sa.activating_player),
105 card_state_name: sa.ir.card_state_name.clone(),
106 ..Default::default()
107 },
108 true,
109 );
110 if before < 2 && after >= 2 {
111 let full = ctx.game.card(card_id).full_name.clone();
115 ctx.game.card_mut(card_id).card_name = full;
116
117 ctx.trigger_handler.run_trigger(
118 TriggerType::FullyUnlock,
119 RunParams {
120 card: Some(card_id),
121 player: Some(sa.activating_player),
122 ..Default::default()
123 },
124 true,
125 );
126 }
127 }
128 }
129}