manabrew_engine/ability/effects/
damage_each_effect.rs1use forge_foundation::ZoneType;
2
3use super::{matches_valid_cards_for_sa, resolve_numeric_svar, EffectContext};
4use crate::card::card_damage_map::DamageTarget;
5use crate::ids::CardId;
6
7#[manabrew_engine_macros::spell_effect(DamageEachEffect)]
22fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
23 let use_damage_map = ctx.game.pending_damage_map.is_some() || sa.ir.damage_map;
24 if sa.ir.damage_map {
25 ctx.game.ensure_pending_damage_maps();
26 }
27
28 let valid_cards = sa.ir.valid_cards_selector.as_ref();
29 let fixed_dmg = sa
30 .ir
31 .num_dmg_present
32 .then(|| {
33 let v = resolve_numeric_svar(ctx.game, sa, "NumDmg", -1);
34 if v == -1 {
35 None
36 } else {
37 Some(v)
38 }
39 })
40 .flatten();
41
42 let player_ids = ctx.game.player_order.clone();
43 let mut damagers: Vec<CardId> = Vec::new();
44
45 for &pid in &player_ids {
46 let zone_cards = ctx.game.cards_in_zone(ZoneType::Battlefield, pid).to_vec();
47 for cid in zone_cards {
48 if matches_valid_cards_for_sa(ctx.game, sa, ctx.game.card(cid), valid_cards, "Creature")
49 {
50 damagers.push(cid);
51 }
52 }
53 }
54
55 let target_player = sa
57 .target_chosen
58 .target_player
59 .unwrap_or_else(|| ctx.game.opponent_of(sa.activating_player));
60
61 for card_id in damagers {
62 if ctx.game.card(card_id).zone != ZoneType::Battlefield {
63 continue;
64 }
65 let dmg = fixed_dmg.unwrap_or_else(|| ctx.game.card(card_id).power().max(0));
66 if dmg <= 0 {
67 continue;
68 }
69
70 if use_damage_map {
71 if let Some(map) = ctx.game.pending_damage_map.as_mut() {
72 map.put(card_id, DamageTarget::Player(target_player), dmg);
73 }
74 } else {
75 let dealt = ctx.game.deal_damage_to_player(target_player, dmg);
77 ctx.game.record_player_damage_assignment(
78 Some(card_id),
79 Some(target_player),
80 dealt,
81 false,
82 );
83
84 ctx.trigger_handler.run_trigger(
85 crate::trigger::TriggerType::DamageDone,
86 crate::event::RunParams {
87 damage_source: Some(card_id),
88 damage_target_player: Some(target_player),
89 damage_amount: Some(dmg),
90 is_combat_damage: Some(false),
91 ..Default::default()
92 },
93 false,
94 );
95 }
96 }
97}