diff --git a/app/imports/api/docs/Docs.js b/app/imports/api/docs/Docs.js index 6f97d27d..acce3445 100644 --- a/app/imports/api/docs/Docs.js +++ b/app/imports/api/docs/Docs.js @@ -112,6 +112,22 @@ function getDocLink(doc, urlName) { return address.join('/'); } +// Add a means of seeding new servers with documentation +if (Meteor.isClient) { + Docs.getJsonDocs = function () { + return JSON.stringify(Docs.find({}).fetch(), null, 2); + } +} else if (Meteor.isServer) { + Meteor.startup(() => { + if (!Docs.findOne()) { + Assets.getText('docs/defaultDocs.json', (string) => { + const docs = JSON.parse(string) + docs.forEach(doc => Docs.insert(doc)); + }); + } + }); +} + const insertDoc = new ValidatedMethod({ name: 'docs.insert', validate: null, diff --git a/app/imports/client/ui/docs/DocViewer.vue b/app/imports/client/ui/docs/DocViewer.vue index f49de442..661cf158 100644 --- a/app/imports/client/ui/docs/DocViewer.vue +++ b/app/imports/client/ui/docs/DocViewer.vue @@ -5,12 +5,13 @@ lg="8" > `, less than: `<`, greater than or equal to: `>=`, less than or equal to: `<=`, equal: `=` or `==` or `===`, not equal: `!=` or `!==` |\n| **If-else** | `condition ? resultIfTrue : resultIfFalse`, `level > 10 ? 'high tier' : 'low tier'` |\n| **Arrays** | lists of values `[3, 6, 9, 12]`. |\n| **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]`. |\n| **Function calls** | `functionName(argument1, argument1)` See [Functions](/docs/functions) for a full list of available functions. |\n\n## Special variables\n\n### Built-in variables\n\nThese 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.\n\n- `xp` A total of all the experiences with xp added to the character sheet\n- `milestoneLevels` A total of all the experiences with milestone levels added to the character sheet\n- `itemsAttuned` Number of items the creature is attuned to\n- `weightEquipment` Total weight of all equipment on the creature\n- `valueEquipment` Total value of all equipment on the creature\n- `weightTotal` Total weight of the creature's entire inventory\n- `valueTotal` Total value of the creature's entire inventory\n- `weightCarried` Total weight of all carried items and containers\n- `valueCarried` Total value of all carried items and containers\n- `level` The current level of the creature, including all class levels\n- `criticalHitTarget` Defaults to 20, the natural roll needed to consider an attack roll as a critical hit\n\n### Action variables\n\nThese variables are available during an action after the relevant property has been applied.\n\nFor Advanced users, a [Roll](/docs/property/roll) can set these variables, overriding the default behavior.\n\n#### [Actions](/docs/property/action)\n\n- `$attackDiceRoll` The value of the d20 roll before any modifiers were applied.\n- `$attackRoll` The total attack roll after modifiers.\n- `$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`.\n- `$criticalMiss` Set to `true` if the attack roll was not a critical hit and rolled a natural 1 on the d20 roll.\n- `$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.\n- `$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.\n\n#### [Damage](/docs/property/damage)\n\n- `$lastDamageType` The type of damage dealt last, any damage that has the `extra` type will use this damage type instead\n\n#### [Saving throws](/docs/property/saving-throw)\n\n- `$saveFailed` Set to `true` if the target failed its saving throw or there are no targets for the saving throw\n- `$saveSucceeded` Set to `true` if the target made its saving throw or there are no targets for the saving throw\n- `$saveDiceRoll` The unmodified d20 roll the target made to save\n- `$saveRoll` The final value of the saving throw roll after modifiers\n\n## Ancestor references\n\nThe ancestors of a property can be accessed directly using the `#ancestorType` syntax.\n\nFor example, a spell might need to know the save DC of the spell list that it is inside of, it can use `#spellList.dc`.\n\nTriggers 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." + }, + { + "_id": "o8u2Z5gZW54ZXNeZB", + "name": "Dependency loops", + "parent": { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs" + }, + "ancestors": [ + { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs", + "name": "Concepts", + "urlName": "concepts" + } + ], + "order": 35, + "urlName": "dependency-loops", + "href": "/docs/concepts/dependency-loops", + "published": true, + "description": "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.\n\nBut consider the following property values that could be added to a creature\n\n- The creature's Strength base value is set to `dexterity + 1` so that it will always have 1 more strength than dexterity\n- The creature's Dexterity base value is set to `constitution + 1` so that it will always have 1 more dexterity than constitution\n- The creature's Constitution base value is set to `strength` so that its constitution is always equal to its strength\n\nIt 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.\n\nMost 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.\n\n![dependency loop example](/images/docs/dependency-loop.png)\n\n## Toggles\n\nCalculated [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.\n\nConsider this example\n\n- A calculated toggle that is active if `strength < 10`\n- An effect under that toggle that adds 2 to `strength`\n\nThe 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.\n\n## Troubleshooting a dependency loop\n\n- 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.\n- Move any properties in the loop out from being children of calculated Toggles\n- Use static values in place of variables where they are not stricly needed\n- Ask for [help](/feedback)" + }, + { + "_id": "KFkmXFLQrdPQNpJ7X", + "name": "Inline Calculations", + "parent": { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs" + }, + "ancestors": [ + { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs", + "name": "Concepts", + "urlName": "concepts" + } + ], + "order": 36, + "urlName": "inline-calculations", + "href": "/docs/concepts/inline-calculations", + "description": "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.\n\nFor example a creature's strength attribute may have the following in its description: `Your carrying capacity is {strength * 15} lbs.`\n\nWhen the creature is calculated, if it has 8 strength, the action description will become: \"Your carrying capacity is 120 lbs.\"\n\nIf 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`.\n\nDo 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.", + "published": true + }, + { + "_id": "QFtqb7y5kLPDJoWXG", + "name": "Tags", + "parent": { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs" + }, + "ancestors": [ + { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs", + "name": "Concepts", + "urlName": "concepts" + } + ], + "order": 37, + "urlName": "tags", + "href": "/docs/concepts/tags", + "description": "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.\n\n## Built in tags\n\nProperties have specific tags automatically for use with tag-targeting. These aren't relevant for slots and finding properties in a library with specific tags.\n\n- `#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\n- `variableName` if a property has a variable name it will be included as a tag\n- The type of damage done by a [damage](/docs/property/damage) property: `bludgeoning`, `slashing`, `...` \n- The skill type of a [skill](/docs/property/skill) property: `skill`, `save`, `check`, `tool`, `weapon`, `armor`, `language`, `utility`\n- The attribute type of an [attribute](/docs/property/attribute) property: `ability`, `stat`, `modifier`, `hitDice`, `healthBar`, `resource`, `spellSlot`, `utility`\n- When the property resets: `longRest`, `shortRest`" + }, + { + "_id": "3dkEFEnwH4ShSY2BS", + "name": "Functions", + "parent": { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs" + }, + "ancestors": [ + { + "id": "E2DFwsCoiKy2Rc9Mz", + "collection": "docs", + "name": "Concepts", + "urlName": "concepts" + } + ], + "order": 38, + "urlName": "functions", + "href": "/docs/concepts/functions", + "description": "## min\nReturns the smallest of the given numbers\n`min(12, 6, 3, 168)` = `3`\n\n## round\nReturns the value of a number rounded to the nearest integer\n`round(5.95)` = `6`\n`round(5.5)` = `6`\n`round(5.05)` = `5`\n\n## floor\nRounds a number down to the next smallest integer\n`floor(5.95)` = `5`\n`floor(5.05)` = `5`\n`floor(5)` = `5`\n`floor(-5.5)` = `-6`\n\n## ceil\nRounds a number up to the next largest integer\n`ceil(5.95)` = `6`\n`ceil(5.05)` = `6`\n`ceil(5)` = `5`\n`ceil(-5.5)` = `-5`\n\n## trunc\nReturns the integer part of a number by removing any fractional digits\n`trunc(5.95)` = `5`\n`trunc(5.05)` = `5`\n`trunc(5)` = `5`\n`trunc(-5.5)` = `-5`\n\n## sign\nReturns either a positive or negative 1, indicating the sign of a number, or zero\n`sign(-3)` = `-1`\n`sign(3)` = `1`\n`sign(0)` = `0`\n\n## tableLookup\nReturns the index of the last value in the array that is less than the specified amount\n`tableLookup([100, 300, 900], 457)` = `2`\n`tableLookup([100, 300, 900], 23)` = `0`\n`tableLookup([100, 300, 900, 1200], 900)` = `3`\n`tableLookup([100, 300], 594)` = `2`\n\n## resolve\nForces the given calcultion to resolve into a number, even in calculations where it would usually keep the unknown values as is\n`resolve(someUndefinedVariable + 3 + 4)` = `7`\n`resolve(1d6)` = `4`", + "published": true + } +] \ No newline at end of file