overlord_event_system/mechanics/
effect_cb.rs

1//! script ports (`behaviors::cast_ability` / `cast_projectile`).
2//!
3//! ones push `add_entity_stat_mod(owner, stat, value)`, which the engine lowers
4//! to `add_entity_attr(owner, "{stat}.mod", value)` → an `EntityIncrAttribute`
5//! those reactions here, keyed by effect **code** (stable across ids):
6//!
7//! | code          | on_apply                                  |
8//! |---------------|-------------------------------------------|
9//! | `empower`     | `add_entity_stat_mod(attack, +5000)`      |
10//! | `war_fury`    | `add_entity_stat_mod(attack, +3000)`      |
11//! | `battle_blessing` | `add_entity_stat_mod(attack, +1500)` + `(armor, +1500)` |
12//! | `weakness`    | `add_entity_stat_mod(attack, -5000)`      |
13//! | `protection`  | `add_entity_stat_mod(received_damage, -5000)` |
14//! | `vulnerability`| `add_entity_stat_mod(received_damage, +5000)` |
15//! | `test_effect` / `stun` / `shield` | `print(...)` — no events |
16//! | (others)      | no `on_apply` at all — no events           |
17//!
18//! `on_change` is only dispatched by `remove_entity_effect` (with
19//! `new_stacks = 0`, `old_stacks = current`). That path is currently reached
20//! from a `behaviors` native script — so the native `on_change` is, in
21//! practice, not exercised today. It is nonetheless ported faithfully below
22//! (rather than left a no-op) so that any future native caller stays
23//!
24//! |---------------|------------------------------------------------------|
25//! | `empower`     | `add_entity_stat_mod(attack, (new-old)*500)`         |
26//! | `weakness`    | `add_entity_stat_mod(attack, (new-old)*-500)`        |
27//! | `vulnerability`| `add_entity_stat_mod(received_damage, (new-old)*500)`|
28//! | `protection`  | `add_entity_stat_mod(received_damage, -5000)` (flat) |
29//! | (others)      | no `on_change` — no events                            |
30//!
31//! If a new effect with an event-producing reaction ships, extend the matches
32//! below.
33
34use essences::entity::Entity;
35
36use crate::mechanics::content_lookups::EffectTpl;
37use crate::mechanics::fight::{EffectCb, FightSink, add_entity_stat_mod};
38
39/// Native effect-callback dispatcher keyed by effect code. Stateless.
40pub struct OverlordEffectCb;
41
42impl EffectCb for OverlordEffectCb {
43    fn on_apply(
44        &mut self,
45        sink: &mut dyn FightSink,
46        effect: &EffectTpl,
47        target: &Entity,
48    ) -> Result<(), anyhow::Error> {
49        match effect.code.as_str() {
50            "empower" => add_entity_stat_mod(sink, target, "attack", 5000),
51            // BAL-033 class buffs. Their magnitudes are authored flat: rank
52            // moves only the damage/heal payload of the ability that applies
53            // them.
54            "war_fury" => add_entity_stat_mod(sink, target, "attack", 3000),
55            "battle_blessing" => {
56                add_entity_stat_mod(sink, target, "attack", 1500)?;
57                add_entity_stat_mod(sink, target, "armor", 1500)
58            }
59            "weakness" => add_entity_stat_mod(sink, target, "attack", -5000),
60            "protection" => add_entity_stat_mod(sink, target, "received_damage", -5000),
61            "vulnerability" => add_entity_stat_mod(sink, target, "received_damage", 5000),
62            _ => Ok(()),
63        }
64    }
65
66    fn on_change(
67        &mut self,
68        sink: &mut dyn FightSink,
69        effect: &EffectTpl,
70        target: &Entity,
71        new_stacks: i64,
72        old_stacks: i64,
73    ) -> Result<(), anyhow::Error> {
74        // keep it in `i64` and pass it straight to `add_entity_stat_mod`
75        let delta = new_stacks - old_stacks;
76        match effect.code.as_str() {
77            "empower" => add_entity_stat_mod(sink, target, "attack", delta * 500),
78            "weakness" => add_entity_stat_mod(sink, target, "attack", delta * -500),
79            "vulnerability" => add_entity_stat_mod(sink, target, "received_damage", delta * 500),
80            // Protection's on_change is a flat `-5000` (it does not use stacks).
81            "protection" => add_entity_stat_mod(sink, target, "received_damage", -5000),
82            _ => Ok(()),
83        }
84    }
85}