Skip to main content

Rules

Rules let nexSys change its curing as a fight develops. They can raise a priority when a lock is close, change a setting in a particular situation, or use a class cure. A rule describes what should be true right now. When the situation passes, nexSys puts everything back by itself.

You don't need to write rules to use nexSys: a set of rules ships with it and is always on. The first part of this page describes them. The rest is for players who want to add their own.

Rules that ship with nexSys​

General rules​

RuleWhat it does
aeon-threshold-and-priorityWhile you have aeon: lowers sip and moss thresholds, turns off batching, raises the clotting threshold, and moves asthma, weariness, anorexia, impatience, and paralysis to the front of the curing order.
nonfunctional-legs-paralysisWhen both of your legs are broken, damaged, or mangled, moves paralysis back to priority 25.
paralysis-long-balanceWhile you're off balance or equilibrium for a long time, as reported by the game, moves paralysis back to priority 24. You couldn't act anyway. It returns paralysis to normal just before you recover.
kelp-paralysis-slicknessWith paralysis, asthma, and slickness, and asthma as your only kelp affliction, cures asthma first.
darkshade-lightwallOnce you've had darkshade for 10 seconds with a lightwall in the room, moves darkshade to priority 2.

Class cures​

Rules named automatic-cure.<ability> use class abilities that server-side curing can't: Fitness, Bloodboil, Educe salt, Shrugging, Fling fool, Alleviate, Dragonheal, Dragonflex, and Dwinnu. Each one only acts when your class has the ability. Curing and priorities lists when each one is used.

Opponent class packs​

Some advice only makes sense against particular classes. Those rules live in packs named after the opponent's class:

PackRuleWhat it does
vs.infernal, vs.psion, vs.shaman, vs.waterlordhaemophilia-bleedingWith haemophilia and 200 or more bleeding, cures haemophilia sooner (priority 3), so you can clot before they can use your bleeding.
vs.waterlordlatch-ginseng-over-wearinessWith weariness and two or more of addiction, haemophilia, nausea, and lethargy, eats ginseng before kelp. Latch counts those afflictions (plus heavy bleeding), and at four you can be desiccated. Weariness lets the Water Lord add two at once.

Each rule's id starts with its pack, such as vs.shaman.haemophilia-bleeding. Class packs are currently always on, whoever you're fighting. You can switch a pack off and on yourself:

nexSys.api.rules.disablePack("vs.shaman");
nexSys.api.rules.enablePack("vs.shaman");

Turning a rule off​

Disable any rule by its id, for example nexSys.api.rules.disable("darkshade-lightwall"). This lasts until nexSys next loads, so put it in your SystemLoaded function to make it stick. See Customizing nexSys.

Writing your own rule​

A rule is an object with an id and an evaluate function. nexSys calls evaluate at every prompt with a set of helpers called ctx. Return null when the rule doesn't apply. When it does, return the changes you want:

nexSys.api.rules.add({
id: "my.asthma-before-slickness",
evaluate(ctx) {
if (!ctx.haveAffs(["asthma", "slickness"])) return null;
return { affPriorities: { asthma: 2 } };
},
});

While both afflictions are present, asthma moves to priority 2. When either is cured, the rule returns null and asthma goes back to its normal priority. You never undo a rule's changes yourself.

Rules only last for the current session. Add yours in a SystemLoaded function in nexSys4.userSettings, so they're added every time nexSys loads. Give every rule a unique id. A short prefix of your own, such as my., keeps it clear of nexSys's ids.

What a rule can change​

KeyExampleEffect
affPriorities{ asthma: 2 }Affliction priorities. 0 or 26 ignores an affliction.
defPriorities{ rebounding: 0 }Defence priorities, for every kind of defence.
settings{ batch: false, sipHealthAt: 60 }Server-side curing settings, using the names from the State reference.
cureActions{ fitness: true }Turn on a class cure.

In affPriorities, defPriorities, and cureActions, a value of "RESET" hands that key back to its normal value, even if an earlier rule changed it. settings doesn't support "RESET".

settings also accepts the booleans focusWithGuilt and focusWithFulminated: true allows focus with that affliction, and false prevents it. When your rule stops applying, nexSys restores the session's normal preference.

To switch curing off entirely while a rule applies, return ctx.suspendCuring(). You can pass other changes to it, as in ctx.suspendCuring({ settings: { batch: false } }). Curing comes back when no rule is suspending it and nexSys isn't otherwise paused.

Use priorities 1 to 3

nexSys's recommended priorities start at 4, which leaves 1 to 3 free for rules. Raising an affliction into that range puts it ahead of everything else without disturbing the rest of your order. Remember that a priority ranks cures, not afflictions. See Affliction priorities.

