Sacking and Rebuilding Phandalin May 12, 2021
Phandalin is a common setting for 5E. Here are nine maps for the sacking and rebuilding of Phandalin
Sacking and Rebuilding Phandalin May 12, 2021
Phandalin is a common setting for 5E. Here are nine maps for the sacking and rebuilding of Phandalin
No More Initiative February 08, 2021
No More Initiative is an extension for Fantasy Grounds that speeds up combat.
Critmas 2020 December 25, 2020
2020 was the year that we all learned to play D&D over the Internet. Here is a sketch of my awesome players.
Stealth Variant Rules August 01, 2020
Variant rules for running stealth missions in D&D faster and more engaging.
IonCreation January 01, 1992
A platformer game written using Microsoft QuickBasic 4.5 for MS-DOS. Play it in your browser!
Dungeons and Dragons uses a system called initiative to determine turn order. Players roll dice at the start of combat to determine the turn order, after which it is fixed. This extension lets you run Fantasy Grounds and Fantasy Grounds Unity games with no initiative.
The extension creates a note that the DM can optionally share by checking the "Public" option. When die rolls are made, they are added to the list, which is kept sorted. It also displays whether the roll was sucessful or not for 5E.
Place it in your FG or FGU data/extensions
folder.
That's it! *
* there is one issue, which is that you still need to forward through the turns to trigger any "at the start of your turn" type events.
No initiative? What? Are you crazy?
No initiative might sound crazy, but my players straight out prefer it. Try it out, you might like it. The idea is that when you roll dice it actually includes an intrinsic sense of initiave. I originally came across this idea from this video:
There are several edge cases that can arise from a no initiative system. You can solve them however you want, but here are some ways that I deal with them:
I allow players to move before they do their action if they want. If a player specifically wants to move after they've done something then they just tell me. Unless there is a good reason not to allow it, I allow it. If there is ever any doubt, I ask them to do a contest check, such as an athletics contest against an enemy that's trying to cut them off. You can also just have them throw a d20 to see if they can get there in time.
If a player runs up to an opponent and the opponent runs away at the same time, no opportunity attack is triggered. If they start the round next to each other, then it is triggered. It should be intuitive when an opportunity attack is appropriate, but if you're running into issues, you can separate the movement and actions into separate phases. Movement first, actions second.
If a player's target is taken down before it gets to their action, I allow them to instead strike a similar target. For melee, it needs to be adjacent to them. For ranged it needs to be in the same general vicinity.
If you don't like that, another option is to allow them to roll at disadvantage for a replacement action. The disadvantage represents that they were intending to do something and had to hastily switch.
This extension makes it easy to do. At first I was trying to read back through the log and I don't recommend that, too easy to miss actions or get the order wrong.
The extension passes die rolls to the host through out of bounds (OOB) messages. The host then parses them into:
nValue
: the roll totalnHit
: whether it hit or missedsSource
: the legible name of the actor doing the actionsTarget
: the legible name of the actor being targetedsActivity
: the legible name of the weapon or spellThe host then adds those values to a table, which is sorted by nValue
. It uses this table
to generate the tracker note with formatting, such as bold and italics.
Spells are interesting because they are done as forced saving throws. In Fantasy Grounds this
is achieved using two different actions: first a "powersave"
action, which then forces the target to
take a "save"
action. We need both of these to figure out a spell.
The "powersave"
action doesn't have the roll but gives us the sSource
field, while the
save
action tells us the roll but doesn't have the sSource
information any more.
Another thing about saves is that they are defensive. Therefore we calculate a proxy value by taking the DC, and adding the DC minus the roll. This anchors the value to the DC number while making a target that rolls low take damage earlier.
nValue = DC + DC - roll
For example, someone that rolls a 2 on a DC 14 has the hit against them recorded as 26:
26 = 14 + 14 - 2
This sytem definitely needs refinement and I'd welcome any input.
I wasn't able to find an appropriate event listener. There is registerResultHandler
,
which tells us about the roll that was made. However, we're missing the source and target
information.
Instead, we intercept the ActionsManager.resolveAction
function from the CORE ruleset. This
is very easy in lua:
function onInit()orig_resolveAction = ActionsManager.resolveActionActionsManager.resolveAction = my_resolveActionendfunction my_resolveAction(rSource, rTarget, rRoll)... -- do our logic here, with access to rSource, rTarget, rRollorig_resolveAction(rSource, rTarget, rRoll);end
While I wanted this extension to be widely useful, I happen to use it for D&D 5E. I tried to make the 5E ruleset optional, but I haven't tested with an actual non-5E game.
In 5E there is advantage and disadvantage. This means you roll two dice and take either the higher or lower of the two. CORE doesn't understand this, so I had to add extra logic to decode the dice result, adapted from the 5E ruleset code:
function getRollTotal(rRoll)local bADV = string.match(rRoll.sDesc, "%[ADV%]");local bDIS = string.match(rRoll.sDesc, "%[DIS%]");if (bADV and not bDIS) or (bDIS and not bADV) thenif #(rRoll.aDice) > 1 thenlocal nDecodeDie;if (bADV and not bDIS) thennDecodeDie = math.max(rRoll.aDice[1].result, rRoll.aDice[2].result);elsenDecodeDie = math.min(rRoll.aDice[1].result, rRoll.aDice[2].result);endreturn nDecodeDie + rRoll.nMod;endendreturn ActionsManager.total(rRoll);end
Spell casting in 5E is done in reverse. Rather than rolling to see how your spell did, the opponent rolls to see if they saved. To figure out if the spell hit, we need to figure out if they made their roll or not, and reverse it.
function getSaveDetermination(nValue, rRoll)if getRollTotal(rRoll) >= rRoll.nTarget then-- actor made their saving throw, therefore action missedreturn HIT_MISS;elsereturn HIT_HIT;endend
The biggest enhancement I would make would be to handle the "on your next turn" type events automatically. For example, regeneration is only applied when the actor's turn starts.
Other ideas:
Lua is a beautifully simple and clean language. It's amazing that SmiteWorks made so much, both CORE and 5E rulesets, entirely with Lua. Fantasy Grounds is a cool system with the database and OOB delivery systems being straight forward and easy to work with.
However, the OOB message system only supports text. I ended up writing my own trivial JSON codec so that I could transfer the logic to the server. It's possible that I missed a built in way to serialize tables.
Documentation would be nice. Also it would be nice if they ruleset was designed to be more reusable. For example, getting the AC or DC would be nice. A logical flow of action processing would be nice, rather than "powersave" hack for example.