1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
|
# Features Format
Many features are complex. Here we lay out the format used when writing a feature.
The overall structure of a feature is a dictionary as follows:
* "name": NAME
* "text": TEXT
* "subfeatures": SUBFEATURES
In addition to the hardcoded data provided in the feature, certain variables may be given at runtime.
## NOUNS
Nouns embedded into subfeature elements may be any of:
* "self"
* "creature"
* "creatures" (i.e., all creatures for whom "effect conditions" are true)
* "object"
* "structure"
* "point in space"
* "any"
* "terrain"
* NAME
Where NAME is interpreted by the game as a specific creature or object with a matching name.
## Variables
Many features are very similar between creatures except for certain variables. When instantiated programatically, the feature is given the following:
* NAME: The name of the creature with this feature
* V0, V1, ... VN: Zero-indexed list of integer variables
Certain portions of features accept these as parameters, either inline as in TEXT, or in the place of hardcoded variables for conditions or effects.
In addition to these, certain attributes of the creature having this feature may be probed (as they are intrinsic, modifications are reverted at the end of a duration) such as:
* STR
* DEX
* CON
* INT
* WIS
* CHA
* PROF
* MAXHP
* HP
* MOVESPEED
* MOVEREMAIN
* SPELLDC
* SIZE (stored as a scalar, e.g., 5 for Medium or 2.5 for Tiny)
* OBJECT\_TYPE (-1: creature, 0: misc item, 1: weapon, 2: armor, 3: shield)
* OBJECT\_AC
* CR
* PLANE = 0 (each value is a different plane)
* DAMAGE (Returns a damage object regarding the most recent time this was hit):
* AMOUNT
* CRITICAL
* TYPE
* ATTACK (Returns an attack object regarding the most recent attack this made):
* MELEE
* ADVANTAGE
* DISADVANTAGE
* WEAPON (0 is none, else weapon ID)
* TURNS (number of completed turns since rolling initiative)
* FLYING
* TERRAIN (current terain)
* LIGHTING (i.e., sunlight, dim light, darkness, magical darkness)
* LANGUAGECOUNT
* SURPRISED
* METAL (i.e., made of metal)
* TERRAIN\_IS\_DIFFICULT (only applies to terrain)
Furthermore, this list is expanded with the following properties and conditions (default values provided) (note: for conditions other than EXHAUSTED, e.g., GRAPPLED, the value is the ID of the source of the condition):
* BLINDED = 0
* CHARMED = 0
* DEAFENED = 0
* FRIGHTENED = 0
* GRAPPLED = 0
* INCAPACITATED = 0
* INVISIBLE = 0
* PARALYZED = 0
* PETRIFIED = 0
* POISONED = 0
* PRONE = 0
* RESTRAINED = 0
* STUNNED = 0
* UNCONSCIOUS = 0
* EXHAUSTED = 0 (ranges up to 6)
* REGAINS\_HP = 1
* CAN\_STOP\_IN\_HOSTILE\_SPACE = 0
* MIN\_SPACE\_WITHOUT\_SQUEEZING = SIZE
* BREATHES\_AIR = 1
* BREATHES\_WATER = 0
* BREATH\_HOLD\_MINUTES = (1,CON,+,.5,max)
* CARRY\_CAPACITY = (2,SIZE,2.5,-,SIZE,0,ifelse,5,-,5,/,^,15,\*,STR,\*)
* BERSERK = 0
* TELEPATHIC = 0 (0 = no, 1 = yes, .5 = one-way)
* DASH = 0 (0 = action, 1 = bns action)
* DISENGAGE = 0
* HIDE = 0
* SEES\_MAGICAL\_DARKNESS = 0
* SEES\_ETHEREAL = 0
* DETECTS\_LIES = 0
* LEAVES\_CORPSE = 1
* HOLDS\_INVENTORY = 1
* PROVOKES\_OPPORTUNITY\_ATTACKS = 1
* IGNORES\_DIFFICULT\_TERRAIN = 0
* PASSES\_THROUGH\_CREATURES\_AS\_DIFFICULT\_TERRAIN = 0
* IGNORES\_WEBS = 0
* REACTIONS = 1
* BRIGHT\_LIGHT = 0
* DIM\_LIGHT = 0
* PERFECT\_MAP\_RECALL = 0
* MIMIC\_SOUNDS\_VOICES\_INSIGHT\_DC = (PERFORMANCE,DECEPTION,max)
* SPEAKS\_WITH\_BEASTS = 0
* SPEAKS\_WITH\_PLANTS = 0
* SPIDER\_CLIMB = 0
* BOILS\_WATER = 0
* FORM\_STATE = 0 (0 is true form, others are defined in features)
* MUNDANE\_OBJECT\_WHEN\_STILL = 0
* CAN\_SMELL = 1
* ALIGNMENT = 11 (00: LG, 11: NN, 22: CE, etc.)
* ANTIMAGIC\_INCAPACITATES = 0
* ALIVE = 1
* BLINDSIGHT = 0
* RUST = 0
* EXPOSED = 0 (underside is exposed)
* HEADS = 1
* SPELLSLOTS = 0 (num remaining)
* NV1, NV2, ... (variables saved to N private only to this feature, all initially 0)
The above attributes by default apply to self (i.e., self.STR), however, they may also be used for another creature (i.e., creature.STR).
Simple math can be provided in postfix notation surounded by parentheses. For example, to set a save DC equal to 8+int+prof: (8,INT,PROF,+,+), or to set breath time to max(.5, 1+CON): (1,CON,+,.5,max). Additionally, boolean expressions may be imbedded, using "|" for "or", "&" for "and", "!" for not (which only consumes one operand), comparitors (i.e., "<", ">", "<=", ">=", "=="), and an "ifelse" expresion, with 0 being false and any else being true. The following rules are respected; note order matters:
* (X,Y,&) -> 0 if Y == 0, else X
* (X,Y,|) -> Y if X == 0, else X
* (X,!) -> 1 if X == 0, else 0
* (X,Y,<) -> 1 if X < Y, else 0
* (X,Y,Z,ifelse) -> if X != 0 then Y, else Z
* (X,consume) -> removes X from the stack
* (X,duplicate) -> X, X
* (X,Y,store) -> X, and stores X to variable Y
More complex conditions are below, potentially resulting in complex "types":
* bool: 0 is false, 1 is true
* creature: stored as creature ID
* TYPE: various constants for skills, abilities, damage types, etc.
Syntax is "operator": operand1, operand2,... -> resultType; description (if necessary)
* "hostile": N1, N2 -> bool; N1 is hostile to N2 (one-directional)
* "allied": N1, N2; N1 is allied to N2 (one-directional)
* "approves": N; N agrees to the effect
* "roll": N, TYPE -> int; TYPE is an ability or skill
* "distance": N1, N2 -> int; units of feet
* "sees": N1, N2 -> bool; N1 can see N2
* "movedto": N1, N2 -> int; distance (feet) N1 moved directly toward N2 this turn
* "underspell": N, SPELL -> bool; N is currently under the effects of SPELL; SPELL can alternatively be of school SCHOOL
* "N is in lighting LIGHTING" (sunlight, dim light, darkness, magical darkness)
* "understand": N1, N2 -> bool; N1 and N2 share a language
* "bound": N1, N2 -> bool; N1 is bound by N2
* "aware": N1, N2 -> bool; N1 as aware of N2
* "webshare": N1, N2 -> bool; N1 and N2 are in the same web
* "carried": N1, N2 -> bool; N1 is worn or carried by N2
## TEXT
This is explanatory text. It accepts embedded variables in the form {VARNAME}. For example, the text "The {NAME}'s weapon attacks are magical. When the {NAME} hits with any weapon, the weapon deals an extra {V0}d{V1} radiant damage.", when applied to a "deva" with runtime variables (4, 8), we get:
"The deva's weapon attacks are magical. When the deva hits with any weapon, the weapon deals an extra 4d8 radiant damage."
## Subfeatures
Each feature consists of a list of "subfeatures", which are treated as independent features in the game, but are grouped together for clear organization.
Each subfeature is a dictionary with the following elements:
* "trigger": TRIGGER
* "conditions": CONDITIONS
* "effects": EFFECTS
* "recharge": RECHARGE
Several of the elements accept various nouns.
### TRIGGER
TRIGGER is a list containing any of the following followed by nouns corresponding to instances of N:
The subfeature activates when TRIGGER is true. The TRIGGER uses any condition, with the following exclusive conditions:
* "passive": -> bool; evaluated on initialization
* "action": -> bool; taken by creature on turn
* "bonus": -> bool; bonus action
* "free": -> bool; free action
* "legendary": X -> bool; legendary action costing X
* "turnstart": N -> bool; N start of turn
* "turnend": N -> bool; N end of turn
* "damaged": N -> bool; N takes damage
* "moves": N -> bool; N moves
* "checkagainst": N1, N2 -> ROLLCLASS; N1 makes check against N2
* "forcesave": N1, N2 -> ROLLCLASS; N1 forces N2 to save
* "rolls": N, X -> bool; N rolls a dX
* "targetspell": N1, N2 -> SPELL; N1 targets N2 by a spell
* "attacks": N1, N2 -> ATTACK; N1 attacks N2
* "hits": N1, N2 -> DAMAGE; N1 hits N2
* "touches": N1, N2 -> bool; N1 touches N2
Where ROLLCLASS is any of:
* "attack"
* "grapple"
* "escape grapple"
* "shove"
* "frightened"
...
### CONDITION
CONDITION is a string containing the conditional which, if it evaluates to true (i.e., not 0), then the effect occurs.
### AOE
AOE is
* "in": N, AOE -> bool; N is in an AOE
* "line LENGTH WIDTH"
* "cone LENGTH"
### EFFECTS
EFFECTS is a list of dictionaries containing the following:
* "target": NOUN
* "condition": CONDITION
* "effect": [EFFECT, variables]
* "duration": DURATION
(Note: Unlike subfeature conditions, effect conditions apply to each target individually, i.e., for target = creatures, we can apply condition on each creature.)
Where EFFECT is any of the following (UNDER CONSTRUCTION DENOTED BY x):
* "Move up to X ft toward N"
x * Increase movement speed by X
x * Increase jump distance by X
x * Increase jump height by X
* "Set N = N"
* "Destroyed"
x * Death
x * Surprised
x * Pushed X feet in DIRECTION direction
x * Immune to feature FEATURE
x * Immune to spells with trait SPELL\_TRAIT
* "Impose disadvantage"
* "Impose disadvantage on TYPE" (any of "attack rolls", "ability checks", "saving throws")
* "Grant advantage"
* "Grant critical hit"
x * Advantage on rolls ROLL\_CLASS
x * Automatic fail on rolls ROLL\_CLASS
x * Automatic succeed on rolls ROLL\_CLASS
x * Move X distance
x * Deal X damage
* "Inflict XdX TYPE damage"
* "Inflict XdX TYPE damage, dc X ABILITY save halves"
* "Deal +X weapon die damage"
* "Damage dealt is magical"
* "Take action ACTION"
* "cantrip"
* "cast spell"
* "attack"
* specific feature
x * Disable other feature
x * Know distance/direction to creature/object within X distance
* "Reduce incoming damage by X"
* "Regain X hp"
* "Polymorph N into creature <= X cr"
x * Weapon/armor corrodes
x * Ignite flammable objects
x * Expend spell slot
x * Special movement
x * Plane shift
x * Grant spell effect
x * Transparency (perpetual hidenness?)
x * Prescribed actions (randomized), any of:
x - Nothing
x - Moves in random direction
x - Attacks random creature within reach
x * Telepathic command
x * Learns creature's desires
x * Spell storing
x * Creates X diameter tunnel
The conditions on an effect may be omitted if not applicable, and are the same as conditions for a trigger.
The duration of an effect may be omitted for instantaneous effects and is a condition, including the contents of TRIGGER, plus the following:
x * "End of turn"
x * "Start of next turn"
x * "End of self next turn"
x * "End of target next turn"
x * "Until action is taken to end"
x * TIME (formatted "X units", where units is any of sec, min, hr, day, month, year)
x * "Until lesser restoration is cast" (implies at least lesser)
x * "Until overridden or dead"
x * Repeated saves???
x * Repeated saves at advantage/disadvantage with condition???
x * Until certain spell is cast???
x * Until other effect expires???
### RECHARGE
The recharge of a feature may be omitted to indicate that it is unlimited. Otherwise, it is a list of the following two items:
* Integer indicating number of times the feature can be used
* Any of "turn", "long rest", "short rest", "X-Y" (for integers X and Y) indicating range on a d6 where spent uses are restored
|