Rules can also return predictions, prioAff, and manualQueue, but avoid them. The game uses those up without telling nexSys, so nexSys can't tell when they're done. Raising a priority does the same job reliably.

What a rule can check​

HelperAnswers
ctx.haveAff(name), ctx.haveAffs([...]), ctx.haveAnAff([...])Do you have this affliction, all of them, or any of them?
ctx.affCount(name)How many stacks of an affliction you have
ctx.affElapsed(name)Milliseconds since you gained (or lost) an affliction
ctx.cureAffCount(cure)How many of your afflictions a cure treats, such as ctx.cureAffCount("kelp")
ctx.canUseCure(name)Whether your class can use a class cure
ctx.getCuringSetting(name)Your configured curing preference, including "focusWithGuilt" and "focusWithFulminated", before any rule overrides
ctx.sortedActiveAffs()Your afflictions, most urgent first
ctx.haveDef(name), ctx.haveDefs([...]), ctx.haveADef([...])Do you have this defence, all of them, or any of them?
ctx.haveBal(name), ctx.haveBals([...]), ctx.haveABal([...])Is this balance available?
ctx.balElapsed(name), ctx.balRemaining(name)Milliseconds since a balance was used, and until it returns
ctx.isBalReported(name)Whether the game reported how long the current balance loss lasts
ctx.bleeding()Your current bleeding
ctx.limbDamage(limb), ctx.limbStage(limb), ctx.isLimbBroken(limb)Limb damage percentage, "healthy", "damaged", or "mangled", and whether an arm or leg is broken
ctx.isClass(name)Whether you're in this class, or in any class of an array, such as ctx.isClass(["Dragon", "Magi"])
ctx.isTarget(name)Whether this is your current target
ctx.roomHasItem(name)Whether an item with exactly this name is in the room
ctx.haveTrackable(name), ctx.trackableElapsed(name), ctx.trackableRemaining(name)Tracked effects, such as snapTrack after you're snapped

Rules only see these helpers, never nexSys's internal state, and they should only answer questions. Don't send commands or change anything from inside evaluate.

getCuringSetting(name) reads the preference saved in nexSys, using the default when none was saved. Temporary overrides and game confirmations do not change what it returns. Unsupported or unset settings return undefined.

Time-based conditions​

Rules run when something happens, usually at a prompt. A condition that depends on how long something has lasted can become true while nothing happens in the game. Tell nexSys when to check again with ctx.recheckIn(ms):

nexSys.api.rules.add({
id: "my.late-darkshade",
evaluate(ctx) {
if (!ctx.haveAff("darkshade")) return null;
const untilThreshold = 8000 - ctx.affElapsed("darkshade");
if (untilThreshold > 0) {
ctx.recheckIn(untilThreshold);
return null;
}
return { affPriorities: { darkshade: 2 } };
},
});
  • Ask every time evaluate runs. A request only lasts until the next run.
  • Work out the delay from the current values, not from something you saved.
  • Make the boundary inclusive: >= for time elapsed, <= for time remaining. A recheck can land exactly on the boundary, and a strict comparison would still say "not yet".

Order and precedence​

Rules run from top to bottom, and when two rules change the same key, the later one wins. nexSys's general rules run first, then the opponent class packs, then the rules you add. So your rules win.

OptionEffect
terminal: trueStop checking further rules while this one applies.
enabled: falseAdd the rule switched off.
pack: "my-pack"Group rules so you can switch them on or off together with enablePack() and disablePack().

To put a rule at a particular position, pass an index: nexSys.api.rules.add(rule, { index: 0 }). To load a whole set of rules as a pack, use nexSys.api.rules.load("my-pack", [ruleA, ruleB]).

Managing rules​

CallDoes
nexSys.api.rules.add(rule, options?)Add a rule. Returns false if the id is taken.
nexSys.api.rules.remove(id)Remove a rule.
nexSys.api.rules.enable(id) / disable(id)Switch a rule on or off.
nexSys.api.rules.enablePack(packId) / disablePack(packId)Switch every rule in a pack on or off.
nexSys.api.rules.load(packId, rules) / unload(packId)Add or remove a pack of rules.
nexSys.api.rules.reorder(ids)Set the full order of rules.
nexSys.api.rules.list()Every rule, with its position, pack, and whether it's active right now.

nexSys.state.rules shows the combined changes from all active rules, and which rule won each one.

Reacting when a rule switches on or off​

Run code when a rule starts or stops applying, keeping your evaluate function free of side effects:

const stop = nexSys.api.rules.bindTransition("my.asthma-before-slickness", {
onActivate(payload) {
nexusclient.display_notice("Asthma first!", "yellow");
},
onDeactivate(payload) {},
});

// Later, to stop listening:
stop();

The same moments are published as the nexsys4.rule.activated.<id> and nexsys4.rule.deactivated.<id> events.