Skip to main content

EffectProvider

Trait EffectProvider 

Source
pub trait EffectProvider: BattleProvider + 'static {
    type EffectStateKind: Clone;

    // Required methods
    fn effect_for_move(&self, m: &Self::Move) -> Option<&'static Effect<Self>>
       where Self: Sized;
    fn effect_for_status(
        &self,
        s: &Self::Status,
    ) -> Option<&'static Effect<Self>>
       where Self: Sized;
    fn turn_order_rank(
        &self,
        state: &BattleState<Self>,
        who: BattlerRef,
        action: &<Self as BattleProvider>::Move,
    ) -> (i32, i32)
       where Self: Sized;

    // Provided methods
    fn effect_for_volatile(
        &self,
        kind: &Self::EffectStateKind,
    ) -> Option<&'static Effect<Self>>
       where Self: Sized { ... }
    fn forced_action(
        &self,
        effects: &[EffectState<Self>],
        actor: BattlerRef,
        chosen: &BattleAction<Self>,
    ) -> Option<BattleAction<Self>>
       where Self: Sized { ... }
    fn effect_for_ability(
        &self,
        b: &BattlerState<Self>,
    ) -> Option<&'static Effect<Self>>
       where Self: Sized { ... }
    fn effect_for_item(
        &self,
        b: &BattlerState<Self>,
    ) -> Option<&'static Effect<Self>>
       where Self: Sized { ... }
    fn side_effects(
        &self,
        ctx: &BattleCtx<'_, Self>,
        side: u8,
    ) -> &[&'static Effect<Self>]
       where Self: Sized { ... }
    fn field_effects(
        &self,
        ctx: &BattleCtx<'_, Self>,
    ) -> &[&'static Effect<Self>]
       where Self: Sized { ... }
}
Expand description

The game’s effect registry, extending BattleProvider (design §1.5).

The engine ships the dispatch machinery with zero game-specific types; all specifics (which move maps to which Effect, the volatile state enum) live in the game via this trait. For the POC, EffectStateKind is a concrete game-supplied associated type (design §3.1 — promote to richer generics when a second game lands).

Required Associated Types§

Source

type EffectStateKind: Clone

The game-supplied typed per-effect-kind state enum (design §3.1). The engine treats it opaquely (it only stamps effect_order and routes it to the host). pokered supplies the Gen-1 enum (Toxic counter, Substitute hp, …).

Required Methods§

Source

fn effect_for_move(&self, m: &Self::Move) -> Option<&'static Effect<Self>>
where Self: Sized,

Resolve the Effect registered for a given move. Returns None if the move registers no stack hooks.

Source

fn effect_for_status(&self, s: &Self::Status) -> Option<&'static Effect<Self>>
where Self: Sized,

Resolve the Effect registered for a non-volatile status (e.g. the poison residual). Returns None if the status registers no hooks.

Source

fn turn_order_rank( &self, state: &BattleState<Self>, who: BattlerRef, action: &<Self as BattleProvider>::Move, ) -> (i32, i32)
where Self: Sized,

Turn-order rank for whodrawing NO randomness (design §1.3/§2).

The driver compares the two ranks; on an exact tie it draws one byte to break it (mirroring pokered’s single order_random coin flip, turn_order.rs:41, bug #22) — the only turn-order RNG site. This is why the stack does NOT reuse BattleProvider::turn_order_key (which draws per actor): a per-actor draw would consume the wrong number of bytes and break draw-order parity with the legacy oracle (design §4.1).

Lower rank acts first; encode “acts earlier” as a smaller key (e.g. (-priority, -effective_speed)).

Provided Methods§

Source

fn effect_for_volatile( &self, kind: &Self::EffectStateKind, ) -> Option<&'static Effect<Self>>
where Self: Sized,

Resolve the Effect registered for a live volatile in the effect arena (design §3.4: every live effect on a battler contributes its handlers, not only the non-volatile status). Returns None (the default) when the volatile registers no hooks — so a provider that has no volatile-borne residuals (every game built on the engine so far) is completely unaffected and the driver’s arena-residual pass is inert.

This is the generic seam that lets a game host a residual on a volatile (Gen-1 Leech Seed / badly-poisoned both live in status2/status3 bit flags, NOT the non-volatile status byte) without the engine knowing any game-specific semantics. The /16, the toxic counter, and the ASM “status then leech” order all live in the game’s handlers; the engine only fires the hooks the game registers, in the order the game’s order values dictate.

Source

fn forced_action( &self, effects: &[EffectState<Self>], actor: BattlerRef, chosen: &BattleAction<Self>, ) -> Option<BattleAction<Self>>
where Self: Sized,

Cross-turn action override (design §3 / §9, the multi-turn lock-in seam). Before the driver executes actor’s chosen action, it asks the game whether a live volatile forces a different action this turn — Gen-1 Thrash/Petal Dance and Wrap/Bind re-issue the locked move ignoring the player’s choice, Fly/Dig/Solar Beam strike on the second turn, and Hyper Beam recharge forces inaction (BattleAction::Nothing). The game reads its own effects arena (the cross-turn home of the lock counter / charge flag / recharge flag) and returns Some(forced) to override chosen, or None to let the chosen action stand.

This is the canonical proof (design §9) that a per-turn [Action; 2] input is insufficient: the locked volatile, recorded on a PRIOR turn, hijacks this turn’s action. The seam is generic (the engine names no game-specific volatile — it only swaps one BattleAction for another) and defaulted to None, so it is completely INERT for every other game and for slices 1–5 (which never register a forcing volatile). All Gen-1 lock-in semantics (which volatile forces which move, the lock counter, the recharge skip) live in the game’s forced_action impl, never in the engine.

Source

fn effect_for_ability( &self, b: &BattlerState<Self>, ) -> Option<&'static Effect<Self>>
where Self: Sized,

Resolve the Effect registered for a battler’s ability, hosted on that battler (design §2.4). Returns None (the default) when the game has no abilities or this one registers no stack hooks.

Source

fn effect_for_item( &self, b: &BattlerState<Self>, ) -> Option<&'static Effect<Self>>
where Self: Sized,

Resolve the Effect registered for a battler’s held item, hosted on that battler (design §2.4). Returns None (the default) when the game has no items or this one registers no stack hooks.

Source

fn side_effects( &self, ctx: &BattleCtx<'_, Self>, side: u8, ) -> &[&'static Effect<Self>]
where Self: Sized,

Resolve the side-hosted effects for side (screens, hazards, Wish; design §2.4). Returns &[] (the default) when the game has no side conditions.

The returned slice borrows from self (the provider owns the registry of &'static Effect tables); ctx is passed read-only so a game can decide which side conditions are currently live by consulting its arena/field state. The engine only fetches hook tables — it never reads a side condition’s meaning.

Source

fn field_effects(&self, ctx: &BattleCtx<'_, Self>) -> &[&'static Effect<Self>]
where Self: Sized,

Resolve the field-hosted effects (weather, terrain, Trick Room; design §2.4). Returns &[] (the default) when the game has no field conditions. The returned slice borrows from self (see side_effects).

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§