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}