ludic/packages/ludic.effects
2026-09-28 20:13:59 +03:00
..
tests fix(leaks): effects_live_into / effects_live_count and hints_rail_into - a HUD's read-outs into lists it keeps 2026-09-28 01:21:53 +03:00
index.ludic refactor(packages): the mechanic packages use ludic_base only, and ask through ports 2026-09-25 05:36:11 +03:00
package.ludic feat(ludic.effects): timed modifiers as a mechanic package; ludic.base's q_new is queue_new 2026-09-25 04:14:09 +03:00
queries.ludic fix(allocs): ludic.update, steps, effects and telemetry at 0 frame allocs and 0 keeps 2026-09-28 20:13:06 +03:00
README.md feat(ludic.effects): timed modifiers as a mechanic package; ludic.base's q_new is queue_new 2026-09-25 04:14:09 +03:00
state.ludic refactor(packages): 0.R5 - a question no longer starts its state - 64 lazy starts ('if st.x == null { st.x = ... }' inside a getter) are the state's defaults, gear__ensure is gone, and ludic migrate state --tighten took mut off 208 package parameters: things_all, thing_find, gear_charge, gear_level, jobs_state and the rest read 2026-09-27 00:51:03 +03:00
system.ludic refactor(packages): 0.R5 - a question no longer starts its state - 64 lazy starts ('if st.x == null { st.x = ... }' inside a getter) are the state's defaults, gear__ensure is gone, and ludic migrate state --tighten took mut off 208 package parameters: things_all, thing_find, gear_charge, gear_level, jobs_state and the rest read 2026-09-27 00:51:03 +03:00
verbs.ludic Merge branch 'lang/memory-burn3' into lang/foundations 2026-09-28 20:13:59 +03:00

ludic.effects

Timed modifiers that run down in game time: a meal that holds the cold off for fifty minutes, a drink that is twenty minutes of legs and then a crash, a soaking that chills you for ten. The rules of the game ask one question - "what should I add for this kind right now?" - and the package answers it. Uses ludic.base and nothing else.

import "ludic.effects"

A kind is the game's own number (EF_WARMTH_RATE, EF_CARRY, ...); the package never knows what one means. A magnitude is in that kind's units. Time is game minutes.

Rules

  • The same kind from the same label replaces itself. A second soda extends the fizz, it does not double it.
  • Bonuses are capped (effects_config(max, bonus_max), 8 and 3 by default): a bonus that would be one too many pushes out the bonus nearest its end. A menu is a choice.
  • A full ring drops whatever is nearest its end.
  • A delayed effect (effects_add_after) counts for nothing until it begins, then runs its time.

API

effects_add(kind, mag, minutes, bonus, label) start one now
effects_add_after(after, kind, mag, minutes, bonus, label) start one after game minutes from now
effects_clear() stop everything, silently (a new trip, a night's sleep)
effects_run(minutes) run them down (the system's tick does this from Tick.hours)
effects_sum(kind), effects_has(kind), effects_bonus_count() what the rules ask
effects_count(), effects_at(i) -> Effect, effects_live() -> []int what a read-out draws (effects_at is a copy)
effects_config(max, bonus_max), effects_capacity(), effects_bonus_capacity() the ring's size
effects_ended() -> Queue<EffectEnded> the facts: { kind, label, why, bonus }, why one of EFFECT_RAN_OUT, EFFECT_PUSHED_OUT, EFFECT_CROWDED_OUT
effects_system() -> System "effects", PH_SIMULATE: reset, tick, and its save section (effects_save, effects_load)

No ports: the package asks the world nothing.

Tests

ludic build packages/ludic.effects/tests/effects_test.ludic --headless -o /tmp/effects_test && /tmp/effects_test