Module laws

Source
Expand description

Laws v0.2 — the combat runtime of condition → effect + Resonance.

A law is no longer a stat block that happens to be side-gated: it watches for one Core occurrence, runs one action, and drops its Resonance into its bridge. This module is the whole of that behaviour; the arithmetic (charge capacity, amplification, upgrade scaling) lives in crate::mechanics::cores and the shapes in essences::cores.

Three entry points, because the three condition families need three different moments:

  • OverlordLogic::apply_law_pre_cast runs from handle_cast_ability BEFORE the cast resolves. RL-01 reads “every 5th Basic Attack: THIS strike deals +100%”, which is only expressible if the law fires before its own strike computes damage.
  • OverlordLogic::apply_law_reactions hangs off apply_success_hooks, so it sees the world an outcome actually produced — crits, dodges, hits taken, kills, HP thresholds, AoE target counts.
  • OverlordLogic::apply_flip_to_laws runs on a completed flip: it delivers the bridge charge, re-folds attributes, and only THEN fires the “phase started” laws (RL-12, FL-11). That order is acceptance #9 — reversed, those two would be the only laws in the catalog a bridge can never reach, since their single fire happens exactly at that moment.

Anti-loop. Every condition is gated on essences::combat_origin::CombatEventOrigin::is_core and every combat outcome a law produces is emitted Proc. FL-09 (“a Core action killed an enemy → 150% Attack to every enemy”) therefore cannot chain on the kills its own blast makes: those arrive on Proc damage, which is not a condition at all. A genuine Basic Attack or original Skill stays Core even when a law changed its magnitude — a law arms an attribute, it never re-emits the action.

All per-fight law state lives in the entity’s attributes, the same idiom the stones runtime uses (stone.*). Keys are namespaced law.* and tagged by side + slot index rather than by law id, so they stay short and are stable for a whole fight. Mid-fight build edits update the durable Core state only; the entity-local snapshot continues driving this fight.

Known edge — the event that crosses the gauge belongs to the INCOMING phase. A producer advances the entity’s own flip_state while it resolves and emits GlobalFlip as a follow-up event, so by the time the law hook runs the outgoing side is already down: the flipping event is evaluated against the incoming side’s laws, and against them at their PRE-delivery amplification. One action per flip is affected. It is not a loop and not a leak (the phase-start laws are still fired exactly once, by the flip handler, after delivery); moving it would mean deferring the side change out of the producers, which is flip machinery rather than law machinery.

There is ONE producer:

  • logic::stones::accumulate_trigger_gauge — a Trigger Stone fire. This one is structural rather than incidental: apply_success_hooks runs the stones hook immediately before the laws hook, so a fire that crosses the gauge always hands the rest of that event to the incoming side. Pinned by test_cores::a_stone_driven_flip_hands_the_same_event_to_the_incoming_sides_laws.

Re-exports§

pub use crate::mechanics::cores::ARM_BASIC;
pub use crate::mechanics::cores::ARM_SKILL;
pub use crate::mechanics::cores::ARM_THIS;

Constants§

ARM_ECHO
Echo armed for the owner’s next original Skill, permyriad of Attack.
ARM_SPLASH
Splash armed for the owner’s next Basic Attack, permyriad of Attack. Spent at that attack’s pre-cast hook against every OTHER living enemy.