manabrew_engine/ability/effects/
ring_tempts_you_effect.rs1use forge_foundation::ZoneType;
8
9use super::EffectContext;
10use crate::ability::ability_factory::build_spell_ability;
11use crate::event::RunParams;
12use crate::game::GameState;
13use crate::ids::{CardId, PlayerId};
14use crate::player::player_factory_util::add_static_ability;
15use crate::spellability::SpellAbility;
16use crate::trigger::parse_trigger;
17use crate::trigger::TriggerHandler;
18use crate::trigger::TriggerType;
19
20pub fn run(game: &mut crate::game::GameState, player: crate::ids::PlayerId) {
25 if let Some(bearer_id) = game.player(player).ring_bearer {
28 let bearer = game.card(bearer_id);
29 if bearer.zone != ZoneType::Battlefield || bearer.controller != player {
30 game.player_mut(player).ring_bearer = None;
31 }
32 }
33}
34
35#[manabrew_engine_macros::spell_effect(RingTemptsYouEffect)]
39fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
40 let controller = sa.activating_player;
41 let players = if let Some(def) = sa.defined_player() {
42 super::resolve_defined_players(def, controller, ctx.game)
43 } else {
44 vec![controller]
45 };
46
47 for pid in players {
48 ring_tempts(ctx, sa, pid);
49 }
50}
51
52fn ring_tempts(ctx: &mut EffectContext, _sa: &SpellAbility, player: PlayerId) {
53 crate::player::create_the_ring(ctx.game, player);
54
55 let current_level = ctx.game.player(player).ring_level;
56 if current_level < 4 {
57 ctx.game.player_ring_tempt(player);
58 }
59 sync_ring_effect(ctx.game, ctx.trigger_handler, player);
60
61 let creatures: Vec<CardId> = ctx
62 .game
63 .cards
64 .iter()
65 .filter(|c| {
66 c.zone == ZoneType::Battlefield
67 && c.controller == player
68 && c.type_line
69 .core_types
70 .iter()
71 .any(|ct| matches!(ct, forge_foundation::CoreType::Creature))
72 })
73 .map(|c| c.id)
74 .collect();
75
76 let mut ring_bearer = None;
77 if !creatures.is_empty() {
78 ctx.agents[player.index()].snapshot_state(ctx.game, ctx.mana_pools);
79 if let Some(chosen) = ctx.agents[player.index()].choose_single_card_for_zone_change(
80 ctx.game,
81 player,
82 &creatures,
83 "Choose your Ring-bearer",
84 false,
85 ) {
86 ctx.game.player_set_ring_bearer(player, Some(chosen));
87 ring_bearer = Some(chosen);
88 }
89 }
90
91 ctx.trigger_handler.run_trigger(
92 TriggerType::RingTemptsYou,
93 RunParams {
94 player: Some(player),
95 card: ring_bearer,
96 ..Default::default()
97 },
98 false,
99 );
100}
101
102pub fn sync_ring_effect(
103 game: &mut GameState,
104 trigger_handler: &mut TriggerHandler,
105 player: PlayerId,
106) {
107 if game.player(player).ring_level <= 0 {
108 return;
109 }
110 crate::player::create_the_ring(game, player);
111 let level = game.player(player).ring_level.min(4);
112 for ring_level in 1..=level {
113 set_ring_level(game, trigger_handler, player, ring_level);
114 }
115}
116
117fn set_ring_level(
118 game: &mut GameState,
119 trigger_handler: &mut TriggerHandler,
120 player: PlayerId,
121 level: i32,
122) {
123 let Some(effect_id) = game.player(player).ring_effect_card else {
124 return;
125 };
126
127 let changed = match level {
128 1 => {
129 let effect = game.card_mut(effect_id);
130 if effect.static_abilities.len() >= 2 {
131 false
132 } else {
133 add_static_ability(
134 effect,
135 "Mode$ Continuous | EffectZone$ Command | Affected$ Card.YouCtrl+IsRingbearer | AddType$ Legendary | Description$ Your Ring-bearer is legendary.",
136 ) | add_static_ability(
137 effect,
138 "Mode$ CantBlockBy | EffectZone$ Command | ValidAttacker$ Card.YouCtrl+IsRingbearer | ValidBlockerRelative$ Creature.powerGTX | Description$ Your Ring-bearer can't be blocked by creatures with greater power.",
139 )
140 }
141 }
142 2 => add_ring_attack_trigger(game, effect_id, player),
143 _ => false,
144 };
145
146 if changed {
147 trigger_handler.unregister_active_triggers(effect_id);
148 trigger_handler.register_active_trigger(game, effect_id);
149 }
150}
151
152fn add_ring_attack_trigger(game: &mut GameState, effect_id: CardId, player: PlayerId) -> bool {
153 if game.card(effect_id).triggers.iter().any(|trigger| {
154 trigger
155 .description
156 .contains("Whenever your Ring-bearer attacks")
157 }) {
158 return false;
159 }
160
161 {
162 let effect = game.card_mut(effect_id);
163 effect.set_s_var(
164 "RingAttackDiscard",
165 "DB$ Discard | Defined$ You | NumCards$ 1 | Mode$ TgtChoose",
166 );
167 }
168
169 let Some(mut trigger) = parse_trigger(
170 "Mode$ Attacks | ValidCard$ Card.YouCtrl+IsRingbearer | TriggerDescription$ Whenever your Ring-bearer attacks, draw a card, then discard a card. | TriggerZones$ Command",
171 &mut 0,
172 ) else {
173 return false;
174 };
175
176 let ability = build_spell_ability(
177 game,
178 effect_id,
179 "DB$ Draw | Defined$ You | NumCards$ 1 | SubAbility$ RingAttackDiscard",
180 player,
181 );
182 trigger.bind_host_card_id(effect_id);
183 trigger.set_overriding_ability(ability);
184 game.card_mut(effect_id).add_trigger(trigger)
185}