pub struct ReplacementEffect {
pub base: Box<TriggerReplacementBase>,
pub event: ReplacementType,
pub layer: ReplacementLayer,
pub ir: ReplacementEffectIr,
pub active_zones: Vec<ZoneType>,
pub suppressed: bool,
}Expand description
A parsed replacement effect from an R$ line in a card script.
Reference: Java ReplacementEffect.java in forge/game/replacement/.
Fields§
§base: Box<TriggerReplacementBase>Shared trait base (host card, sVars, text-changes, map params).
Mirrors Java ReplacementEffect extends TriggerReplacementBase extends CardTraitBase.
Currently default-initialized by the parser; card factory population is
a follow-up parity task so that matches_valid_param picks up
Invert* entries from map_params.
Boxed because CardState holds five inline Option<ReplacementEffect>
fields (loyalty_rep, defense_rep, saga_rep, adventure_rep,
omen_rep) and TriggerReplacementBase → CardTraitBase contains an
Option<CardState>, which would otherwise form an infinite-sized
type. Trigger does not need this because CardState only owns
triggers via Vec (heap indirection already).
event: ReplacementTypeThe event type this effect intercepts.
layer: ReplacementLayerThe CR 616 layer this effect belongs to.
ir: ReplacementEffectIrTyped runtime view of lowered replacement semantics.
active_zones: Vec<ZoneType>Zones where this effect is active. Empty = active everywhere.
Parsed from ActiveZones$ parameter.
TODO(java-parity): collapse into base.valid_host_zones.
suppressed: boolTemporary suppression flag used by effects like commander replacement.
Implementations§
Source§impl ReplacementEffect
impl ReplacementEffect
Sourcepub fn set_host_card(&mut self, host: &Card)
pub fn set_host_card(&mut self, host: &Card)
Attach the host card id on the embedded trait base. Mirrors Java’s
inherited CardTraitBase.setHostCard(host) — called from the
ReplacementEffect constructor (ReplacementEffect.java:107) so
a freshly-constructed effect is always host-bound.
In Rust the parser builds an unbound effect first (parser doesn’t
have a Card handle) and every insertion site
(card_state::add_replacement_effect, keyword grants, factory
helpers) routes through this method to bind the host. After this
call, CardTrait machinery can stop threading explicit host: &Card
args. TriggerReplacementBase::set_host_card also propagates the
host into any cached overriding ability.
Source§impl ReplacementEffect
impl ReplacementEffect
pub fn new( event: ReplacementType, layer: ReplacementLayer, params: Params, active_zones: Vec<ZoneType>, ) -> Self
pub fn replace_with(&self) -> Option<&str>
pub fn has_skip(&self) -> bool
pub fn prevents(&self) -> bool
pub fn matches_phase(&self, phase: PhaseType) -> bool
Sourcepub fn active_in_zone(&self, zone: ZoneType) -> bool
pub fn active_in_zone(&self, zone: ZoneType) -> bool
Returns true if this effect is active while the source card is in zone.
An empty active_zones list means the effect is always active (mirrors
Java zonesCheck() returning true when activeZones is empty).
Sourcepub fn description(&self, host: &Card, game: &GameState) -> String
pub fn description(&self, host: &Card, game: &GameState) -> String
Human-readable description. Mirrors Java ReplacementEffect.getDescription().
- Suppressed or missing
Description$→ empty string. - Applies text-change effects carried on the trait (Glamerdye / Crystal Spray word-swaps).
- Substitutes
CARDNAMEandNICKNAMEwith the host’s name. - Substitutes
EFFECTSOURCEwith the card that created this host viaeffect_source(token makers, emblems, etc.). - For
DamageDonereplacements whose overridingSpellAbilityusesAB$ ReplaceDamage/AB$ ReplaceSplitDamage, appends"Shields remain: N"when theAmount$/VarName$SVar resolves toNumber$<n>. Only fires when the SA is already cached on the base (matches Java’sgetOverridingAbility()notensureAbility()).
Multi-locale translation is UI-layer and intentionally skipped.
Sourcepub fn has_run(&self) -> bool
pub fn has_run(&self) -> bool
Always false. Java’s ReplacementEffect.hasRun is a per-effect flag
used mainly during otherChoices resolution (Java gap #2 here). Our
per-event chain uses ReplacementHandler.has_run instead, and a new
handler is constructed by apply_replacements per event — so stale
run-marks never leak across events. Revisit when otherChoices lands
(a nested choice flow is the only path that needs the per-effect flag).
Sourcepub fn requirements_check(&self, game: &GameState, source: &Card) -> bool
pub fn requirements_check(&self, game: &GameState, source: &Card) -> bool
Check requirements for this replacement effect against the current game state.
Sourcepub fn copy(&self) -> Self
pub fn copy(&self) -> Self
Clone this replacement effect. Since ReplacementEffect derives Clone,
this delegates to self.clone().
Mirrors Java ReplacementEffect.copy().
Sourcepub fn ensure_ability(
&self,
game: &GameState,
host_card: CardId,
activating_player: PlayerId,
) -> Option<SpellAbility>
pub fn ensure_ability( &self, game: &GameState, host_card: CardId, activating_player: PlayerId, ) -> Option<SpellAbility>
Mirrors Java ReplacementEffect.ensureAbility():
- If an overriding
SpellAbilityis already cached on the base, return a clone of it. - Otherwise, if
ReplaceWith$is set, look up the named SVar on the host card, parse it viaAbilityFactory.getAbility()(the Rust equivalent isbuild_spell_ability), and return the built ability.
This variant does NOT cache the built ability (const receiver). Use
ensure_ability_mut to lazily cache on the base, matching Java’s
setOverridingAbility(sa) call inside ensureAbility.
Sourcepub fn ensure_ability_mut(
&mut self,
game: &GameState,
host_card: CardId,
activating_player: PlayerId,
) -> Option<&mut SpellAbility>
pub fn ensure_ability_mut( &mut self, game: &GameState, host_card: CardId, activating_player: PlayerId, ) -> Option<&mut SpellAbility>
Mirrors Java ReplacementEffect.ensureAbility() including the cache
write (Java calls setOverridingAbility(sa) on first build). Returns
a mutable reference to the cached ability so callers can mutate
trigger payloads before resolution.
Sourcepub fn can_replace_etb(&self, source: &Card, affected: &Card) -> bool
pub fn can_replace_etb(&self, source: &Card, affected: &Card) -> bool
Filter for ETB replacement events. Mirrors Java
ReplacementEffect.canReplaceETB(runParams) (L321-345).
Returns false (skip) when the effect targets things OTHER than itself
(ValidCard$ is not Card.Self-prefixed) AND the affected card IS
the host card — i.e. the effect would be replacing its own ETB.
Otherwise returns true.
Not yet ported: Java’s second guard reads AbilityKey.LastStateBattlefield
to also skip when the host wasn’t on the battlefield before this
Moved event. Rust doesn’t snapshot the previous battlefield state for
replacement resolution, so that branch is omitted. Effects whose host
just entered may still slip through in narrow nested ETB scenarios.
Sourcepub fn set_replacing_objects(
&self,
event: &ReplacementEvent,
sa: &mut SpellAbility,
)
pub fn set_replacing_objects( &self, event: &ReplacementEvent, sa: &mut SpellAbility, )
Mirrors Java ReplacementEffect.setReplacingObjects(runParams, sa).
Java’s base method is an empty default overridden by each concrete
subclass (ReplaceMoved, ReplaceDamage, ReplaceAddCounter, …).
Rust has no subclasses; the match on self.event fills the same role
by dispatching per event type inline.
The sub-ability walk is a Rust-ism — Java’s resolver inherits the
triggering/replacing maps from the parent SA automatically, while the
Rust SpellAbility resolver reads directly from each node. Writing
to every node keeps Defined$ ReplacedCard-style lookups working
inside SubAbility$ chains (Rust stores these under
sa.trigger_objects; Java keeps replacingObjects separate).
Scope note: today this only runs on event paths that actually build a
SpellAbility and resolve it through the SA resolver — currently just
replace_moved::execute. Other handlers mutate events inline via
execute_replace_effect_chain and bypass this hook. Migrate those
paths first before adding their cases here.
Sourcepub fn mode_check(&self, event: &ReplacementType) -> bool
pub fn mode_check(&self, event: &ReplacementType) -> bool
Check if this effect’s event type matches the given event.
For AddCounter, also matches Moved events when the effect handles
counter-on-move (i.e. has a CounterMap interaction).
Mirrors Java ReplacementEffect.modeCheck().
Trait Implementations§
Source§impl CardTrait for ReplacementEffect
impl CardTrait for ReplacementEffect
Source§fn base(&self) -> &CardTraitBase
fn base(&self) -> &CardTraitBase
CardTraitBase. Implementors own a
CardTraitBase (directly or transitively) and return a reference.Source§fn resolve_source_player(&self, src_card: &Card) -> PlayerId
fn resolve_source_player(&self, src_card: &Card) -> PlayerId
Valid$ expressions.
Default matches Java’s base behavior (source card’s controller).
Trigger overrides — mirrors this instanceof Trigger in Java
CardTraitBase.matchesValid(Object, String[], Card) at line 214.Source§fn matches_valid(
&self,
target: &MatchValidTarget<'_>,
valids: &[&str],
src_card: Option<&Card>,
) -> bool
fn matches_valid( &self, target: &MatchValidTarget<'_>, valids: &[&str], src_card: Option<&Card>, ) -> bool
matchesValid(Object, String[], Card).fn matches_compiled_valid( &self, target: &MatchValidTarget<'_>, selector: &CompiledSelector, src_card: Option<&Card>, ) -> bool
fn matches_valid_param( &self, param: &str, target: &MatchValidTarget<'_>, src_card: Option<&Card>, ) -> bool
Source§fn matches_valid_card(&self, expr: &str, card: &Card, source: &Card) -> bool
fn matches_valid_card(&self, expr: &str, card: &Card, source: &Card) -> bool
matches_valid for
card targets. Mirrors Java’s matchesValid(Object, String[], Card)
call pattern where valids is often a single comma-separated string
(e.g. "Creature.YouCtrl,Artifact").fn matches_compiled_valid_card( &self, selector: &CompiledSelector, card: &Card, source: &Card, ) -> bool
Source§fn matches_valid_player(
&self,
expr: &str,
player: PlayerId,
source: &Card,
) -> bool
fn matches_valid_player( &self, expr: &str, player: PlayerId, source: &Card, ) -> bool
matches_valid for
player targets.fn matches_compiled_valid_player( &self, selector: &CompiledSelector, player: PlayerId, source: &Card, ) -> bool
Source§impl CardTraitIrOwner for ReplacementEffect
impl CardTraitIrOwner for ReplacementEffect
type Ir = ReplacementEffectIr
fn ir(&self) -> &Self::Ir
fn card_trait_requirements(&self) -> &CardTraitRequirementsIr
fn meets_card_trait_requirements( &self, game: &GameState, source: &Card, svar_source: &dyn HasSVars, ) -> bool
Source§impl Clone for ReplacementEffect
impl Clone for ReplacementEffect
Source§fn clone(&self) -> ReplacementEffect
fn clone(&self) -> ReplacementEffect
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more