Cards become JSON data in course/cards (one file per card, validated against card.schema.json and the catalog); the M5 references load them via registerCards and interpret effects, replacing content closures. Adds assemble(base, donor, half), the assemble/buffHand effects with an injected chooser, Fleshshape as the data-only Expansion Drop, and stages course/cards in verify-references and start-module. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
2.1 KiB
Rust
54 lines
2.1 KiB
Rust
//! Auras, and the one routine that applies trigger multipliers.
|
|
//!
|
|
//! An aura is data on a card: a continuous effect its minion has while in play.
|
|
//! The engine never asks "is that card on the board?" in the middle of resolving
|
|
//! something. It takes a snapshot of the auras in force at defined points (an Aura
|
|
//! Update) and every rule reads the snapshot.
|
|
//!
|
|
//! Hearthstone runs two kinds of Aura Update when the outermost Phase ends: one for
|
|
//! Health/Attack auras before the Death Creation Step, and one for every other aura
|
|
//! after it. Trigger multipliers are "Other" auras, so a minion that dies in a Death
|
|
//! Creation Step no longer multiplies the Deathrattles of that step's Death Phase.
|
|
//! Summoning a minion also runs an Aura Update.
|
|
|
|
use super::card::{Aura, Stacking, TriggerOn};
|
|
use super::world::{ActiveAura, PlayerId, World};
|
|
|
|
/// Aura Update (Other): replace the snapshot with the auras of every minion now in play.
|
|
pub fn aura_update_other(world: &mut World) {
|
|
let mut active = Vec::new();
|
|
for id in world.minions_in_play() {
|
|
for &aura in &world.card(world.card_name(id)).auras {
|
|
active.push(ActiveAura {
|
|
owner: world.owner_of(id),
|
|
aura,
|
|
});
|
|
}
|
|
}
|
|
world.set_active_auras(active);
|
|
}
|
|
|
|
/// How many times a trigger listening for `on`, on a minion `owner` controls, activates
|
|
/// when it resolves. Reads the snapshot from the last Aura Update. With no multiplier in
|
|
/// force the answer is 1. Multipliers with `Stacking::Max` contribute their largest
|
|
/// `times`; each `Stacking::Additive` one adds `times - 1` extra activations.
|
|
pub fn activations(world: &World, owner: PlayerId, on: TriggerOn) -> u32 {
|
|
let mut max = 1;
|
|
let mut extra = 0;
|
|
for active in world.active_auras() {
|
|
let Aura::TriggerMultiplier {
|
|
trigger,
|
|
times,
|
|
stacking,
|
|
} = active.aura;
|
|
if active.owner != owner || trigger != on {
|
|
continue;
|
|
}
|
|
match stacking {
|
|
Stacking::Max => max = max.max(times),
|
|
Stacking::Additive => extra += times - 1,
|
|
}
|
|
}
|
|
max + extra
|
|
}
|