View Full Version : Feature Request: Additional Result States
willrune
March 22nd, 2026, 21:02
I looked around on the forums for a more appropriate location for feature requests and did not notice it. I'd like to apologize if I missed it.
Currently, if we need to apply an effect for "success or lower" or "failure or higher" you have to duplicate the effect.
One for "Success" and another for "Fail or Crit Fail"
One for "Fail" and another for "Success or Crit Success"
This works well enough for many spells with a small number of effects, but for multiple effects, multiple variations, or worse, both, doubling everything is visually overwhelming.
Can 2 more result states be added?
"S-" / "SUCCESS, FAIL, or CRIT FAIL"
"F+" / "FAIL, SUCCESS, or CRIT"
to the existing options of:
"-" (never applied)
"CS" / "CRITICAL SUCCESS"
"S" / "SUCCESS"
"F" / "FAILURE"
"CF" / "CRITICAL FAILURE"
"ALL" (always applied)
"S+" / "SUCCESS or CRIT"
"F-" / "FAIL or CRIT FAIL"
MOTIVATION: I'm working on a Kineticist feature with many effects. (https://www.fantasygrounds.com/forums/showthread.php?84738-Kineticist-Actions&p=760732&viewfull=1#post760732)
Trenloe
March 24th, 2026, 05:27
Can you give some example use cases for this please?
MaxAstro
March 25th, 2026, 20:21
One example would be the spell "Overwhelming Memory" from Rival Academies, which has the result "the target is affected by the memory until the beginning of your next turn" on success, fail, and crit fail, with additional effects on fail and crit fail.
This spell in particular would benefit immensely from this change, actually, since there are four different types of memory you can apply, meaning you would need eight separate effect lines just for that if you separated success and fail. With this change you could have one effect for each memory all set to "success or worse", and then just two more effects to handle the fail and crit fail.
willrune
March 27th, 2026, 01:48
For the sake of argument, we can leave out that I am managing 3 effects per variant as I described in the kineticist actions thread. I can't think of many things juggling that.
In the case of what I was working on for Kineticist, Extract Element (https://2e.aonprd.com/Actions.aspx?ID=2127), what remains relevant is "S-" / "SUCCESS, FAIL, or CRIT FAIL". As long as they don't crit succeed, you have something you want to do to them that is not damage.
Extract element will:
IGNORERESIST or IGNOREIMMUNE
penalty to saves and AC (always -1)
Duration (always 5 minutes)
Do damage with a basic Fort save
As long as it isn't a crit success, everything is the same.
In the screenshots, I've only finished with fire, but you can see how repetitive it is getting.
---
currently, I am planning to include the following instructions
*"IGNORERESIST" and "IF (IMMUNE); RESIST" are visible to the GM only to avoid revealing the target's level and whether or not it has an immunity or resistance without an appropriate recall knowledge check. "IGNOREIMMUNE" on its own won't reveal information and remains visible on the source/player.
*INSTRUCTIONS FOR GM : For each damage type:
(1) If the target is immune to that type, update the resistance on the target and remove the IGNORERESIST from the source/player for that damage type; Failure to do this means the source will always deal full damage for this type as they will ignore both immunity and resistance at the same time.
(2) Otherwise, if not immune, you may remove the "IF CUSTOM(IMMUNE: type); RESIST: TARGET_LVL type" effect for this type from the target to remove clutter from the combat tracker or leave it as is because it shouldn't affect anything;
*An effect will be added to the source / player reminding the GM about the above instructions. The effect will automatically remove itself at the end of the source's / player's turn to avoid cluttering the combat tracker. If you get tired of seeing it, set its "Apply to Result State" to "-" (none, meaning it would only appear if it was manually applied)
I also wanted to program the spell to have all the elemental effects be "-" by default with instruction to set the entries corresponding to the gates you have opened to "S-". This is pretty straight forward if they just have to worry about 1 value. When they have to worry about "One is S and another is F-" there is a higher margin for error. Being able to do everything with 3 effects per element instead of 6 effects per element would help reduce clutter and make instructions easier to follow.
Outside Extract Elements, nothing is coming immediately to mind as I've been playing a kineticist for a long time. I can't imagine that it is the only thing that has identical intensity and duration across 3 of the 4 save results. Outside Paizo's first party spell, I can see it being useful for home brew effects as well.
willrune
March 27th, 2026, 01:53
There will also be instructions for "Using Impulse" and "CHARACTER_NAME", but we don't need to worry about that for this thread.
willrune
March 27th, 2026, 02:37
I originally thought only the fire entries would be used in practice, but looks like there is one level 18 creature in a certain AP (which I won't spoil here) which does have immunity to air. Its an AP I hope to play some day, so I immediately stopped looking at the entry!
I'm not aware of anything else applying, even if you search for individual metals (cold iron, silver, mithril, dawnsilver, adamantine, etc.) over the more general "metal".
Trenloe
March 27th, 2026, 18:33
Thanks for the details everyone. I wasn't pushing back on this, I just need to understand the use case/s so that I can code the best solution for the end result. We're in a change freeze at the moment as we work through the next effect functionality. I've made a note to look into this in the near future.
willrune
March 27th, 2026, 23:32
I appreciate the fact that you want to understand. A lot.
As a software engineer, well, I'm not the best, but after 20+ years of it, I like to think that I do alright. Its tough to get other stake holders or even the users themselves to understand that the WHY of it is as important as the WHAT.
You can ignore the rest of this as my brain is in puzzle solving mode where I think out loud.
---
// TypeScript
function shouldApplyEffect_v1(
saveResult: 'cs' | 's' | 'f' | 'cf',
targetResult: 'cs' | 's' | 'f' | 'cf' | '-' | 'all' | 's+' | 'f-' | 's-' | 'f+'
): boolean {
switch(targetResult) {
case '-': { return false; }
case 'all': { return true; }
case 's+': { return saveResult === 's' || saveResult === 'cs'; }
case 's-': { return saveResult === 's' || saveResult === 'f' || saveResult === 'cf'; }
case 'f+': { return saveResult === 'f' || saveResult === 's' || saveResult === 'cs'; }
case 'f-': { return saveResult === 'f' || saveResult === 'cf'; }
default: { return saveResult === targetResult; }
}
}
function shouldApplyEffect_v2(
saveResult: 4 | 3 | 2 | 1,
targetResult: 4 | 3 | 2 | 1 | '-' | 'all' | 's+' | 'f-' | 's-' | 'f+'
): boolean {
// 4 = CRITICAL SUCCESS
// 3 = SUCCESS
// 2 = FAILURE
// 1 = CRITICAL FAILURE
switch(targetResult) {
case '-': { return false; }
case 'all': { return true; }
case 's+': { return saveResult >= 2; }
case 's-': { return saveResult <= 3; }
case 'f+': { return saveResult >= 1; }
case 'f-': { return saveResult <= 1; }
default: { return saveResult === targetResult; }
}
}
The odds of it being this simple? 50/50. This does not account for all the things and I don't know how performant similar code would be in Unity. Thanks again!
willrune
March 28th, 2026, 00:21
Ok, I'm stopping now... promise.
const SAVE_RESULT = {
CRIT_SUCCESS: 45,
SUCCESS: 35,
FAIL: 25,
CRIT_FAIL: 15,
} as const; // think enum
const SAVE_RESULT_TARGET = {
CRIT_SUCCESS: 45,
// --------------
S_MINUS: 36,
SUCCESS: 35,
S_PLUS: 34,
// --------------
F_MINUS: 26,
FAIL: 25,
F_PLUS: 24,
// --------------
CRIT_FAIL: 15,
// --------------
ALL: 1,
NONE: 0,
} as const; // think enum
type SaveResultValue = typeof SAVE_RESULT[keyof typeof SAVE_RESULT];
type SaveResultTargetValue = typeof SAVE_RESULT_TARGET[keyof typeof SAVE_RESULT_TARGET];
const validSaveResults = new Set<SaveResultValue>(Object.values(SAVE_RESULT));
const validSaveResultTargets = new Set<SaveResultTargetValue>(Object.values(SAVE_RESULT_TARGET));
function shouldApplyEffect_v3(
saveResult: SaveResultValue,
targetResult: SaveResultTargetValue
): boolean {
if (
targetResult === SAVE_RESULT_TARGET.NONE ||
!validSaveResults.has(saveResult) ||
!validSaveResultTargets.has(targetResult)
) { return false; }
if (targetResult === SAVE_RESULT_TARGET.ALL) { return true; }
const targetModulus = targetResult % 10;
if (targetModulus === 5) { return saveResult === targetResult; }
if (targetModulus === 6) { return saveResult < targetResult; }
if (targetModulus === 4) { return saveResult > targetResult; }
return false;
}
Powered by vBulletin® Version 4.2.1 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.