Finished basic docs

This commit is contained in:
Stefan Zermatten
2022-09-05 14:36:39 +02:00
parent f0e7253374
commit dbc5f7253f
13 changed files with 224 additions and 56 deletions

View File

@@ -112,10 +112,10 @@ export default {
}
},
'resolve': {
comment: 'Forces the given calcultion to resolve into a number',
comment: 'Forces the given calcultion to resolve into a number, even in calculations where it would usually keep the unknown values as is',
examples: [
{input: 'resolve(someUndefinedVariable + 3 + 4)', result: '7'},
{input: 'resolve(3d6)', result: '2'},
{input: 'resolve(1d6)', result: '4'},
],
arguments: ['parseNode'],
fn: function resolveFn(node){

View File

@@ -4,6 +4,7 @@ import { propsByDocsPath } from '/imports/constants/PROPERTIES.js';
// Manual doc paths
const docPaths = [
'computed-fields',
'inline-calculations',
'dependency-loops',
'docs',
'tags',

View File

@@ -1,5 +1,5 @@
<template>
<v-container>
<v-container class="documentation">
<v-row>
<v-col cols="12">
<v-fade-transition mode="out-in">
@@ -97,4 +97,4 @@ export default {
}
}
}
</script>
</script>

View File

@@ -0,0 +1,56 @@
<template>
<v-container class="documentation">
<v-row>
<v-col cols="12">
<v-card>
<v-card-text class="markdown">
<h1>Functions</h1>
<div
v-for="fn in functions"
:key="fn.name"
class="mb-3"
>
<h3>{{ fn.name }}</h3>
<div class="my-2">
{{ fn.comment }}
</div>
<table style="min-width: initial;">
<tr
v-for="example in fn.examples"
:key="example.input"
>
<td>
<code>{{ example.input }}</code>
</td>
<td>
<v-icon>mdi-arrow-right</v-icon>
</td>
<td>
<code>{{ example.result }}</code>
</td>
</tr>
</table>
</div>
</v-card-text>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script lang="js">
import functions from '/imports/parser/functions.js';
export default {
computed:{
functions(){
let fns = [];
for (let name in functions){
let f = functions[name];
fns.push({name, ...f});
}
console.log(fns);
return fns;
}
}
}
</script>

View File

@@ -16,7 +16,8 @@ const SignIn = () => import('/imports/ui/pages/SignIn.vue' );
const Register = () => import('/imports/ui/pages/Register.vue');
const IconAdmin = () => import('/imports/ui/icons/IconAdmin.vue');
//const Friends = () => import('/imports/ui/pages/Friends.vue' );
const Feedback = () => import('/imports/ui/pages/Feedback.vue' );
const Feedback = () => import('/imports/ui/pages/Feedback.vue');
const FunctionReference = () => import('/imports/ui/pages/FunctionReference.vue');
const Account = () => import('/imports/ui/pages/Account.vue' );
const InviteSuccess = () => import('/imports/ui/pages/InviteSuccess.vue' );
const InviteError = () => import('/imports/ui/pages/InviteError.vue' );
@@ -243,6 +244,14 @@ RouterFactory.configure(router => {
meta: {
title: 'Feedback',
},
}, {
path: '/docs/functions',
components: {
default: FunctionReference,
},
meta: {
title: 'Functions',
},
}, {
path: '/docs/:docPath([^/]+.*)',
components: {

View File

@@ -86,7 +86,7 @@
}
.markdown tbody>tr:nth-child(odd) {
background-color: rgba(0, 0, 0, 0.1)
background-color: rgba(0, 0, 0, 0.03)
}
.markdown ul {
@@ -94,5 +94,26 @@
}
.theme--dark.v-application .markdown tbody>tr:nth-child(odd) {
background-color: rgba(255, 255, 255, 0.1)
background-color: rgba(255, 255, 255, 0.03)
}
.documentation .markdown {
font-size: 16px;
line-height: 24px;
}
.documentation .markdown p {
line-height: 24px;
}
.documentation .markdown ul {
line-height: 32px;
}
.documentation .markdown td {
padding: 8px;
}
.documentation .markdown th {
padding: 8px;
}

View File

@@ -1,49 +0,0 @@
<template lang="html">
<div>
<div
v-for="fn in functions"
:key="fn.name"
class="mb-3"
>
<h3>{{ fn.name }}</h3>
<div class="my-2">
{{ fn.comment }}
</div>
<table>
<tr
v-for="example in fn.examples"
:key="example.input"
>
<td>
<code>{{ example.input }}</code>
</td>
<td>
<v-icon>mdi-arrow-right-thick</v-icon>
</td>
<td>
<code>{{ example.result }}</code>
</td>
</tr>
</table>
</div>
</div>
</template>
<script lang="js">
import functions from '/imports/parser/functions.js';
export default {
computed:{
functions(){
let fns = [];
for (let name in functions){
let f = functions[name];
fns.push({name, ...f});
}
return fns;
}
}
}
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,4 +1,81 @@
# Computed fields
Some fields in DiceCloud creature properties expect calculations. These fields are then computed by the DiceCloud engine.
Some fields, like the value of an attirbute, resolve down to a single number, while others, like the damage to deal in an attack, only simplify their calculation as far as they can, and then resolve down to a number when applied. Avoid adding dice rolls to calculations that expect to resolve down to a number, because they will re-roll every time the creature is recalculated, causing instability in the creature's stats.
## Parser
The DiceCloud parser can understand the following syntax:
| | |
| :- | :- |
| **Numbers** | `13`, `3.14` |
| **Dice rolls** | `3d6`, `(1 + 2)d4`|
| **Strings of text** | `'Some text'`, `"some other text"` |
| **Boolean values** | `true` or `false`. When DiceCloud expects a boolean, `0`, an empty string `''` and `false` are all considered false by DiceCloud's engine, every other value is considered true. |
| **Variable names** | `variableName` |
| **Addition and subtraction** | `1 + 2 + 3`, `12 - 6` |
| **Multiplication** | `6 * 4`, `12 * 2` = `24` |
| **Exponents** | `3 ^ 2` Raise 3 to the power of 2 |
| **Modulo** | Returns the remainder of a division operation `15 % 6` = `3` |
| **AND** | `&` or `&&`: Returns the value of the right hand side if the left side is true `true & 'cat'` = `'cat'` |
| **OR** | `|` or `||`: Returns the left hand side if it is true, otherwise returns the right hand side `'dog' || 'cat'` = `'dog'` |
| **NOT** | `!` returns false if the value after it is true, otherwise returns false |
| **Comparisons** | greater than: `>`, less than: `<`, greater than or equal to: `>=`, less than or equal to: `<=`, equal: `=` or `==` or `===`, not equal: `!=` or `!==` |
| **If-else** | `condition ? resultIfTrue : resultIfFalse`, `level > 10 ? 'high tier' : 'low tier'` |
| **Arrays** | lists of values `[3, 6, 9, 12]`. |
| **Array Indexes** | A value can be chosen from an array using another set of square brackets: `[3, 6, 9, 12][2]` = `[6]` because `[2]` fetches the 2nd value in the array. Arrays start at 1 in DiceCloud so that level tables can have 20 entries and be accessed by `array[level]`. |
| **Function calls** | `functionName(argument1, argument1)` See [Functions](/docs/functions) for a full list of available functions. |
## Special variables
### Built-in variables
These variables are added to the creature automatically when relevant. They can be overriden if needed by creating a property with the same variable name. They can also be targetted by effects.
- `xp` A total of all the experiences with xp added to the character sheet
- `milestoneLevels` A total of all the experiences with milestone levels added to the character sheet
- `itemsAttuned` Number of items the creature is attuned to
- `weightEquipment` Total weight of all equipment on the creature
- `valueEquipment` Total value of all equipment on the creature
- `weightTotal` Total weight of the creature's entire inventory
- `valueTotal` Total value of the creature's entire inventory
- `weightCarried` Total weight of all carried items and containers
- `valueCarried` Total value of all carried items and containers
- `level` The current level of the creature, including all class levels
- `criticalHitTarget` Defaults to 20, the natural roll needed to consider an attack roll as a critical hit
### Action variables
These variables are available during an action after the relevant property has been applied.
For Advanced users, a [Roll](/docs/property/roll) can set these variables, overriding the default behavior.
#### [Actions](/docs/property/action)
- `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.
- `$attackRoll` The total attack roll after modifiers.
- `$criticalHit` Set to `true` if the attack roll's d20 is a natural 20. If `criticalHitTarget` is set, the attack roll's d20 must instead be equal to or greater than `criticalHitTarget` for this to be set to `true`.
- `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.
- `$attackHit` If the attack roll is higher than or equal to the target's AC or a critical hit this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical hit.
- `$attackMiss` If the attack roll is lower than the target's AC or a critical miss, this is set to `true`. Remains unset if there is no target for the attack unless the attack is a critical miss.
#### [Damage](/docs/property/damage)
- `$lastDamageType` The type of damage dealt last, any damage that has the `extra` type will use this damage type instead
#### [Saving throws](/docs/property/saving-throw)
- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw
- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw
- `$saveDiceRoll` The unmodified d20 roll the target made to save
- `$saveRoll` The final value of the saving throw roll after modifiers
## Ancestor references
The ancestors of a property can be accessed directly using the `#ancestorType` syntax.
For example, a spell might need to know the save DC of the spell list that it is inside of, it can use `#spellList.dc`.
Triggers and their children work differently: They don't have access to their own ancestors, but rather inherit the ancestors of the property that caused them to fire. For example, a trigger at the root of the creature's tree might be fired by a spell being cast, you can still use references to ancestors like `#spellList.attackRollBonus` inside that trigger as if it were under the spell itself.

View File

@@ -1,2 +1,33 @@
# Dependency loops
When a variable is referenced in a calculation, that calculation can be said to depend on that variable. In order for the calculation to compute, the value of the variable needs to be known.
But consider the following property values that could be added to a creature
- The creature's Strength base value is set to `dexterity + 1` so that it will always have 1 more strength than dexterity
- The creature's Dexterity base value is set to `constitution + 1` so that it will always have 1 more dexterity than constitution
- The creature's Constitution base value is set to `strength` so that its constitution is always equal to its strength
It is not possible to resolve these calculations, not just because no values exist which satisfy the constraints, but because strength depends on dexterity which depends on constitution which depends on strength. None can be computed before the others have finalized their values. This is a dependency loop.
Most dependency loops that appear in actual DiceCloud creatures are less trivial than this example, but they cause the same result: a sheet that can't be accurately computed. In these cases, DiceCloud does its best, chooses an order to resolve the calculations arbitrarily, and continues calculating. An error will show on the Build tab to let you know that something went wrong.
![dependency loop example](/images/docs/dependency-loop.png)
## Toggles
Calculated [Toggles](/docs/property/toggle) are the main source of dependency loops on creatures, because they create a dependency that isn't as obvious as a calculation might be. When a toggle is in calculated mode, its children do not know whether they are active or not until the calulation is resolved. Because of this, every calculation under the toggle depends on the toggles calaculation, making the chance for a loop to be formed more likely the more children are under a toggle.
Consider this example
- A calculated toggle that is active if `strength < 10`
- An effect under that toggle that adds 2 to `strength`
The effect can't compute, because it does not know if it is active yet, so the toggle must compute its calculation first. The toggle needs to know if `strength` is greater than 10. Strength depends on all of the effects targeting it, it must know if the +2 effect is active or not. This creates a dependency loop, because there is no valid order in which everything can be calculated.
## Troubleshooting a dependency loop
- First, identify all the properties that make up the dependency loop. These are linked in the depdency loop error message. The field names in square brackets after the property name indicates which calculations on the property are directly involved.
- Move any properties in the loop out from being children of calculated Toggles
- Use static values in place of variables where they are not stricly needed
- Ask for [help](/feedback)

View File

@@ -35,4 +35,5 @@
- ### [Computed fields](/docs/computed-fields)
- ### [Inline Calculations](/docs/inline-calculations)
- ### [Dependency Loops](/docs/dependency-loops)
- ### [Functions](/docs/functions)
- ### [Tags](/docs/tags)

View File

@@ -1,2 +1,11 @@
# Inline Calculations
Most long-format fields allow inline [calculations](/docs/computed-fields) to be included. Calculations inside of curly bracers will be computed down to numbers using the characters stats.
For example a creature's strength attribute may have the following in its description: `Your carrying capacity is {strength * 15} lbs.`
When the creature is calculated, if it has 8 strength, the action description will become: "Your carrying capacity is 120 lbs."
If a description includes a dice roll, only the part that can be calculated to a single number should be included in the calulation bracers: `The attack does an extra {paladin.level}d8 damage`, which becomes `The attack does an extra 4d8 damage`.
Do not inlclude the dice roll in the calaculation: `The attack does an extra {(paladin.level)d8} damage`, because it will become `The attack does an extra 16 damage` but the number 16 will change every time the creature recalculates.

View File

@@ -1,2 +1,14 @@
# Tags
Tags are used to reference multiple similar properties at once. A slot can require only properties from your library that has matching tags, effects and some other properties can also target properties to apply to by tags.
## Built in tags
Properties have specific tags automatically for use with tag-targeting. These aren't relevant for slots and finding properties in a library with specific tags.
- `#type` Actions will have the `#action` tag, etc. Damage will either have the tag `#damage` or the tag `#healing` if the damage type is healing
- `variableName` if a property has a variable name it will be included as a tag
- The type of damage done by a [damage](/docs/property/damage) property: `bludgeoning`, `slashing`, `...`
- The skill type of a [skill](/docs/property/skill) property: `skill`, `save`, `check`, `tool`, `weapon`, `armor`, `language`, `utility`
- The attribute type of an [attribute](/docs/property/attribute) property: `ability`, `stat`, `modifier`, `hitDice`, `healthBar`, `resource`, `spellSlot`, `utility`
- When the property resets: `longRest`, `shortRest`

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB