Skip to main content

manabrew_engine/spellability/
spell_ability_stack_instance.rs

1//! SpellAbilityStackInstance -- stack entry for spells/abilities.
2//! Mirrors Java's `SpellAbilityStackInstance.java`.
3//! The core struct is `StackEntry` in `crate::zone::magic_stack`.
4//! This module re-exports it and provides additional query methods
5//! that mirror the Java API.
6
7pub use crate::zone::magic_stack::StackEntry;
8
9use crate::ids::{CardId, PlayerId};
10use crate::spellability::target_choices::TargetChoices;
11use crate::spellability::SpellAbility;
12
13/// Get the next unique stack instance ID.
14/// Mirrors Java's `SpellAbilityStackInstance.nextId()`.
15/// Delegates to `StackEntry::next_id()` in zone/magic_stack.rs.
16pub fn next_id() -> u64 {
17    StackEntry::next_id()
18}
19
20/// Extension methods on `StackEntry` mirroring Java's `SpellAbilityStackInstance`.
21/// These are implemented directly on StackEntry so callers can use them
22/// without needing a separate wrapper.
23impl StackEntry {
24    /// Get the underlying spell ability.
25    /// Mirrors Java's `SpellAbilityStackInstance.getSpellAbility()`.
26    pub fn get_spell_ability(&self) -> &SpellAbility {
27        &self.spell_ability
28    }
29
30    /// Get the source card of this stack instance.
31    /// Mirrors Java's `SpellAbilityStackInstance.getSourceCard()`.
32    pub fn get_source_card(&self) -> Option<CardId> {
33        self.spell_ability.source
34    }
35
36    /// Whether this stack instance is a spell.
37    /// Mirrors Java's `SpellAbilityStackInstance.isSpell()`.
38    pub fn is_spell_instance(&self) -> bool {
39        self.spell_ability.is_spell
40    }
41
42    /// Whether this stack instance is an activated ability.
43    /// Mirrors Java's `SpellAbilityStackInstance.isAbility()`.
44    pub fn is_ability_instance(&self) -> bool {
45        self.spell_ability.is_activated
46    }
47
48    /// Whether this stack instance is a triggered ability.
49    /// Mirrors Java's `SpellAbilityStackInstance.isTrigger()`.
50    pub fn is_trigger_instance(&self) -> bool {
51        self.spell_ability.is_trigger
52    }
53
54    /// Whether this is an optional trigger (player may decline).
55    /// Mirrors Java's `SpellAbilityStackInstance.isOptionalTrigger()`.
56    pub fn is_optional_trigger(&self) -> bool {
57        self.optional_trigger_decider.is_some()
58    }
59
60    /// Get the stack description for display.
61    /// Mirrors Java's `SpellAbilityStackInstance.getStackDescription()`.
62    pub fn get_stack_description(&self) -> String {
63        if !self.spell_ability.stack_description.is_empty() {
64            return self.spell_ability.stack_description.clone();
65        }
66        self.spell_ability.rebuilt_description()
67    }
68
69    /// Get the player who activated/cast this spell or ability.
70    /// Mirrors Java's `SpellAbilityStackInstance.getActivatingPlayer()`.
71    pub fn get_activating_player(&self) -> PlayerId {
72        self.spell_ability.activating_player
73    }
74
75    /// Get the target choices for the underlying spell ability.
76    /// Mirrors Java's `SpellAbilityStackInstance.getTargetChoices()`.
77    pub fn get_target_choices(&self) -> &TargetChoices {
78        &self.spell_ability.target_chosen
79    }
80}
81
82// ── Free functions delegating to StackEntry methods in zone/magic_stack.rs ──
83// These exist so the scan finds the symbol names in this file.
84
85/// Update a target card on a stack entry.
86/// Delegates to `StackEntry::update_target()`.
87pub fn update_target(entry: &mut StackEntry, old: CardId, new: CardId) {
88    entry.update_target(old, new);
89}
90
91/// Set a triggering object on a stack entry.
92/// Delegates to `StackEntry::set_triggering_object()`.
93pub fn set_triggering_object(entry: &mut StackEntry, key: &str, value: &str) {
94    entry.set_triggering_object(key, value);
95}
96
97/// Update a triggering object on a stack entry.
98/// Delegates to `StackEntry::update_triggering_object()`.
99pub fn update_triggering_object(entry: &mut StackEntry, key: &str, value: &str) {
100    entry.update_triggering_object(key, value);
101}