A downloadable tool

Buy Now$14.99 USD or more

Buy a status-effect icon pack and you get 200 PNGs and no system. Buy a buff/debuff framework and you get stacking rules and no art. Then you discover the third problem: you wanted your poison to look worse as it got worse, and that is four more drawings per ailment, times every ailment in your game.

Affliction is both halves, and the second half is the one nobody sells. Application, stacking, duration, refresh, resistance, immunity, cleanse, damage-over-time and interaction chains — and every affliction generates its own icon, its HUD chip and its on-sprite overlay from its own definition. There is no sprites/ directory in this package, because there is nothing to put in one.

An icon is a pure function of the affliction

icon(affliction) = MARK × FRAME × SEVERITY × TINT

Same affliction in, same icon out — every frame, on every machine. Nothing is random at draw time; the only randomness is a seeded hash of the affliction's own identity, so two afflictions that differ in any property look different and the same one never flickers between looks.

40 hand-authored marks, in six families

7burn — ember, pyre, scorch, cinder, wildfire, smoulder, immolate
6chill — rime, frostbite, glaciate, numb, hailmark, deep freeze
7toxin — venom, blight, corrode, nausea, plague, necrosis, spore
6shock — static, stun, overload, arc, paralyse, magnetise
7mind — fear, charm, confuse, sleep, silence, despair, berserk
7body — bleed, fracture, weaken, slow, root, petrify, wither

Each family has its own frame silhouette, so a player learns six shapes once and every affliction you author afterwards is already legible. The frame is overridable, so any mark can wear any surround. Multiplied out: 40 marks × 6 frames × 4 severities = 960 distinct icons, before the ten tints.

The self-test asserts every one of those numbers on every run, derived from the id arrays rather than typed — so this page cannot drift away from the product.

The severity ramp is the part an icon pack cannot have

Four severities — minor, major, severe, terminal — and they are generated from the same mark, not drawn four times. Clean, then cracked, then weeping, then consuming, where the mark outgrows its own frame. A stack that intensifies raises the severity, so the icon degrades with no extra art from you.

Eight fields that draw on the character, not on the HUD

A chip is what a player glances at. The overlay is what is on screen for the whole duration, on the character they are already looking at. Rime creeps inward off the outline, embers rise, shimmer bands the body, crust climbs from the feet, drips run and gather, sparks jump between extremities, a veil closes in, hairline fractures spread.

All eight are driven by remaining duration, so an affliction visibly weakens instead of vanishing on its last tick — and all eight take an optional silhouette ring, so if you have your character's real outline, pass it and every field keys off your shape instead of the built-in torso proxy.

Colour is computed, not picked

Tints are built in Oklch, a perceptual colour space, so a hue rotation stays legible instead of turning muddy at the dark end and neon at the light one. Ten damage types ship, and a bounded hue tie-breaker keeps two afflictions that share a damage type distinguishable at 24px — seven different poisons stay seven different icons.

And the system underneath it works on its own

afl_state draws nothing, imports nothing from the corpus, and never asks whether a motif is real. If you already have art you like, take the system and leave the icons.

  • Three stacking modes. Independent — every application keeps its own clock, so five poisons expire at five different times. Refresh — one instance, re-applying resets the clock, and a short re-application never shortens a long one. Intensify — stacks raise the severity.
  • Damage over time resolved by accumulator, not by a modulo on a frame counter — at a delta that does not divide the interval, a modulo silently skips ticks, and the bug only shows up on a machine with a different frame rate than yours.
  • Resistance takes the strongest tag, never the product of two, so stacking two 50% resists does not accidentally make you immune. Immunity refuses outright, and every refusal is reported — "nothing happened" and "the input was dropped" are indistinguishable to a player unless the HUD says which.
  • Cleanse by authored priority, not by recency. A recency rule is trivially exploited by applying a harmless debuff first.
  • Ten authored interaction chains — wet+shock conducts, oil+fire immolates, chill+fracture shatters, poison+bleed turns septic. Authored, never a combinatorial matrix of 45 meaningless pairs.
  • Time is your unit. Frames, seconds or turns — the product does not know or care which, so a turn-based game does not have to fight it.
  • Events are returned, never dispatched through a callback, so a damage handler that kills the entity cannot mutate the list being iterated.

Built to be read, and to be fast

  • Pure GML. No native extension, no DLL, no shader — nothing to break on a runtime update and nothing that constrains your target platforms.
  • One file talks to the GPU. afl_render turns geometry into draw calls and knows nothing about afflictions; everything above it produces geometry and makes no engine calls at all. The half that can be wrong is the half you can read.
  • The chip is a drawer, not a HUD. It puts one chip where you ask and returns its width. Your layout stays yours.
  • No font dependency in the runtime path. Even the chip's stack numerals past 5 are ten stroked digits rather than a draw_text call, so nothing you ship depends on shipping our font.
  • Namespaced afl_ / AFL_ throughout, because GML's global namespace is flat and a collision in your project is a support ticket nobody can debug remotely.
  • No absolute paths, no hardcoded room or layer indices, and a documented header block on every public script.

1,717 assertions, run inside the engine

GML cannot be unit-tested outside GameMaker, so this package ships its own suite and runs it inside a real build — press F1 in the demo room, or run the executable with -selftest. It checks counts, geometry bounds, determinism, severity monotonicity, the stacking and resistance rules, and that every overlay field respects the silhouette it is handed.

What that does not prove: it cannot tell you a picture looks good. For that, run the demo room and look at it — which is why the demo room ships.

Compatibility

GameMaker 2024.14 and later. Built and package-verified against runtime 2024.14.4.268. Pure GML with no extensions, so it is not tied to a platform — it draws with the same primitives everywhere GameMaker draws. It adds no objects to your game except the optional demo, touches no global state outside its own AFL_ namespace, and imports as a standard local package alongside anything else you already have.

Install, in two minutes

  1. Tools → Import Local Package, choose Affliction.yymps, Add All.
  2. Open rm_affliction_demo and press Run.
// Define once
afl_define("burning", {
    motif: "ember", tint: "fire", stacking: "intensify",
    dot: { amount: 4, interval: 1.0, tag: "fire" },
    tags: ["fire", "dot"]
});
// A carrier is any struct you want to put afflictions on
var _c = afl_carrier();
afl_resist(_c, "fire", 0.5);
afl_apply(_c, "burning", { duration: 8, stacks: 3 });
// Tick in YOUR unit - frames, seconds or turns
var _events = afl_tick(_c, delta_time / 1000000);
// Draw one chip wherever you want it; it returns its own width
var _w = afl_chip_draw(afl_get(_c, "burning"), x, y, 48, 0.25);

There is nothing to configure, no texture group to set up and no sprite to import.

Built the same way as

  • Grimoire — a spell system that draws its own seals. 8,064 of them, from the spell's own school, tier, element and band.
  • Facet — a card framework that draws its own faces. Deck logic plus the deck.
  • Meridian — procedural skill trees, with 480 node marks generated from 60 authored motifs.

Same principle in all four: the package generates the art, so there is no sprite sheet to commission and nothing to redraw when you add a fortieth affliction.


Every image on this page was rendered by the product itself, headless, from the shipped GML — not by a preview tool and not by hand.

Raw, readable source. Full licence to use in commercial games. Built by Core Systems Asset Factory.

Purchase

Buy Now$14.99 USD or more

In order to download this tool you must purchase it at or above the minimum price of $14.99 USD. You will get access to the following files:

Affliction_GameMaker.zip 680 kB

Leave a comment

Log in with itch.io to leave a comment.