Whether or not to append the layer to the tabs list. If set to false, then the tree node will instead always remove all tabs to its right and then add the layer tab. Defaults to true.
A button that is used to control a conversion. It will show how much can be converted currently, and can show when that amount will go up, as well as handle only being clickable when a sufficient amount of currency can be gained. Assumes this button is associated with a specific node on a tree, and triggers that tree's reset propagation.
Takes an array of modifier "sections", and creates a JSXFunction that can render all those sections, and allow each section to be collapsed. Also returns a list of persistent refs that are used to control which sections are currently collapsed.
Utility function for displaying the result of a formula such that it will, when told to, preview how the formula's result will change. Requires a formula with a single variable inside.
Given a player save data object being loaded, return a list of layers that should currently be enabled. If your project does not use dynamic layers, this should just return all layers.
An object representing a theme the player can use to change the look of the game.
Name
Type
Description
floatingTabs
boolean
Whether or not tabs should "float" in the center of their container.
mergeAdjacent
boolean
Whether or not adjacent features should merge together - removing the margin between them, and only applying the border radius to the first and last elements in the row or column.
showPin
boolean
Whether or not to show a pin icon on pinned tooltips.
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
A type representing a computable value for a node on the board. Used for node types to return different values based on the given node and the state of the board.
Whether or not completing this challenge should grant multiple completions if requirements met. Requires requirements to be a requirement or array of requirements with Requirement.canMaximize true.
onComplete?
VoidFunction
A function that is called when the challenge is completed.
onEnter?
VoidFunction
A function that is called when the challenge is entered.
onExit?
VoidFunction
A function that is called when the challenge is exited.
Utility for taking an array of challenges where only one may be active at a time, and giving a ref to the one currently active (or null if none are active)
The absolute amount the output resource will be changed by. Typically this will be set for you in a conversion constructor. This will differ from currentGain in the cases where the conversion isn't just adding the converted amount to the output resource.
The amount of the input resource currently being required in order to produce the currentGain. That is, if it went below this value then currentGain would decrease. Typically this will be set for you in a conversion constructor.
The formula used to determine how much gainResource should be earned by this converting. The passed value will be a Formula representing the baseResource variable.
A callback that happens after a conversion has been completed. Receives the amount gained via conversion. This will not be called whenever using currentGain without calling convert (e.g. passive generation)
Lazily creates a conversion with the given options. You typically shouldn't use this function directly. Instead use one of the other conversion constructors, which will then call this.
Creates a conversion that simply adds to the gainResource amount upon converting. This is similar to the behavior of "normal" layers in The Modding Tree. This is equivalent to just calling createConversion directly.
Creates a conversion that will replace the gainResource amount with the new amount upon converting. This is similar to the behavior of "static" layers in The Modding Tree.
This will automatically increase the value of conversion.gainResource without lowering the value of the input resource. It will by default perform 100% of a conversion's currentGain per second. If you use a ref for the rate you can set it's value to 0 when passive generation should be disabled.
Utility function for a function that returns an object of a given type, with "this" bound to what the type will eventually be processed into. Intended for making lazily evaluated objects.
Any value that can be passed into an HTML element's style attribute. Note that Profectus uses its own StyleValue and CSSProperties that are extended, in order to have additional properties added to them, such as variable CSS variables.
Traverses an object and returns all features that are not any of the given types. Features are any object with a "type" property that has a symbol value.
Gets a unique ID to give to each feature, used for any sort of system that needs to identify elements in the DOM rather than references to the feature itself. (For example, branches) IDs are guaranteed unique, but NOT persistent - they likely will change between updates.
Takes a function and marks it as JSX so it won't get auto-wrapped into a ComputedRef. The function may also return empty string as empty JSX tags cause issues.
Represents a cell within a grid. These properties will typically be accessed via a cell proxy that calls functions on the grid to get the properties for a specific cell.
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
An object that represents a feature that display particle effects on the screen. The config should typically be gotten by designing the effect using the online particle effect editor and passing it into the upgradeConfig from @pixi/particle-emitter.
Whether or not clicking this repeatable should attempt to maximize amount based on the requirements met. Requires requirements to be a requirement or array of requirements with Requirement.canMaximize true.
Returns a reference to the amount of resource being gained in terms of orders of magnitude per second, calcualted over the last tick. Useful for situations where the gain rate is increasing very rapidly.
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
An object that represents a feature that is a tree of nodes with branches between them. Contains support for reset mechanics that can propagate through the tree.
Utility for creating a tooltip for a tree node that displays a resource-based unlock requirement, and after unlock shows the amount of another resource. It sounds oddly specific, but comes up a lot.
Using document.fonts.ready returns too early on firefox, so we use document.fonts.onloadingdone instead, which doesn't accept multiple listeners. This event fires when that callback is called.
Sent when constructing the Settings object. Use it to add default values for custom properties to the object. See features/features.setDefault for setting default values.
onLoad
VoidFunction
Sent whenever a save has finished loading. Happens when the page is opened and upon switching saves in the saves manager.
A class that can be used for cost/goal functions. It can be evaluated similar to a cost function, but also provides extra features for supported formulas. For example, a lot of math functions can be inverted. Typically, the use of these extra features is to support cost/goal functions that have multiple levels purchased/completed at once efficiently.
Utility for calculating the cost of a formula for a given amount of purchases. If spendResources is changed to false, the calculation will be much faster with higher numbers.
Utility for calculating the maximum amount of purchases possible with a given formula and resource. If spendResources is changed to false, the calculation will be much faster with higher numbers.
An object that configures a Layer. Even moreso than features, the developer is expected to include extra properties in this object. All Persistent refs must be included somewhere within the layer object.
The layout of this layer's features. When the layer is open in game/player.PlayerData.tabs, but the tab is Layer.minimized this is the content that is displayed.
A reference to all the current layers. It is shallow reactive so it will update when layers are added or removed, but not interfere with the existing refs within each layer.
When creating layers, this object a map of layer ID to a set of any created persistent refs in order to check they're all included in the final layer object.
Enables a layer object, so it will be updated every tick. Note that accessing a layer/its properties does NOT require it to be enabled. For dynamic layers you can call this function and removeLayer as necessary. Just make sure getInitialLayers will provide an accurate list of layers based on the player data object. For static layers just make getInitialLayers return all the layers.
Convenience method for removing and immediately re-adding a layer. This is useful for layers with dynamic content, to ensure persistent refs are correctly configured.
Utility function for creating a modal that display's a display. Returns the modal itself, which can be rendered anywhere you need, as well as a function to open the modal.
An object that can be used to apply or unapply some modification to a number. Being reversible requires the operation being invertible, but some features may rely on that. Descriptions can be optionally included for displaying them to the player. The built-in modifier creators are designed to display the modifiers using createModifierSection.
Utility type used to narrow down a modifier type that will have a description and/or enabled property based on optional parameters, T and S (respectively).
â–¸ createSequentialModifier<T, S>(modifiersFunc): S
Takes an array of modifiers and applies and reverses them in order. Modifiers that are not enabled will not be applied nor reversed. Also joins their descriptions together.
Create a boolean ref that will automatically be set based on the given condition, but also dismissed when hovering over a given element, typically the element where acting upon the notification would take place.
Mark a Persistent as deleted, so it won't be saved and loaded. Since persistent refs must be created during a layer's options func, features can not create persistent refs after evaluating their own options funcs. As a result, it must create any persistent refs it might need. This function can then be called after the options func is evaluated to mark the persistent ref to not be saved or loaded.
Create a persistent ref, which can be saved and loaded. All (non-deleted) persistent refs must be included somewhere within the layer object returned by that layer's options func.
The amount of resource that must be met for this requirement. You can pass a formula, in which case maximizing will work out of the box (assuming its invertible and, for more accurate calculations, its integral is invertible). If you don't pass a formula then you can still support maximizing by passing a custom pay function.
When calculating multiple levels to be handled at once, whether it should consider resources used for each level as spent. Setting this to false causes calculations to be faster with larger numbers and supports more math functions. See
Whether or not this requirement can have multiple levels of requirements that can be met at once. Requirement is assumed to not have multiple levels if this property not present.
The display for this specific requirement. This is used for displays multiple requirements condensed. Required if visibility can be Visibility.Visible.
Calculates the maximum number of levels that could be acquired with the current requirement states. True/false requirements will be counted as Infinity or 0.
Loads the player settings from localStorage. Calls the GlobalEvents.loadSettings event for custom properties to be included. Custom properties should be added by the file they relate to, so they won't be included if the file is tree shaken away. Custom properties should also register the field to modify said setting using registerSettingField.
This section of the docs is generated via the doc comments inside the Profectus source code. While it can be used as a reference, the comments themselves should show up in your IDE when relevant, which is probably a better way to get help. The guide has longer-form explanations of key concepts and is more likely to be of use to new developers.
-
diff --git a/assets/api_modules_data_common.md.1d58f522.js b/assets/api_modules_data_common.md.af9c5ce0.js
similarity index 97%
rename from assets/api_modules_data_common.md.1d58f522.js
rename to assets/api_modules_data_common.md.af9c5ce0.js
index 60c4c3ef..1646fd82 100644
--- a/assets/api_modules_data_common.md.1d58f522.js
+++ b/assets/api_modules_data_common.md.af9c5ce0.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: data/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/common.md","lastUpdated":null}'),r={name:"api/modules/data/common.md"},d=a('
Whether or not to append the layer to the tabs list. If set to false, then the tree node will instead always remove all tabs to its right and then add the layer tab. Defaults to true.
A button that is used to control a conversion. It will show how much can be converted currently, and can show when that amount will go up, as well as handle only being clickable when a sufficient amount of currency can be gained. Assumes this button is associated with a specific node on a tree, and triggers that tree's reset propagation.
Takes an array of modifier "sections", and creates a JSXFunction that can render all those sections, and allow each section to be collapsed. Also returns a list of persistent refs that are used to control which sections are currently collapsed.
Utility function for displaying the result of a formula such that it will, when told to, preview how the formula's result will change. Requires a formula with a single variable inside.
',125),l=[d];function c(n,i,s,h,f,u){return o(),t("div",null,l)}const b=e(r,[["render",c]]);export{m as __pageData,b as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: data/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/common.md","lastUpdated":null}'),r={name:"api/modules/data/common.md"},d=a('
Whether or not to append the layer to the tabs list. If set to false, then the tree node will instead always remove all tabs to its right and then add the layer tab. Defaults to true.
A button that is used to control a conversion. It will show how much can be converted currently, and can show when that amount will go up, as well as handle only being clickable when a sufficient amount of currency can be gained. Assumes this button is associated with a specific node on a tree, and triggers that tree's reset propagation.
Takes an array of modifier "sections", and creates a JSXFunction that can render all those sections, and allow each section to be collapsed. Also returns a list of persistent refs that are used to control which sections are currently collapsed.
Utility function for displaying the result of a formula such that it will, when told to, preview how the formula's result will change. Requires a formula with a single variable inside.
',125),l=[d];function c(n,i,s,h,f,u){return o(),t("div",null,l)}const g=e(r,[["render",c]]);export{m as __pageData,g as default};
diff --git a/assets/api_modules_data_common.md.1d58f522.lean.js b/assets/api_modules_data_common.md.af9c5ce0.lean.js
similarity index 76%
rename from assets/api_modules_data_common.md.1d58f522.lean.js
rename to assets/api_modules_data_common.md.af9c5ce0.lean.js
index 30e30104..1c64f036 100644
--- a/assets/api_modules_data_common.md.1d58f522.lean.js
+++ b/assets/api_modules_data_common.md.af9c5ce0.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: data/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/common.md","lastUpdated":null}'),r={name:"api/modules/data/common.md"},d=a("",125),l=[d];function c(n,i,s,h,f,u){return o(),t("div",null,l)}const b=e(r,[["render",c]]);export{m as __pageData,b as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: data/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/common.md","lastUpdated":null}'),r={name:"api/modules/data/common.md"},d=a("",125),l=[d];function c(n,i,s,h,f,u){return o(),t("div",null,l)}const g=e(r,[["render",c]]);export{m as __pageData,g as default};
diff --git a/assets/api_modules_data_projEntry.md.65f0a74c.js b/assets/api_modules_data_projEntry.md.c2b3a1aa.js
similarity index 93%
rename from assets/api_modules_data_projEntry.md.65f0a74c.js
rename to assets/api_modules_data_projEntry.md.c2b3a1aa.js
index 116484f6..735ecace 100644
--- a/assets/api_modules_data_projEntry.md.65f0a74c.js
+++ b/assets/api_modules_data_projEntry.md.c2b3a1aa.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: data/projEntry","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/projEntry.md","lastUpdated":null}'),o={name:"api/modules/data/projEntry.md"},n=r('
Given a player save data object being loaded, return a list of layers that should currently be enabled. If your project does not use dynamic layers, this should just return all layers.
',27),d=[n];function l(i,s,c,h,p,f){return a(),t("div",null,d)}const b=e(o,[["render",l]]);export{y as __pageData,b as default};
+import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: data/projEntry","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/projEntry.md","lastUpdated":null}'),o={name:"api/modules/data/projEntry.md"},n=r('
Given a player save data object being loaded, return a list of layers that should currently be enabled. If your project does not use dynamic layers, this should just return all layers.
',27),d=[n];function l(i,s,c,h,p,f){return t(),a("div",null,d)}const b=e(o,[["render",l]]);export{y as __pageData,b as default};
diff --git a/assets/api_modules_data_projEntry.md.65f0a74c.lean.js b/assets/api_modules_data_projEntry.md.c2b3a1aa.lean.js
similarity index 70%
rename from assets/api_modules_data_projEntry.md.65f0a74c.lean.js
rename to assets/api_modules_data_projEntry.md.c2b3a1aa.lean.js
index 30d57227..37927c4e 100644
--- a/assets/api_modules_data_projEntry.md.65f0a74c.lean.js
+++ b/assets/api_modules_data_projEntry.md.c2b3a1aa.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: data/projEntry","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/projEntry.md","lastUpdated":null}'),o={name:"api/modules/data/projEntry.md"},n=r("",27),d=[n];function l(i,s,c,h,p,f){return a(),t("div",null,d)}const b=e(o,[["render",l]]);export{y as __pageData,b as default};
+import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: data/projEntry","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/projEntry.md","lastUpdated":null}'),o={name:"api/modules/data/projEntry.md"},n=r("",27),d=[n];function l(i,s,c,h,p,f){return t(),a("div",null,d)}const b=e(o,[["render",l]]);export{y as __pageData,b as default};
diff --git a/assets/api_modules_data_themes.md.f07be1bf.js b/assets/api_modules_data_themes.md.0c2d9c86.js
similarity index 95%
rename from assets/api_modules_data_themes.md.f07be1bf.js
rename to assets/api_modules_data_themes.md.0c2d9c86.js
index 90082255..5897ed84 100644
--- a/assets/api_modules_data_themes.md.f07be1bf.js
+++ b/assets/api_modules_data_themes.md.0c2d9c86.js
@@ -1 +1 @@
-import{_ as t,c as e,o as a,N as d}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: data/themes","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/themes.md","lastUpdated":null}'),l={name:"api/modules/data/themes.md"},o=d('
An object representing a theme the player can use to change the look of the game.
Name
Type
Description
floatingTabs
boolean
Whether or not tabs should "float" in the center of their container.
mergeAdjacent
boolean
Whether or not adjacent features should merge together - removing the margin between them, and only applying the border radius to the first and last elements in the row or column.
showPin
boolean
Whether or not to show a pin icon on pinned tooltips.
',28),r=[o];function n(s,i,c,h,f,g){return a(),e("div",null,r)}const b=t(l,[["render",n]]);export{u as __pageData,b as default};
+import{_ as t,c as e,o as a,N as d}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: data/themes","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/themes.md","lastUpdated":null}'),l={name:"api/modules/data/themes.md"},o=d('
An object representing a theme the player can use to change the look of the game.
Name
Type
Description
floatingTabs
boolean
Whether or not tabs should "float" in the center of their container.
mergeAdjacent
boolean
Whether or not adjacent features should merge together - removing the margin between them, and only applying the border radius to the first and last elements in the row or column.
showPin
boolean
Whether or not to show a pin icon on pinned tooltips.
',28),r=[o];function n(s,i,c,h,f,g){return a(),e("div",null,r)}const y=t(l,[["render",n]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_data_themes.md.f07be1bf.lean.js b/assets/api_modules_data_themes.md.0c2d9c86.lean.js
similarity index 75%
rename from assets/api_modules_data_themes.md.f07be1bf.lean.js
rename to assets/api_modules_data_themes.md.0c2d9c86.lean.js
index 967cd168..3da29ce1 100644
--- a/assets/api_modules_data_themes.md.f07be1bf.lean.js
+++ b/assets/api_modules_data_themes.md.0c2d9c86.lean.js
@@ -1 +1 @@
-import{_ as t,c as e,o as a,N as d}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: data/themes","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/themes.md","lastUpdated":null}'),l={name:"api/modules/data/themes.md"},o=d("",28),r=[o];function n(s,i,c,h,f,g){return a(),e("div",null,r)}const b=t(l,[["render",n]]);export{u as __pageData,b as default};
+import{_ as t,c as e,o as a,N as d}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: data/themes","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/data/themes.md","lastUpdated":null}'),l={name:"api/modules/data/themes.md"},o=d("",28),r=[o];function n(s,i,c,h,f,g){return a(),e("div",null,r)}const y=t(l,[["render",n]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_features_achievement.md.e19ffa90.js b/assets/api_modules_features_achievement.md.bf6cff9a.js
similarity index 96%
rename from assets/api_modules_features_achievement.md.e19ffa90.js
rename to assets/api_modules_features_achievement.md.bf6cff9a.js
index fdd71aef..63e60632 100644
--- a/assets/api_modules_features_achievement.md.e19ffa90.js
+++ b/assets/api_modules_features_achievement.md.bf6cff9a.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/achievements/achievement","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/achievement.md","lastUpdated":null}'),d={name:"api/modules/features/achievement.md"},c=o('
',58),l=[c];function n(i,r,s,h,p,f){return a(),t("div",null,l)}const g=e(d,[["render",n]]);export{u as __pageData,g as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/achievements/achievement","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/achievement.md","lastUpdated":null}'),c={name:"api/modules/features/achievement.md"},d=o('
',58),l=[d];function n(i,r,s,h,p,f){return a(),t("div",null,l)}const g=e(c,[["render",n]]);export{u as __pageData,g as default};
diff --git a/assets/api_modules_features_achievement.md.e19ffa90.lean.js b/assets/api_modules_features_achievement.md.bf6cff9a.lean.js
similarity index 58%
rename from assets/api_modules_features_achievement.md.e19ffa90.lean.js
rename to assets/api_modules_features_achievement.md.bf6cff9a.lean.js
index 3e275bcb..88bbc7fd 100644
--- a/assets/api_modules_features_achievement.md.e19ffa90.lean.js
+++ b/assets/api_modules_features_achievement.md.bf6cff9a.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/achievements/achievement","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/achievement.md","lastUpdated":null}'),d={name:"api/modules/features/achievement.md"},c=o("",58),l=[c];function n(i,r,s,h,p,f){return a(),t("div",null,l)}const g=e(d,[["render",n]]);export{u as __pageData,g as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/achievements/achievement","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/achievement.md","lastUpdated":null}'),c={name:"api/modules/features/achievement.md"},d=o("",58),l=[d];function n(i,r,s,h,p,f){return a(),t("div",null,l)}const g=e(c,[["render",n]]);export{u as __pageData,g as default};
diff --git a/assets/api_modules_features_action.md.57ac6d70.js b/assets/api_modules_features_action.md.d13c2982.js
similarity index 97%
rename from assets/api_modules_features_action.md.57ac6d70.js
rename to assets/api_modules_features_action.md.d13c2982.js
index 735ff04d..30552ca8 100644
--- a/assets/api_modules_features_action.md.57ac6d70.js
+++ b/assets/api_modules_features_action.md.d13c2982.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/action","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/action.md","lastUpdated":null}'),c={name:"api/modules/features/action.md"},d=a('
',47),l=[d];function i(r,n,s,h,f,p){return o(),t("div",null,l)}const g=e(c,[["render",i]]);export{b as __pageData,g as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/action","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/action.md","lastUpdated":null}'),c={name:"api/modules/features/action.md"},d=a('
',47),l=[d];function i(r,n,s,h,f,p){return o(),t("div",null,l)}const g=e(c,[["render",i]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_features_action.md.57ac6d70.lean.js b/assets/api_modules_features_action.md.d13c2982.lean.js
similarity index 100%
rename from assets/api_modules_features_action.md.57ac6d70.lean.js
rename to assets/api_modules_features_action.md.d13c2982.lean.js
diff --git a/assets/api_modules_features_bar.md.6715e91d.js b/assets/api_modules_features_bar.md.af2b0e42.js
similarity index 96%
rename from assets/api_modules_features_bar.md.6715e91d.js
rename to assets/api_modules_features_bar.md.af2b0e42.js
index a0be32e3..36e2b776 100644
--- a/assets/api_modules_features_bar.md.6715e91d.js
+++ b/assets/api_modules_features_bar.md.af2b0e42.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/bars/bar","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/bar.md","lastUpdated":null}'),r={name:"api/modules/features/bar.md"},d=o('
',51),l=[d];function c(s,i,n,p,f,b){return a(),t("div",null,l)}const y=e(r,[["render",c]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/bars/bar","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/bar.md","lastUpdated":null}'),r={name:"api/modules/features/bar.md"},d=o('
',51),l=[d];function c(s,i,n,p,f,h){return a(),t("div",null,l)}const y=e(r,[["render",c]]);export{b as __pageData,y as default};
diff --git a/assets/api_modules_features_bar.md.6715e91d.lean.js b/assets/api_modules_features_bar.md.af2b0e42.lean.js
similarity index 59%
rename from assets/api_modules_features_bar.md.6715e91d.lean.js
rename to assets/api_modules_features_bar.md.af2b0e42.lean.js
index f0b0b2d7..afe05e3d 100644
--- a/assets/api_modules_features_bar.md.6715e91d.lean.js
+++ b/assets/api_modules_features_bar.md.af2b0e42.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/bars/bar","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/bar.md","lastUpdated":null}'),r={name:"api/modules/features/bar.md"},d=o("",51),l=[d];function c(s,i,n,p,f,b){return a(),t("div",null,l)}const y=e(r,[["render",c]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/bars/bar","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/bar.md","lastUpdated":null}'),r={name:"api/modules/features/bar.md"},d=o("",51),l=[d];function c(s,i,n,p,f,h){return a(),t("div",null,l)}const y=e(r,[["render",c]]);export{b as __pageData,y as default};
diff --git a/assets/api_modules_features_board.md.daf85c69.js b/assets/api_modules_features_board.md.cbded4a2.js
similarity index 98%
rename from assets/api_modules_features_board.md.daf85c69.js
rename to assets/api_modules_features_board.md.cbded4a2.js
index ad98aa46..236e2d40 100644
--- a/assets/api_modules_features_board.md.daf85c69.js
+++ b/assets/api_modules_features_board.md.cbded4a2.js
@@ -1 +1 @@
-import{_ as t,c as e,o as d,N as o}from"./chunks/framework.0799945b.js";const x=JSON.parse('{"title":"Module: features/boards/board","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/board.md","lastUpdated":null}'),l={name:"api/modules/features/board.md"},a=o('
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
A type representing a computable value for a node on the board. Used for node types to return different values based on the given node and the state of the board.
',188),r=[a];function c(n,i,s,f,g,y){return d(),e("div",null,r)}const b=t(l,[["render",c]]);export{x as __pageData,b as default};
+import{_ as t,c as e,o as d,N as o}from"./chunks/framework.0799945b.js";const x=JSON.parse('{"title":"Module: features/boards/board","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/board.md","lastUpdated":null}'),l={name:"api/modules/features/board.md"},a=o('
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
A type representing a computable value for a node on the board. Used for node types to return different values based on the given node and the state of the board.
',188),r=[a];function c(n,i,s,f,g,y){return d(),e("div",null,r)}const b=t(l,[["render",c]]);export{x as __pageData,b as default};
diff --git a/assets/api_modules_features_board.md.daf85c69.lean.js b/assets/api_modules_features_board.md.cbded4a2.lean.js
similarity index 100%
rename from assets/api_modules_features_board.md.daf85c69.lean.js
rename to assets/api_modules_features_board.md.cbded4a2.lean.js
diff --git a/assets/api_modules_features_challenge.md.61992126.js b/assets/api_modules_features_challenge.md.2eb0f36d.js
similarity index 97%
rename from assets/api_modules_features_challenge.md.61992126.js
rename to assets/api_modules_features_challenge.md.2eb0f36d.js
index 4297a787..daadb023 100644
--- a/assets/api_modules_features_challenge.md.61992126.js
+++ b/assets/api_modules_features_challenge.md.2eb0f36d.js
@@ -1 +1 @@
-import{_ as e,c as t,o as l,N as a}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/challenges/challenge","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/challenge.md","lastUpdated":null}'),o={name:"api/modules/features/challenge.md"},c=a('
Whether or not completing this challenge should grant multiple completions if requirements met. Requires requirements to be a requirement or array of requirements with Requirement.canMaximize true.
onComplete?
VoidFunction
A function that is called when the challenge is completed.
onEnter?
VoidFunction
A function that is called when the challenge is entered.
onExit?
VoidFunction
A function that is called when the challenge is exited.
Utility for taking an array of challenges where only one may be active at a time, and giving a ref to the one currently active (or null if none are active)
',81),d=[c];function n(r,i,s,h,g,f){return l(),t("div",null,d)}const y=e(o,[["render",n]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as l,N as a}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/challenges/challenge","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/challenge.md","lastUpdated":null}'),o={name:"api/modules/features/challenge.md"},c=a('
Whether or not completing this challenge should grant multiple completions if requirements met. Requires requirements to be a requirement or array of requirements with Requirement.canMaximize true.
onComplete?
VoidFunction
A function that is called when the challenge is completed.
onEnter?
VoidFunction
A function that is called when the challenge is entered.
onExit?
VoidFunction
A function that is called when the challenge is exited.
Utility for taking an array of challenges where only one may be active at a time, and giving a ref to the one currently active (or null if none are active)
',81),d=[c];function n(r,i,s,h,g,f){return l(),t("div",null,d)}const y=e(o,[["render",n]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_features_challenge.md.61992126.lean.js b/assets/api_modules_features_challenge.md.2eb0f36d.lean.js
similarity index 100%
rename from assets/api_modules_features_challenge.md.61992126.lean.js
rename to assets/api_modules_features_challenge.md.2eb0f36d.lean.js
diff --git a/assets/api_modules_features_clickable.md.6631e1cc.js b/assets/api_modules_features_clickable.md.5de98f55.js
similarity index 97%
rename from assets/api_modules_features_clickable.md.6631e1cc.js
rename to assets/api_modules_features_clickable.md.5de98f55.js
index 8c8daee0..99796667 100644
--- a/assets/api_modules_features_clickable.md.6631e1cc.js
+++ b/assets/api_modules_features_clickable.md.5de98f55.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as l}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/clickables/clickable","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/clickable.md","lastUpdated":null}'),c={name:"api/modules/features/clickable.md"},o=l('
',61),d=[o];function i(r,s,n,b,h,f){return a(),t("div",null,d)}const y=e(c,[["render",i]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as a,N as l}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/clickables/clickable","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/clickable.md","lastUpdated":null}'),c={name:"api/modules/features/clickable.md"},o=l('
',61),d=[o];function i(r,s,n,b,h,f){return a(),t("div",null,d)}const y=e(c,[["render",i]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_features_clickable.md.6631e1cc.lean.js b/assets/api_modules_features_clickable.md.5de98f55.lean.js
similarity index 100%
rename from assets/api_modules_features_clickable.md.6631e1cc.lean.js
rename to assets/api_modules_features_clickable.md.5de98f55.lean.js
diff --git a/assets/api_modules_features_conversion.md.3fe5ca87.js b/assets/api_modules_features_conversion.md.61b07407.js
similarity index 97%
rename from assets/api_modules_features_conversion.md.3fe5ca87.js
rename to assets/api_modules_features_conversion.md.61b07407.js
index f06c0960..6644255a 100644
--- a/assets/api_modules_features_conversion.md.3fe5ca87.js
+++ b/assets/api_modules_features_conversion.md.61b07407.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/conversion","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/conversion.md","lastUpdated":null}'),r={name:"api/modules/features/conversion.md"},n=a('
The absolute amount the output resource will be changed by. Typically this will be set for you in a conversion constructor. This will differ from currentGain in the cases where the conversion isn't just adding the converted amount to the output resource.
The amount of the input resource currently being required in order to produce the currentGain. That is, if it went below this value then currentGain would decrease. Typically this will be set for you in a conversion constructor.
The formula used to determine how much gainResource should be earned by this converting. The passed value will be a Formula representing the baseResource variable.
A callback that happens after a conversion has been completed. Receives the amount gained via conversion. This will not be called whenever using currentGain without calling convert (e.g. passive generation)
Lazily creates a conversion with the given options. You typically shouldn't use this function directly. Instead use one of the other conversion constructors, which will then call this.
Creates a conversion that simply adds to the gainResource amount upon converting. This is similar to the behavior of "normal" layers in The Modding Tree. This is equivalent to just calling createConversion directly.
Creates a conversion that will replace the gainResource amount with the new amount upon converting. This is similar to the behavior of "static" layers in The Modding Tree.
This will automatically increase the value of conversion.gainResource without lowering the value of the input resource. It will by default perform 100% of a conversion's currentGain per second. If you use a ref for the rate you can set it's value to 0 when passive generation should be disabled.
',77),c=[n];function i(d,s,l,u,h,f){return o(),t("div",null,c)}const m=e(r,[["render",i]]);export{b as __pageData,m as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/conversion","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/conversion.md","lastUpdated":null}'),r={name:"api/modules/features/conversion.md"},n=a('
The absolute amount the output resource will be changed by. Typically this will be set for you in a conversion constructor. This will differ from currentGain in the cases where the conversion isn't just adding the converted amount to the output resource.
The amount of the input resource currently being required in order to produce the currentGain. That is, if it went below this value then currentGain would decrease. Typically this will be set for you in a conversion constructor.
The formula used to determine how much gainResource should be earned by this converting. The passed value will be a Formula representing the baseResource variable.
A callback that happens after a conversion has been completed. Receives the amount gained via conversion. This will not be called whenever using currentGain without calling convert (e.g. passive generation)
Lazily creates a conversion with the given options. You typically shouldn't use this function directly. Instead use one of the other conversion constructors, which will then call this.
Creates a conversion that simply adds to the gainResource amount upon converting. This is similar to the behavior of "normal" layers in The Modding Tree. This is equivalent to just calling createConversion directly.
Creates a conversion that will replace the gainResource amount with the new amount upon converting. This is similar to the behavior of "static" layers in The Modding Tree.
This will automatically increase the value of conversion.gainResource without lowering the value of the input resource. It will by default perform 100% of a conversion's currentGain per second. If you use a ref for the rate you can set it's value to 0 when passive generation should be disabled.
',77),c=[n];function i(d,s,l,u,h,f){return o(),t("div",null,c)}const m=e(r,[["render",i]]);export{b as __pageData,m as default};
diff --git a/assets/api_modules_features_conversion.md.3fe5ca87.lean.js b/assets/api_modules_features_conversion.md.61b07407.lean.js
similarity index 100%
rename from assets/api_modules_features_conversion.md.3fe5ca87.lean.js
rename to assets/api_modules_features_conversion.md.61b07407.lean.js
diff --git a/assets/api_modules_features_feature.md.cea7f1eb.js b/assets/api_modules_features_feature.md.65109bb8.js
similarity index 94%
rename from assets/api_modules_features_feature.md.cea7f1eb.js
rename to assets/api_modules_features_feature.md.65109bb8.js
index 98b5a316..f9b0b33b 100644
--- a/assets/api_modules_features_feature.md.cea7f1eb.js
+++ b/assets/api_modules_features_feature.md.65109bb8.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/feature","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/feature.md","lastUpdated":null}'),o={name:"api/modules/features/feature.md"},n=r('
Utility function for a function that returns an object of a given type, with "this" bound to what the type will eventually be processed into. Intended for making lazily evaluated objects.
Any value that can be passed into an HTML element's style attribute. Note that Profectus uses its own StyleValue and CSSProperties that are extended, in order to have additional properties added to them, such as variable CSS variables.
Traverses an object and returns all features that are not any of the given types. Features are any object with a "type" property that has a symbol value.
Gets a unique ID to give to each feature, used for any sort of system that needs to identify elements in the DOM rather than references to the feature itself. (For example, branches) IDs are guaranteed unique, but NOT persistent - they likely will change between updates.
Takes a function and marks it as JSX so it won't get auto-wrapped into a ComputedRef. The function may also return empty string as empty JSX tags cause issues.
',136),d=[n];function i(l,s,c,h,f,u){return a(),t("div",null,d)}const y=e(o,[["render",i]]);export{b as __pageData,y as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/feature","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/feature.md","lastUpdated":null}'),o={name:"api/modules/features/feature.md"},n=r('
Utility function for a function that returns an object of a given type, with "this" bound to what the type will eventually be processed into. Intended for making lazily evaluated objects.
Any value that can be passed into an HTML element's style attribute. Note that Profectus uses its own StyleValue and CSSProperties that are extended, in order to have additional properties added to them, such as variable CSS variables.
Traverses an object and returns all features that are not any of the given types. Features are any object with a "type" property that has a symbol value.
Gets a unique ID to give to each feature, used for any sort of system that needs to identify elements in the DOM rather than references to the feature itself. (For example, branches) IDs are guaranteed unique, but NOT persistent - they likely will change between updates.
Takes a function and marks it as JSX so it won't get auto-wrapped into a ComputedRef. The function may also return empty string as empty JSX tags cause issues.
',136),d=[n];function i(l,s,c,h,f,u){return a(),t("div",null,d)}const y=e(o,[["render",i]]);export{b as __pageData,y as default};
diff --git a/assets/api_modules_features_feature.md.cea7f1eb.lean.js b/assets/api_modules_features_feature.md.65109bb8.lean.js
similarity index 100%
rename from assets/api_modules_features_feature.md.cea7f1eb.lean.js
rename to assets/api_modules_features_feature.md.65109bb8.lean.js
diff --git a/assets/api_modules_features_grid.md.268e4fcb.js b/assets/api_modules_features_grid.md.cd670732.js
similarity index 97%
rename from assets/api_modules_features_grid.md.268e4fcb.js
rename to assets/api_modules_features_grid.md.cd670732.js
index 64825b59..66931475 100644
--- a/assets/api_modules_features_grid.md.268e4fcb.js
+++ b/assets/api_modules_features_grid.md.cd670732.js
@@ -1 +1 @@
-import{_ as e,c as t,o as d,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/grids/grid","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/grid.md","lastUpdated":null}'),a={name:"api/modules/features/grid.md"},l=o('
Represents a cell within a grid. These properties will typically be accessed via a cell proxy that calls functions on the grid to get the properties for a specific cell.
',71),r=[l];function i(c,s,n,g,f,h){return d(),t("div",null,r)}const y=e(a,[["render",i]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as d,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/grids/grid","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/grid.md","lastUpdated":null}'),a={name:"api/modules/features/grid.md"},l=o('
Represents a cell within a grid. These properties will typically be accessed via a cell proxy that calls functions on the grid to get the properties for a specific cell.
',71),r=[l];function c(i,s,n,g,f,h){return d(),t("div",null,r)}const y=e(a,[["render",c]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_features_grid.md.268e4fcb.lean.js b/assets/api_modules_features_grid.md.cd670732.lean.js
similarity index 73%
rename from assets/api_modules_features_grid.md.268e4fcb.lean.js
rename to assets/api_modules_features_grid.md.cd670732.lean.js
index 8e6bf5ba..50478221 100644
--- a/assets/api_modules_features_grid.md.268e4fcb.lean.js
+++ b/assets/api_modules_features_grid.md.cd670732.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as d,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/grids/grid","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/grid.md","lastUpdated":null}'),a={name:"api/modules/features/grid.md"},l=o("",71),r=[l];function i(c,s,n,g,f,h){return d(),t("div",null,r)}const y=e(a,[["render",i]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as d,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/grids/grid","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/grid.md","lastUpdated":null}'),a={name:"api/modules/features/grid.md"},l=o("",71),r=[l];function c(i,s,n,g,f,h){return d(),t("div",null,r)}const y=e(a,[["render",c]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_features_hotkey.md.331f5b10.js b/assets/api_modules_features_hotkey.md.6146eb5c.js
similarity index 94%
rename from assets/api_modules_features_hotkey.md.331f5b10.js
rename to assets/api_modules_features_hotkey.md.6146eb5c.js
index 690da946..664c2dd3 100644
--- a/assets/api_modules_features_hotkey.md.331f5b10.js
+++ b/assets/api_modules_features_hotkey.md.6146eb5c.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/hotkey","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/hotkey.md","lastUpdated":null}'),r={name:"api/modules/features/hotkey.md"},d=o('
',53),n=[d];function s(l,i,h,c,y,f){return a(),t("div",null,n)}const k=e(r,[["render",s]]);export{u as __pageData,k as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/hotkey","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/hotkey.md","lastUpdated":null}'),r={name:"api/modules/features/hotkey.md"},d=o('
',53),n=[d];function s(l,i,h,c,y,f){return a(),t("div",null,n)}const k=e(r,[["render",s]]);export{u as __pageData,k as default};
diff --git a/assets/api_modules_features_hotkey.md.331f5b10.lean.js b/assets/api_modules_features_hotkey.md.6146eb5c.lean.js
similarity index 100%
rename from assets/api_modules_features_hotkey.md.331f5b10.lean.js
rename to assets/api_modules_features_hotkey.md.6146eb5c.lean.js
diff --git a/assets/api_modules_features_infobox.md.99885ce3.js b/assets/api_modules_features_infobox.md.8301f57a.js
similarity index 96%
rename from assets/api_modules_features_infobox.md.99885ce3.js
rename to assets/api_modules_features_infobox.md.8301f57a.js
index d0361771..0e75f469 100644
--- a/assets/api_modules_features_infobox.md.99885ce3.js
+++ b/assets/api_modules_features_infobox.md.8301f57a.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/infoboxes/infobox","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/infobox.md","lastUpdated":null}'),l={name:"api/modules/features/infobox.md"},d=a('
',51),r=[d];function n(i,c,s,f,b,p){return o(),t("div",null,r)}const x=e(l,[["render",n]]);export{u as __pageData,x as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/infoboxes/infobox","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/infobox.md","lastUpdated":null}'),l={name:"api/modules/features/infobox.md"},d=a('
',51),r=[d];function n(i,c,s,f,b,p){return o(),t("div",null,r)}const x=e(l,[["render",n]]);export{u as __pageData,x as default};
diff --git a/assets/api_modules_features_infobox.md.99885ce3.lean.js b/assets/api_modules_features_infobox.md.8301f57a.lean.js
similarity index 100%
rename from assets/api_modules_features_infobox.md.99885ce3.lean.js
rename to assets/api_modules_features_infobox.md.8301f57a.lean.js
diff --git a/assets/api_modules_features_links.md.c8fd9429.js b/assets/api_modules_features_links.md.5299fc5a.js
similarity index 99%
rename from assets/api_modules_features_links.md.c8fd9429.js
rename to assets/api_modules_features_links.md.5299fc5a.js
index 6b2b71a9..355aba1d 100644
--- a/assets/api_modules_features_links.md.c8fd9429.js
+++ b/assets/api_modules_features_links.md.5299fc5a.js
@@ -1 +1 @@
-import{_ as t,c as e,o as d,N as l}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Module: features/links/links","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/links.md","lastUpdated":null}'),o={name:"api/modules/features/links.md"},a=l('
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
',61),r=[a];function n(i,c,s,g,f,y){return d(),e("div",null,r)}const u=t(o,[["render",n]]);export{h as __pageData,u as default};
+import{_ as t,c as e,o as d,N as l}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Module: features/links/links","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/links.md","lastUpdated":null}'),o={name:"api/modules/features/links.md"},a=l('
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
',61),r=[a];function n(i,c,s,g,f,y){return d(),e("div",null,r)}const u=t(o,[["render",n]]);export{h as __pageData,u as default};
diff --git a/assets/api_modules_features_links.md.c8fd9429.lean.js b/assets/api_modules_features_links.md.5299fc5a.lean.js
similarity index 100%
rename from assets/api_modules_features_links.md.c8fd9429.lean.js
rename to assets/api_modules_features_links.md.5299fc5a.lean.js
diff --git a/assets/api_modules_features_particles.md.763b2b91.js b/assets/api_modules_features_particles.md.83fdde2e.js
similarity index 97%
rename from assets/api_modules_features_particles.md.763b2b91.js
rename to assets/api_modules_features_particles.md.83fdde2e.js
index beff74a2..d9e0a485 100644
--- a/assets/api_modules_features_particles.md.763b2b91.js
+++ b/assets/api_modules_features_particles.md.83fdde2e.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Module: features/particles/particles","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/particles.md","lastUpdated":null}'),l={name:"api/modules/features/particles.md"},o=r('
An object that represents a feature that display particle effects on the screen. The config should typically be gotten by designing the effect using the online particle effect editor and passing it into the upgradeConfig from @pixi/particle-emitter.
',51),i=[o];function s(c,d,n,p,h,f){return a(),t("div",null,i)}const y=e(l,[["render",s]]);export{g as __pageData,y as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Module: features/particles/particles","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/particles.md","lastUpdated":null}'),l={name:"api/modules/features/particles.md"},o=r('
An object that represents a feature that display particle effects on the screen. The config should typically be gotten by designing the effect using the online particle effect editor and passing it into the upgradeConfig from @pixi/particle-emitter.
',51),i=[o];function s(c,d,n,p,h,f){return a(),t("div",null,i)}const y=e(l,[["render",s]]);export{g as __pageData,y as default};
diff --git a/assets/api_modules_features_particles.md.763b2b91.lean.js b/assets/api_modules_features_particles.md.83fdde2e.lean.js
similarity index 100%
rename from assets/api_modules_features_particles.md.763b2b91.lean.js
rename to assets/api_modules_features_particles.md.83fdde2e.lean.js
diff --git a/assets/api_modules_features_repeatable.md.9088973d.js b/assets/api_modules_features_repeatable.md.3d77d9ba.js
similarity index 97%
rename from assets/api_modules_features_repeatable.md.9088973d.js
rename to assets/api_modules_features_repeatable.md.3d77d9ba.js
index 95b0afcf..ac031266 100644
--- a/assets/api_modules_features_repeatable.md.9088973d.js
+++ b/assets/api_modules_features_repeatable.md.3d77d9ba.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/repeatable","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/repeatable.md","lastUpdated":null}'),l={name:"api/modules/features/repeatable.md"},r=o('
Whether or not clicking this repeatable should attempt to maximize amount based on the requirements met. Requires requirements to be a requirement or array of requirements with Requirement.canMaximize true.
',53),d=[r];function c(i,s,n,p,b,f){return a(),t("div",null,d)}const m=e(l,[["render",c]]);export{u as __pageData,m as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/repeatable","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/repeatable.md","lastUpdated":null}'),l={name:"api/modules/features/repeatable.md"},r=o('
Whether or not clicking this repeatable should attempt to maximize amount based on the requirements met. Requires requirements to be a requirement or array of requirements with Requirement.canMaximize true.
',53),d=[r];function c(i,s,n,p,b,f){return a(),t("div",null,d)}const m=e(l,[["render",c]]);export{u as __pageData,m as default};
diff --git a/assets/api_modules_features_repeatable.md.9088973d.lean.js b/assets/api_modules_features_repeatable.md.3d77d9ba.lean.js
similarity index 100%
rename from assets/api_modules_features_repeatable.md.9088973d.lean.js
rename to assets/api_modules_features_repeatable.md.3d77d9ba.lean.js
diff --git a/assets/api_modules_features_reset.md.d42e8c0d.js b/assets/api_modules_features_reset.md.b1a80cce.js
similarity index 95%
rename from assets/api_modules_features_reset.md.d42e8c0d.js
rename to assets/api_modules_features_reset.md.b1a80cce.js
index ed405444..28bc0c3a 100644
--- a/assets/api_modules_features_reset.md.d42e8c0d.js
+++ b/assets/api_modules_features_reset.md.b1a80cce.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/reset","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/reset.md","lastUpdated":null}'),s={name:"api/modules/features/reset.md"},o=r('
',57),d=[o];function i(n,l,c,h,f,p){return a(),t("div",null,d)}const g=e(s,[["render",i]]);export{b as __pageData,g as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/reset","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/reset.md","lastUpdated":null}'),s={name:"api/modules/features/reset.md"},o=r('
',57),d=[o];function i(n,l,c,h,f,p){return a(),t("div",null,d)}const g=e(s,[["render",i]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_features_reset.md.d42e8c0d.lean.js b/assets/api_modules_features_reset.md.b1a80cce.lean.js
similarity index 100%
rename from assets/api_modules_features_reset.md.d42e8c0d.lean.js
rename to assets/api_modules_features_reset.md.b1a80cce.lean.js
diff --git a/assets/api_modules_features_resource.md.21d7a628.js b/assets/api_modules_features_resource.md.e6ee26a1.js
similarity index 96%
rename from assets/api_modules_features_resource.md.21d7a628.js
rename to assets/api_modules_features_resource.md.e6ee26a1.js
index 718fdcc9..bb08ee41 100644
--- a/assets/api_modules_features_resource.md.21d7a628.js
+++ b/assets/api_modules_features_resource.md.e6ee26a1.js
@@ -1 +1 @@
-import{_ as e,c as t,o as r,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/resources/resource","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/resource.md","lastUpdated":null}'),o={name:"api/modules/features/resource.md"},s=a('
Returns a reference to the amount of resource being gained in terms of orders of magnitude per second, calcualted over the last tick. Useful for situations where the gain rate is increasing very rapidly.
',84),d=[s];function c(l,n,i,u,h,f){return r(),t("div",null,d)}const g=e(o,[["render",c]]);export{b as __pageData,g as default};
+import{_ as e,c as t,o as r,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/resources/resource","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/resource.md","lastUpdated":null}'),o={name:"api/modules/features/resource.md"},s=a('
Returns a reference to the amount of resource being gained in terms of orders of magnitude per second, calcualted over the last tick. Useful for situations where the gain rate is increasing very rapidly.
',84),d=[s];function c(l,n,i,u,h,f){return r(),t("div",null,d)}const g=e(o,[["render",c]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_features_resource.md.21d7a628.lean.js b/assets/api_modules_features_resource.md.e6ee26a1.lean.js
similarity index 100%
rename from assets/api_modules_features_resource.md.21d7a628.lean.js
rename to assets/api_modules_features_resource.md.e6ee26a1.lean.js
diff --git a/assets/api_modules_features_tabs_tab.md.8c9c4f59.js b/assets/api_modules_features_tabs_tab.md.e5867e59.js
similarity index 94%
rename from assets/api_modules_features_tabs_tab.md.8c9c4f59.js
rename to assets/api_modules_features_tabs_tab.md.e5867e59.js
index 7b345fc7..d3849e43 100644
--- a/assets/api_modules_features_tabs_tab.md.8c9c4f59.js
+++ b/assets/api_modules_features_tabs_tab.md.e5867e59.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/tabs/tab","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tabs/tab.md","lastUpdated":null}'),r={name:"api/modules/features/tabs/tab.md"},d=o('
',49),s=[d];function l(n,i,c,b,h,f){return a(),t("div",null,s)}const y=e(r,[["render",l]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/tabs/tab","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tabs/tab.md","lastUpdated":null}'),r={name:"api/modules/features/tabs/tab.md"},d=o('
',49),s=[d];function l(n,c,i,b,h,f){return a(),t("div",null,s)}const y=e(r,[["render",l]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_features_tabs_tab.md.8c9c4f59.lean.js b/assets/api_modules_features_tabs_tab.md.e5867e59.lean.js
similarity index 85%
rename from assets/api_modules_features_tabs_tab.md.8c9c4f59.lean.js
rename to assets/api_modules_features_tabs_tab.md.e5867e59.lean.js
index 6936ff2a..d19cb9a2 100644
--- a/assets/api_modules_features_tabs_tab.md.8c9c4f59.lean.js
+++ b/assets/api_modules_features_tabs_tab.md.e5867e59.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/tabs/tab","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tabs/tab.md","lastUpdated":null}'),r={name:"api/modules/features/tabs/tab.md"},d=o("",49),s=[d];function l(n,i,c,b,h,f){return a(),t("div",null,s)}const y=e(r,[["render",l]]);export{u as __pageData,y as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: features/tabs/tab","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tabs/tab.md","lastUpdated":null}'),r={name:"api/modules/features/tabs/tab.md"},d=o("",49),s=[d];function l(n,c,i,b,h,f){return a(),t("div",null,s)}const y=e(r,[["render",l]]);export{u as __pageData,y as default};
diff --git a/assets/api_modules_features_tabs_tabFamily.md.a39b0255.js b/assets/api_modules_features_tabs_tabFamily.md.f353d899.js
similarity index 96%
rename from assets/api_modules_features_tabs_tabFamily.md.a39b0255.js
rename to assets/api_modules_features_tabs_tabFamily.md.f353d899.js
index 4c37c348..6caa0333 100644
--- a/assets/api_modules_features_tabs_tabFamily.md.a39b0255.js
+++ b/assets/api_modules_features_tabs_tabFamily.md.f353d899.js
@@ -1 +1 @@
-import{_ as t,c as e,o as a,N as o}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: features/tabs/tabFamily","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tabs/tabFamily.md","lastUpdated":null}'),l={name:"api/modules/features/tabs/tabFamily.md"},r=o('
',85),d=[r];function i(c,n,s,b,f,h){return a(),e("div",null,d)}const u=t(l,[["render",i]]);export{y as __pageData,u as default};
+import{_ as t,c as e,o as a,N as o}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: features/tabs/tabFamily","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tabs/tabFamily.md","lastUpdated":null}'),l={name:"api/modules/features/tabs/tabFamily.md"},r=o('
',85),d=[r];function i(c,n,s,b,f,h){return a(),e("div",null,d)}const u=t(l,[["render",i]]);export{y as __pageData,u as default};
diff --git a/assets/api_modules_features_tabs_tabFamily.md.a39b0255.lean.js b/assets/api_modules_features_tabs_tabFamily.md.f353d899.lean.js
similarity index 100%
rename from assets/api_modules_features_tabs_tabFamily.md.a39b0255.lean.js
rename to assets/api_modules_features_tabs_tabFamily.md.f353d899.lean.js
diff --git a/assets/api_modules_features_tooltip.md.3545844d.js b/assets/api_modules_features_tooltip.md.48851464.js
similarity index 95%
rename from assets/api_modules_features_tooltip.md.3545844d.js
rename to assets/api_modules_features_tooltip.md.48851464.js
index eef7897f..bbfc9520 100644
--- a/assets/api_modules_features_tooltip.md.3545844d.js
+++ b/assets/api_modules_features_tooltip.md.48851464.js
@@ -1 +1 @@
-import{_ as t,c as e,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/tooltips/tooltip","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tooltip.md","lastUpdated":null}'),l={name:"api/modules/features/tooltip.md"},d=a('
',47),i=[d];function r(c,n,s,p,h,f){return o(),e("div",null,i)}const g=t(l,[["render",r]]);export{b as __pageData,g as default};
+import{_ as t,c as e,o,N as a}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Module: features/tooltips/tooltip","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tooltip.md","lastUpdated":null}'),l={name:"api/modules/features/tooltip.md"},d=a('
',47),i=[d];function r(c,n,s,p,h,f){return o(),e("div",null,i)}const b=t(l,[["render",r]]);export{g as __pageData,b as default};
diff --git a/assets/api_modules_features_tooltip.md.3545844d.lean.js b/assets/api_modules_features_tooltip.md.48851464.lean.js
similarity index 57%
rename from assets/api_modules_features_tooltip.md.3545844d.lean.js
rename to assets/api_modules_features_tooltip.md.48851464.lean.js
index b35d5ee1..a926197f 100644
--- a/assets/api_modules_features_tooltip.md.3545844d.lean.js
+++ b/assets/api_modules_features_tooltip.md.48851464.lean.js
@@ -1 +1 @@
-import{_ as t,c as e,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: features/tooltips/tooltip","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tooltip.md","lastUpdated":null}'),l={name:"api/modules/features/tooltip.md"},d=a("",47),i=[d];function r(c,n,s,p,h,f){return o(),e("div",null,i)}const g=t(l,[["render",r]]);export{b as __pageData,g as default};
+import{_ as t,c as e,o,N as a}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Module: features/tooltips/tooltip","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tooltip.md","lastUpdated":null}'),l={name:"api/modules/features/tooltip.md"},d=a("",47),i=[d];function r(c,n,s,p,h,f){return o(),e("div",null,i)}const b=t(l,[["render",r]]);export{g as __pageData,b as default};
diff --git a/assets/api_modules_features_tree.md.ea396790.js b/assets/api_modules_features_tree.md.43e7ab64.js
similarity index 98%
rename from assets/api_modules_features_tree.md.ea396790.js
rename to assets/api_modules_features_tree.md.43e7ab64.js
index 9472cca4..c30c20b1 100644
--- a/assets/api_modules_features_tree.md.ea396790.js
+++ b/assets/api_modules_features_tree.md.43e7ab64.js
@@ -1 +1 @@
-import{_ as t,c as e,o as d,N as l}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Module: features/trees/tree","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tree.md","lastUpdated":null}'),o={name:"api/modules/features/tree.md"},r=l('
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
An object that represents a feature that is a tree of nodes with branches between them. Contains support for reset mechanics that can propagate through the tree.
Utility for creating a tooltip for a tree node that displays a resource-based unlock requirement, and after unlock shows the amount of another resource. It sounds oddly specific, but comes up a lot.
',158),a=[r];function c(n,i,s,g,f,y){return d(),e("div",null,a)}const u=t(o,[["render",c]]);export{h as __pageData,u as default};
+import{_ as t,c as e,o as d,N as l}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Module: features/trees/tree","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/tree.md","lastUpdated":null}'),o={name:"api/modules/features/tree.md"},r=l('
Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application.
aria-atomic?
Booleanish
Indicates whether assistive technologies will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute.
aria-autocomplete?
"none" | "inline" | "list" | "both"
Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made.
aria-busy?
Booleanish
Indicates an element is being modified and that assistive technologies MAY want to wait until the modifications are complete before exposing them to the user.
aria-checked?
Booleanish | "mixed"
Indicates the current "checked" state of checkboxes, radio buttons, and other widgets. See - aria-pressed - aria-selected.
aria-colcount?
Numberish
Defines the total number of columns in a table, grid, or treegrid. See aria-colindex.
aria-colindex?
Numberish
Defines an element's column index or position with respect to the total number of columns within a table, grid, or treegrid. See - aria-colcount - aria-colspan.
aria-colspan?
Numberish
Defines the number of columns spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-colindex - aria-rowspan.
aria-controls?
string
Identifies the element (or elements) whose contents or presence are controlled by the current element. See aria-owns.
Indicates what functions can be performed when a dragged object is released on the drop target. Deprecated in ARIA 1.1
aria-errormessage?
string
Identifies the element that provides an error message for the object. See - aria-invalid - aria-describedby.
aria-expanded?
Booleanish
Indicates whether the element, or another grouping element it controls, is currently expanded or collapsed.
aria-flowto?
string
Identifies the next element (or elements) in an alternate reading order of content which, at the user's discretion, allows assistive technology to override the general default of reading in document source order.
aria-grabbed?
Booleanish
Indicates an element's "grabbed" state in a drag-and-drop operation. Deprecated in ARIA 1.1
Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element.
aria-hidden?
Booleanish
Indicates whether the element is exposed to an accessibility API. See aria-disabled.
aria-invalid?
Booleanish | "grammar" | "spelling"
Indicates the entered value does not conform to the format expected by the application. See aria-errormessage.
aria-keyshortcuts?
string
Indicates keyboard shortcuts that an author has implemented to activate or give focus to an element.
aria-label?
string
Defines a string value that labels the current element. See aria-labelledby.
aria-labelledby?
string
Identifies the element (or elements) that labels the current element. See aria-describedby.
aria-level?
Numberish
Defines the hierarchical level of an element within a structure.
aria-live?
"off" | "assertive" | "polite"
Indicates that an element will be updated, and describes the types of updates the user agents, assistive technologies, and user can expect from the live region.
aria-modal?
Booleanish
Indicates whether an element is modal when displayed.
aria-multiline?
Booleanish
Indicates whether a text box accepts multiple lines of input or only a single line.
aria-multiselectable?
Booleanish
Indicates that the user may select more than one item from the current selectable descendants.
aria-orientation?
"horizontal" | "vertical"
Indicates whether the element's orientation is horizontal, vertical, or unknown/ambiguous.
aria-owns?
string
Identifies an element (or elements) in order to define a visual, functional, or contextual parent/child relationship between DOM elements where the DOM hierarchy cannot be used to represent the relationship. See aria-controls.
aria-placeholder?
string
Defines a short hint (a word or short phrase) intended to aid the user with data entry when the control has no value. A hint could be a sample value or a brief description of the expected format.
aria-posinset?
Numberish
Defines an element's number or position in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-setsize.
aria-pressed?
Booleanish | "mixed"
Indicates the current "pressed" state of toggle buttons. See - aria-checked - aria-selected.
aria-readonly?
Booleanish
Indicates that the element is not editable, but is otherwise operable. See aria-disabled.
Indicates what notifications the user agent will trigger when the accessibility tree within a live region is modified. See aria-atomic.
aria-required?
Booleanish
Indicates that user input is required on the element before a form may be submitted.
aria-roledescription?
string
Defines a human-readable, author-localized description for the role of an element.
aria-rowcount?
Numberish
Defines the total number of rows in a table, grid, or treegrid. See aria-rowindex.
aria-rowindex?
Numberish
Defines an element's row index or position with respect to the total number of rows within a table, grid, or treegrid. See - aria-rowcount - aria-rowspan.
aria-rowspan?
Numberish
Defines the number of rows spanned by a cell or gridcell within a table, grid, or treegrid. See - aria-rowindex - aria-colspan.
aria-selected?
Booleanish
Indicates the current "selected" state of various widgets. See - aria-checked - aria-pressed.
aria-setsize?
Numberish
Defines the number of items in the current set of listitems or treeitems. Not required if all elements in the set are present in the DOM. See aria-posinset.
aria-sort?
"none" | "ascending" | "descending" | "other"
Indicates if items in a table or grid are sorted in ascending or descending order.
aria-valuemax?
Numberish
Defines the maximum allowed value for a range widget.
aria-valuemin?
Numberish
Defines the minimum allowed value for a range widget.
aria-valuenow?
Numberish
Defines the current value for a range widget. See aria-valuetext.
aria-valuetext?
string
Defines the human readable text alternative of aria-valuenow for a range widget.
An object that represents a feature that is a tree of nodes with branches between them. Contains support for reset mechanics that can propagate through the tree.
Utility for creating a tooltip for a tree node that displays a resource-based unlock requirement, and after unlock shows the amount of another resource. It sounds oddly specific, but comes up a lot.
',158),a=[r];function c(n,i,s,g,f,y){return d(),e("div",null,a)}const u=t(o,[["render",c]]);export{h as __pageData,u as default};
diff --git a/assets/api_modules_features_tree.md.ea396790.lean.js b/assets/api_modules_features_tree.md.43e7ab64.lean.js
similarity index 100%
rename from assets/api_modules_features_tree.md.ea396790.lean.js
rename to assets/api_modules_features_tree.md.43e7ab64.lean.js
diff --git a/assets/api_modules_features_upgrade.md.dcbc95f6.js b/assets/api_modules_features_upgrade.md.e9742306.js
similarity index 97%
rename from assets/api_modules_features_upgrade.md.dcbc95f6.js
rename to assets/api_modules_features_upgrade.md.e9742306.js
index 9b9847a5..aae3ff49 100644
--- a/assets/api_modules_features_upgrade.md.dcbc95f6.js
+++ b/assets/api_modules_features_upgrade.md.e9742306.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as d}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Module: features/upgrades/upgrade","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/upgrade.md","lastUpdated":null}'),r={name:"api/modules/features/upgrade.md"},o=d('
',61),l=[o];function c(s,n,i,p,u,g){return a(),t("div",null,l)}const y=e(r,[["render",c]]);export{f as __pageData,y as default};
+import{_ as e,c as t,o as a,N as d}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Module: features/upgrades/upgrade","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/features/upgrade.md","lastUpdated":null}'),r={name:"api/modules/features/upgrade.md"},o=d('
',61),l=[o];function c(s,n,i,p,u,g){return a(),t("div",null,l)}const y=e(r,[["render",c]]);export{f as __pageData,y as default};
diff --git a/assets/api_modules_features_upgrade.md.dcbc95f6.lean.js b/assets/api_modules_features_upgrade.md.e9742306.lean.js
similarity index 100%
rename from assets/api_modules_features_upgrade.md.dcbc95f6.lean.js
rename to assets/api_modules_features_upgrade.md.e9742306.lean.js
diff --git a/assets/api_modules_game_events.md.abe1fe7b.js b/assets/api_modules_game_events.md.b1ba4222.js
similarity index 93%
rename from assets/api_modules_game_events.md.abe1fe7b.js
rename to assets/api_modules_game_events.md.b1ba4222.js
index 55f05017..026ed82d 100644
--- a/assets/api_modules_game_events.md.abe1fe7b.js
+++ b/assets/api_modules_game_events.md.b1ba4222.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/events","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/events.md","lastUpdated":null}'),d={name:"api/modules/game/events.md"},l=o('
Using document.fonts.ready returns too early on firefox, so we use document.fonts.onloadingdone instead, which doesn't accept multiple listeners. This event fires when that callback is called.
Sent when constructing the Settings object. Use it to add default values for custom properties to the object. See features/features.setDefault for setting default values.
onLoad
VoidFunction
Sent whenever a save has finished loading. Happens when the page is opened and upon switching saves in the saves manager.
',15),n=[l];function s(r,c,i,g,f,h){return a(),t("div",null,n)}const p=e(d,[["render",s]]);export{b as __pageData,p as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: game/events","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/events.md","lastUpdated":null}'),d={name:"api/modules/game/events.md"},l=o('
Using document.fonts.ready returns too early on firefox, so we use document.fonts.onloadingdone instead, which doesn't accept multiple listeners. This event fires when that callback is called.
Sent when constructing the Settings object. Use it to add default values for custom properties to the object. See features/features.setDefault for setting default values.
onLoad
VoidFunction
Sent whenever a save has finished loading. Happens when the page is opened and upon switching saves in the saves manager.
',15),n=[l];function s(r,c,i,g,f,h){return a(),t("div",null,n)}const b=e(d,[["render",s]]);export{p as __pageData,b as default};
diff --git a/assets/api_modules_game_events.md.abe1fe7b.lean.js b/assets/api_modules_game_events.md.b1ba4222.lean.js
similarity index 60%
rename from assets/api_modules_game_events.md.abe1fe7b.lean.js
rename to assets/api_modules_game_events.md.b1ba4222.lean.js
index c1bcf462..ccf03b4e 100644
--- a/assets/api_modules_game_events.md.abe1fe7b.lean.js
+++ b/assets/api_modules_game_events.md.b1ba4222.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/events","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/events.md","lastUpdated":null}'),d={name:"api/modules/game/events.md"},l=o("",15),n=[l];function s(r,c,i,g,f,h){return a(),t("div",null,n)}const p=e(d,[["render",s]]);export{b as __pageData,p as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: game/events","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/events.md","lastUpdated":null}'),d={name:"api/modules/game/events.md"},l=o("",15),n=[l];function s(r,c,i,g,f,h){return a(),t("div",null,n)}const b=e(d,[["render",s]]);export{p as __pageData,b as default};
diff --git a/assets/api_modules_game_formulas_formulas.md.b0d33fb7.js b/assets/api_modules_game_formulas_formulas.md.7e77be25.js
similarity index 99%
rename from assets/api_modules_game_formulas_formulas.md.b0d33fb7.js
rename to assets/api_modules_game_formulas_formulas.md.7e77be25.js
index 6c676f30..007dc65b 100644
--- a/assets/api_modules_game_formulas_formulas.md.b0d33fb7.js
+++ b/assets/api_modules_game_formulas_formulas.md.7e77be25.js
@@ -1 +1 @@
-import{_ as e,c as o,o as t,N as c}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Module: game/formulas/formulas","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/formulas.md","lastUpdated":null}'),d={name:"api/modules/game/formulas/formulas.md"},a=c('
A class that can be used for cost/goal functions. It can be evaluated similar to a cost function, but also provides extra features for supported formulas. For example, a lot of math functions can be inverted. Typically, the use of these extra features is to support cost/goal functions that have multiple levels purchased/completed at once efficiently.
Utility for calculating the cost of a formula for a given amount of purchases. If spendResources is changed to false, the calculation will be much faster with higher numbers.
Utility for calculating the maximum amount of purchases possible with a given formula and resource. If spendResources is changed to false, the calculation will be much faster with higher numbers.
',74),r=[a];function l(u,s,f,i,m,n){return t(),o("div",null,r)}const y=e(d,[["render",l]]);export{h as __pageData,y as default};
+import{_ as e,c as o,o as t,N as c}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Module: game/formulas/formulas","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/formulas.md","lastUpdated":null}'),d={name:"api/modules/game/formulas/formulas.md"},a=c('
A class that can be used for cost/goal functions. It can be evaluated similar to a cost function, but also provides extra features for supported formulas. For example, a lot of math functions can be inverted. Typically, the use of these extra features is to support cost/goal functions that have multiple levels purchased/completed at once efficiently.
Utility for calculating the cost of a formula for a given amount of purchases. If spendResources is changed to false, the calculation will be much faster with higher numbers.
Utility for calculating the maximum amount of purchases possible with a given formula and resource. If spendResources is changed to false, the calculation will be much faster with higher numbers.
',74),r=[a];function l(u,s,f,i,m,n){return t(),o("div",null,r)}const y=e(d,[["render",l]]);export{h as __pageData,y as default};
diff --git a/assets/api_modules_game_formulas_formulas.md.b0d33fb7.lean.js b/assets/api_modules_game_formulas_formulas.md.7e77be25.lean.js
similarity index 100%
rename from assets/api_modules_game_formulas_formulas.md.b0d33fb7.lean.js
rename to assets/api_modules_game_formulas_formulas.md.7e77be25.lean.js
diff --git a/assets/api_modules_game_formulas_operations.md.8c5d1a31.js b/assets/api_modules_game_formulas_operations.md.77986a03.js
similarity index 94%
rename from assets/api_modules_game_formulas_operations.md.8c5d1a31.js
rename to assets/api_modules_game_formulas_operations.md.77986a03.js
index 7ca3b51e..fb079dba 100644
--- a/assets/api_modules_game_formulas_operations.md.8c5d1a31.js
+++ b/assets/api_modules_game_formulas_operations.md.77986a03.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/formulas/operations","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/operations.md","lastUpdated":null}'),o={name:"api/modules/game/formulas/operations.md"},l=r('
',439),d=[l];function i(c,n,s,h,f,u){return a(),t("div",null,d)}const m=e(o,[["render",i]]);export{b as __pageData,m as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/formulas/operations","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/operations.md","lastUpdated":null}'),o={name:"api/modules/game/formulas/operations.md"},l=r('
',439),d=[l];function i(c,n,s,h,f,u){return a(),t("div",null,d)}const m=e(o,[["render",i]]);export{b as __pageData,m as default};
diff --git a/assets/api_modules_game_formulas_operations.md.8c5d1a31.lean.js b/assets/api_modules_game_formulas_operations.md.77986a03.lean.js
similarity index 100%
rename from assets/api_modules_game_formulas_operations.md.8c5d1a31.lean.js
rename to assets/api_modules_game_formulas_operations.md.77986a03.lean.js
diff --git a/assets/api_modules_game_formulas_types.md.1363e68e.js b/assets/api_modules_game_formulas_types.md.d603242c.js
similarity index 95%
rename from assets/api_modules_game_formulas_types.md.1363e68e.js
rename to assets/api_modules_game_formulas_types.md.d603242c.js
index cc558696..e87bf853 100644
--- a/assets/api_modules_game_formulas_types.md.1363e68e.js
+++ b/assets/api_modules_game_formulas_types.md.d603242c.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: game/formulas/types","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/types.md","lastUpdated":null}'),o={name:"api/modules/game/formulas/types.md"},l=r('
',131),d=[l];function n(c,i,s,u,f,h){return a(),t("div",null,d)}const b=e(o,[["render",n]]);export{m as __pageData,b as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: game/formulas/types","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/types.md","lastUpdated":null}'),o={name:"api/modules/game/formulas/types.md"},l=r('
',131),d=[l];function c(n,i,s,u,f,h){return a(),t("div",null,d)}const g=e(o,[["render",c]]);export{m as __pageData,g as default};
diff --git a/assets/api_modules_game_formulas_types.md.1363e68e.lean.js b/assets/api_modules_game_formulas_types.md.d603242c.lean.js
similarity index 71%
rename from assets/api_modules_game_formulas_types.md.1363e68e.lean.js
rename to assets/api_modules_game_formulas_types.md.d603242c.lean.js
index 84895b9a..74b4eb1d 100644
--- a/assets/api_modules_game_formulas_types.md.1363e68e.lean.js
+++ b/assets/api_modules_game_formulas_types.md.d603242c.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: game/formulas/types","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/types.md","lastUpdated":null}'),o={name:"api/modules/game/formulas/types.md"},l=r("",131),d=[l];function n(c,i,s,u,f,h){return a(),t("div",null,d)}const b=e(o,[["render",n]]);export{m as __pageData,b as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: game/formulas/types","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/formulas/types.md","lastUpdated":null}'),o={name:"api/modules/game/formulas/types.md"},l=r("",131),d=[l];function c(n,i,s,u,f,h){return a(),t("div",null,d)}const g=e(o,[["render",c]]);export{m as __pageData,g as default};
diff --git a/assets/api_modules_game_gameLoop.md.22660d28.js b/assets/api_modules_game_gameLoop.md.aa195300.js
similarity index 96%
rename from assets/api_modules_game_gameLoop.md.22660d28.js
rename to assets/api_modules_game_gameLoop.md.aa195300.js
index a384457e..b19eca58 100644
--- a/assets/api_modules_game_gameLoop.md.22660d28.js
+++ b/assets/api_modules_game_gameLoop.md.aa195300.js
@@ -1 +1 @@
-import{_ as e,c as a,o,N as t}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Module: game/gameLoop","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/gameLoop.md","lastUpdated":null}'),r={name:"api/modules/game/gameLoop.md"},s=t('
',9),n=[s];function i(l,c,d,m,p,h){return o(),a("div",null,n)}const _=e(r,[["render",i]]);export{g as __pageData,_ as default};
+import{_ as e,c as a,o,N as t}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Module: game/gameLoop","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/gameLoop.md","lastUpdated":null}'),r={name:"api/modules/game/gameLoop.md"},s=t('
',9),n=[s];function i(l,c,d,m,p,h){return o(),a("div",null,n)}const _=e(r,[["render",i]]);export{g as __pageData,_ as default};
diff --git a/assets/api_modules_game_gameLoop.md.22660d28.lean.js b/assets/api_modules_game_gameLoop.md.aa195300.lean.js
similarity index 100%
rename from assets/api_modules_game_gameLoop.md.22660d28.lean.js
rename to assets/api_modules_game_gameLoop.md.aa195300.lean.js
diff --git a/assets/api_modules_game_layers.md.53153f4a.js b/assets/api_modules_game_layers.md.7c45b0ae.js
similarity index 95%
rename from assets/api_modules_game_layers.md.53153f4a.js
rename to assets/api_modules_game_layers.md.7c45b0ae.js
index cad355e6..b8e1a0b6 100644
--- a/assets/api_modules_game_layers.md.53153f4a.js
+++ b/assets/api_modules_game_layers.md.7c45b0ae.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: game/layers","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/layers.md","lastUpdated":null}'),o={name:"api/modules/game/layers.md"},d=r('
An object that configures a Layer. Even moreso than features, the developer is expected to include extra properties in this object. All Persistent refs must be included somewhere within the layer object.
The layout of this layer's features. When the layer is open in game/player.PlayerData.tabs, but the tab is Layer.minimized this is the content that is displayed.
A reference to all the current layers. It is shallow reactive so it will update when layers are added or removed, but not interfere with the existing refs within each layer.
When creating layers, this object a map of layer ID to a set of any created persistent refs in order to check they're all included in the final layer object.
Enables a layer object, so it will be updated every tick. Note that accessing a layer/its properties does NOT require it to be enabled. For dynamic layers you can call this function and removeLayer as necessary. Just make sure getInitialLayers will provide an accurate list of layers based on the player data object. For static layers just make getInitialLayers return all the layers.
Convenience method for removing and immediately re-adding a layer. This is useful for layers with dynamic content, to ensure persistent refs are correctly configured.
Utility function for creating a modal that display's a display. Returns the modal itself, which can be rendered anywhere you need, as well as a function to open the modal.
',157),l=[d];function n(i,s,c,h,y,f){return a(),t("div",null,l)}const g=e(o,[["render",n]]);export{u as __pageData,g as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: game/layers","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/layers.md","lastUpdated":null}'),o={name:"api/modules/game/layers.md"},d=r('
An object that configures a Layer. Even moreso than features, the developer is expected to include extra properties in this object. All Persistent refs must be included somewhere within the layer object.
The layout of this layer's features. When the layer is open in game/player.PlayerData.tabs, but the tab is Layer.minimized this is the content that is displayed.
A reference to all the current layers. It is shallow reactive so it will update when layers are added or removed, but not interfere with the existing refs within each layer.
When creating layers, this object a map of layer ID to a set of any created persistent refs in order to check they're all included in the final layer object.
Enables a layer object, so it will be updated every tick. Note that accessing a layer/its properties does NOT require it to be enabled. For dynamic layers you can call this function and removeLayer as necessary. Just make sure getInitialLayers will provide an accurate list of layers based on the player data object. For static layers just make getInitialLayers return all the layers.
Convenience method for removing and immediately re-adding a layer. This is useful for layers with dynamic content, to ensure persistent refs are correctly configured.
Utility function for creating a modal that display's a display. Returns the modal itself, which can be rendered anywhere you need, as well as a function to open the modal.
',157),l=[d];function n(i,s,c,h,y,f){return a(),t("div",null,l)}const g=e(o,[["render",n]]);export{u as __pageData,g as default};
diff --git a/assets/api_modules_game_layers.md.53153f4a.lean.js b/assets/api_modules_game_layers.md.7c45b0ae.lean.js
similarity index 100%
rename from assets/api_modules_game_layers.md.53153f4a.lean.js
rename to assets/api_modules_game_layers.md.7c45b0ae.lean.js
diff --git a/assets/api_modules_game_modifiers.md.ccb4301e.js b/assets/api_modules_game_modifiers.md.fd2bf591.js
similarity index 97%
rename from assets/api_modules_game_modifiers.md.ccb4301e.js
rename to assets/api_modules_game_modifiers.md.fd2bf591.js
index b30b4270..6a24d9d4 100644
--- a/assets/api_modules_game_modifiers.md.ccb4301e.js
+++ b/assets/api_modules_game_modifiers.md.fd2bf591.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: game/modifiers","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/modifiers.md","lastUpdated":null}'),i={name:"api/modules/game/modifiers.md"},d=a('
An object that can be used to apply or unapply some modification to a number. Being reversible requires the operation being invertible, but some features may rely on that. Descriptions can be optionally included for displaying them to the player. The built-in modifier creators are designed to display the modifiers using createModifierSection.
Utility type used to narrow down a modifier type that will have a description and/or enabled property based on optional parameters, T and S (respectively).
â–¸ createSequentialModifier<T, S>(modifiersFunc): S
Takes an array of modifiers and applies and reverses them in order. Modifiers that are not enabled will not be applied nor reversed. Also joins their descriptions together.
',104),r=[d];function l(n,c,s,f,h,m){return o(),t("div",null,r)}const b=e(i,[["render",l]]);export{u as __pageData,b as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: game/modifiers","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/modifiers.md","lastUpdated":null}'),i={name:"api/modules/game/modifiers.md"},d=a('
An object that can be used to apply or unapply some modification to a number. Being reversible requires the operation being invertible, but some features may rely on that. Descriptions can be optionally included for displaying them to the player. The built-in modifier creators are designed to display the modifiers using createModifierSection.
Utility type used to narrow down a modifier type that will have a description and/or enabled property based on optional parameters, T and S (respectively).
â–¸ createSequentialModifier<T, S>(modifiersFunc): S
Takes an array of modifiers and applies and reverses them in order. Modifiers that are not enabled will not be applied nor reversed. Also joins their descriptions together.
',104),r=[d];function l(n,c,s,f,h,m){return o(),t("div",null,r)}const b=e(i,[["render",l]]);export{u as __pageData,b as default};
diff --git a/assets/api_modules_game_modifiers.md.ccb4301e.lean.js b/assets/api_modules_game_modifiers.md.fd2bf591.lean.js
similarity index 100%
rename from assets/api_modules_game_modifiers.md.ccb4301e.lean.js
rename to assets/api_modules_game_modifiers.md.fd2bf591.lean.js
diff --git a/assets/api_modules_game_notifications.md.97454fd7.js b/assets/api_modules_game_notifications.md.9e2f9c0d.js
similarity index 97%
rename from assets/api_modules_game_notifications.md.97454fd7.js
rename to assets/api_modules_game_notifications.md.9e2f9c0d.js
index 64852d58..6ec16226 100644
--- a/assets/api_modules_game_notifications.md.97454fd7.js
+++ b/assets/api_modules_game_notifications.md.9e2f9c0d.js
@@ -1 +1 @@
-import{_ as t,c as e,o as a,N as o}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: game/notifications","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/notifications.md","lastUpdated":null}'),i={name:"api/modules/game/notifications.md"},l=o('
Create a boolean ref that will automatically be set based on the given condition, but also dismissed when hovering over a given element, typically the element where acting upon the notification would take place.
',31),d=[l];function n(r,s,c,f,h,g){return a(),e("div",null,d)}const b=t(i,[["render",n]]);export{y as __pageData,b as default};
+import{_ as t,c as e,o as a,N as o}from"./chunks/framework.0799945b.js";const y=JSON.parse('{"title":"Module: game/notifications","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/notifications.md","lastUpdated":null}'),i={name:"api/modules/game/notifications.md"},l=o('
Create a boolean ref that will automatically be set based on the given condition, but also dismissed when hovering over a given element, typically the element where acting upon the notification would take place.
',31),d=[l];function n(r,s,c,f,h,g){return a(),e("div",null,d)}const b=t(i,[["render",n]]);export{y as __pageData,b as default};
diff --git a/assets/api_modules_game_notifications.md.97454fd7.lean.js b/assets/api_modules_game_notifications.md.9e2f9c0d.lean.js
similarity index 100%
rename from assets/api_modules_game_notifications.md.97454fd7.lean.js
rename to assets/api_modules_game_notifications.md.9e2f9c0d.lean.js
diff --git a/assets/api_modules_game_persistence.md.b8b93105.js b/assets/api_modules_game_persistence.md.65ff3590.js
similarity index 93%
rename from assets/api_modules_game_persistence.md.b8b93105.js
rename to assets/api_modules_game_persistence.md.65ff3590.js
index a60e6fdd..e676dc10 100644
--- a/assets/api_modules_game_persistence.md.b8b93105.js
+++ b/assets/api_modules_game_persistence.md.65ff3590.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/persistence","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/persistence.md","lastUpdated":null}'),s={name:"api/modules/game/persistence.md"},n=r('
Mark a Persistent as deleted, so it won't be saved and loaded. Since persistent refs must be created during a layer's options func, features can not create persistent refs after evaluating their own options funcs. As a result, it must create any persistent refs it might need. This function can then be called after the options func is evaluated to mark the persistent ref to not be saved or loaded.
Create a persistent ref, which can be saved and loaded. All (non-deleted) persistent refs must be included somewhere within the layer object returned by that layer's options func.
',136),o=[n];function i(d,c,l,h,p,f){return a(),t("div",null,o)}const g=e(s,[["render",i]]);export{b as __pageData,g as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/persistence","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/persistence.md","lastUpdated":null}'),s={name:"api/modules/game/persistence.md"},n=r('
Mark a Persistent as deleted, so it won't be saved and loaded. Since persistent refs must be created during a layer's options func, features can not create persistent refs after evaluating their own options funcs. As a result, it must create any persistent refs it might need. This function can then be called after the options func is evaluated to mark the persistent ref to not be saved or loaded.
Create a persistent ref, which can be saved and loaded. All (non-deleted) persistent refs must be included somewhere within the layer object returned by that layer's options func.
',136),o=[n];function i(c,d,l,h,p,f){return a(),t("div",null,o)}const g=e(s,[["render",i]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_game_persistence.md.b8b93105.lean.js b/assets/api_modules_game_persistence.md.65ff3590.lean.js
similarity index 85%
rename from assets/api_modules_game_persistence.md.b8b93105.lean.js
rename to assets/api_modules_game_persistence.md.65ff3590.lean.js
index 2cd70b19..4c5e60f3 100644
--- a/assets/api_modules_game_persistence.md.b8b93105.lean.js
+++ b/assets/api_modules_game_persistence.md.65ff3590.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/persistence","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/persistence.md","lastUpdated":null}'),s={name:"api/modules/game/persistence.md"},n=r("",136),o=[n];function i(d,c,l,h,p,f){return a(),t("div",null,o)}const g=e(s,[["render",i]]);export{b as __pageData,g as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/persistence","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/persistence.md","lastUpdated":null}'),s={name:"api/modules/game/persistence.md"},n=r("",136),o=[n];function i(c,d,l,h,p,f){return a(),t("div",null,o)}const g=e(s,[["render",i]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_game_player.md.ca5c5962.js b/assets/api_modules_game_player.md.2ff23970.js
similarity index 97%
rename from assets/api_modules_game_player.md.ca5c5962.js
rename to assets/api_modules_game_player.md.2ff23970.js
index 9df955e9..3c990539 100644
--- a/assets/api_modules_game_player.md.ca5c5962.js
+++ b/assets/api_modules_game_player.md.2ff23970.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as l}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: game/player","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/player.md","lastUpdated":null}'),d={name:"api/modules/game/player.md"},o=l('
',33),r=[o];function n(s,i,c,f,h,y){return a(),t("div",null,r)}const u=e(d,[["render",n]]);export{p as __pageData,u as default};
+import{_ as e,c as t,o as a,N as l}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: game/player","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/player.md","lastUpdated":null}'),d={name:"api/modules/game/player.md"},o=l('
',33),r=[o];function n(s,i,c,f,h,y){return a(),t("div",null,r)}const u=e(d,[["render",n]]);export{p as __pageData,u as default};
diff --git a/assets/api_modules_game_player.md.ca5c5962.lean.js b/assets/api_modules_game_player.md.2ff23970.lean.js
similarity index 100%
rename from assets/api_modules_game_player.md.ca5c5962.lean.js
rename to assets/api_modules_game_player.md.2ff23970.lean.js
diff --git a/assets/api_modules_game_requirements.md.c3fc6a41.js b/assets/api_modules_game_requirements.md.c3d814a1.js
similarity index 96%
rename from assets/api_modules_game_requirements.md.c3fc6a41.js
rename to assets/api_modules_game_requirements.md.c3d814a1.js
index 9e6252ba..876c294d 100644
--- a/assets/api_modules_game_requirements.md.c3fc6a41.js
+++ b/assets/api_modules_game_requirements.md.c3d814a1.js
@@ -1 +1 @@
-import{_ as e,c as t,o as r,N as a}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: game/requirements","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/requirements.md","lastUpdated":null}'),i={name:"api/modules/game/requirements.md"},o=a('
The amount of resource that must be met for this requirement. You can pass a formula, in which case maximizing will work out of the box (assuming its invertible and, for more accurate calculations, its integral is invertible). If you don't pass a formula then you can still support maximizing by passing a custom pay function.
When calculating multiple levels to be handled at once, whether it should consider resources used for each level as spent. Setting this to false causes calculations to be faster with larger numbers and supports more math functions. See
Whether or not this requirement can have multiple levels of requirements that can be met at once. Requirement is assumed to not have multiple levels if this property not present.
The display for this specific requirement. This is used for displays multiple requirements condensed. Required if visibility can be Visibility.Visible.
Calculates the maximum number of levels that could be acquired with the current requirement states. True/false requirements will be counted as Infinity or 0.
',112),n=[o];function s(l,d,c,u,h,m){return r(),t("div",null,n)}const b=e(i,[["render",s]]);export{p as __pageData,b as default};
+import{_ as e,c as t,o as r,N as a}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: game/requirements","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/requirements.md","lastUpdated":null}'),i={name:"api/modules/game/requirements.md"},o=a('
The amount of resource that must be met for this requirement. You can pass a formula, in which case maximizing will work out of the box (assuming its invertible and, for more accurate calculations, its integral is invertible). If you don't pass a formula then you can still support maximizing by passing a custom pay function.
When calculating multiple levels to be handled at once, whether it should consider resources used for each level as spent. Setting this to false causes calculations to be faster with larger numbers and supports more math functions. See
Whether or not this requirement can have multiple levels of requirements that can be met at once. Requirement is assumed to not have multiple levels if this property not present.
The display for this specific requirement. This is used for displays multiple requirements condensed. Required if visibility can be Visibility.Visible.
Calculates the maximum number of levels that could be acquired with the current requirement states. True/false requirements will be counted as Infinity or 0.
',112),n=[o];function s(l,d,c,u,h,m){return r(),t("div",null,n)}const b=e(i,[["render",s]]);export{p as __pageData,b as default};
diff --git a/assets/api_modules_game_requirements.md.c3fc6a41.lean.js b/assets/api_modules_game_requirements.md.c3d814a1.lean.js
similarity index 100%
rename from assets/api_modules_game_requirements.md.c3fc6a41.lean.js
rename to assets/api_modules_game_requirements.md.c3d814a1.lean.js
diff --git a/assets/api_modules_game_settings.md.76c1a71b.js b/assets/api_modules_game_settings.md.9be4860a.js
similarity index 93%
rename from assets/api_modules_game_settings.md.76c1a71b.js
rename to assets/api_modules_game_settings.md.9be4860a.js
index e26ea0a5..21c6af30 100644
--- a/assets/api_modules_game_settings.md.76c1a71b.js
+++ b/assets/api_modules_game_settings.md.9be4860a.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: game/settings","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/settings.md","lastUpdated":null}'),o={name:"api/modules/game/settings.md"},n=r('
Loads the player settings from localStorage. Calls the GlobalEvents.loadSettings event for custom properties to be included. Custom properties should be added by the file they relate to, so they won't be included if the file is tree shaken away. Custom properties should also register the field to modify said setting using registerSettingField.
',80),s=[n];function i(d,l,c,h,f,g){return a(),t("div",null,s)}const m=e(o,[["render",i]]);export{u as __pageData,m as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const u=JSON.parse('{"title":"Module: game/settings","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/settings.md","lastUpdated":null}'),o={name:"api/modules/game/settings.md"},n=r('
Loads the player settings from localStorage. Calls the GlobalEvents.loadSettings event for custom properties to be included. Custom properties should be added by the file they relate to, so they won't be included if the file is tree shaken away. Custom properties should also register the field to modify said setting using registerSettingField.
',80),s=[n];function i(d,l,c,h,f,g){return a(),t("div",null,s)}const m=e(o,[["render",i]]);export{u as __pageData,m as default};
diff --git a/assets/api_modules_game_settings.md.76c1a71b.lean.js b/assets/api_modules_game_settings.md.9be4860a.lean.js
similarity index 100%
rename from assets/api_modules_game_settings.md.76c1a71b.lean.js
rename to assets/api_modules_game_settings.md.9be4860a.lean.js
diff --git a/assets/api_modules_game_state.md.f2996de8.js b/assets/api_modules_game_state.md.8c383250.js
similarity index 96%
rename from assets/api_modules_game_state.md.f2996de8.js
rename to assets/api_modules_game_state.md.8c383250.js
index 6278ebd4..6adb9bf4 100644
--- a/assets/api_modules_game_state.md.f2996de8.js
+++ b/assets/api_modules_game_state.md.8c383250.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as l}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/state","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/state.md","lastUpdated":null}'),s={name:"api/modules/game/state.md"},r=l('
',14),n=[r];function o(d,i,c,h,f,u){return a(),t("div",null,n)}const m=e(s,[["render",o]]);export{b as __pageData,m as default};
+import{_ as e,c as t,o as a,N as l}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: game/state","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/game/state.md","lastUpdated":null}'),s={name:"api/modules/game/state.md"},r=l('
',14),n=[r];function o(d,i,c,h,f,u){return a(),t("div",null,n)}const m=e(s,[["render",o]]);export{b as __pageData,m as default};
diff --git a/assets/api_modules_game_state.md.f2996de8.lean.js b/assets/api_modules_game_state.md.8c383250.lean.js
similarity index 100%
rename from assets/api_modules_game_state.md.f2996de8.lean.js
rename to assets/api_modules_game_state.md.8c383250.lean.js
diff --git a/assets/api_modules_lib_break_eternity.md.10391c7b.js b/assets/api_modules_lib_break_eternity.md.70037e83.js
similarity index 99%
rename from assets/api_modules_lib_break_eternity.md.10391c7b.js
rename to assets/api_modules_lib_break_eternity.md.70037e83.js
index 6154ca8e..9404e822 100644
--- a/assets/api_modules_lib_break_eternity.md.10391c7b.js
+++ b/assets/api_modules_lib_break_eternity.md.70037e83.js
@@ -1 +1 @@
-import{_ as e,c as t,o as d,N as c}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: lib/break_eternity","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/lib/break_eternity.md","lastUpdated":null}'),a={name:"api/modules/lib/break_eternity.md"},o=c('
',18),l=[o];function r(i,f,n,u,s,y){return d(),t("div",null,l)}const b=e(a,[["render",r]]);export{m as __pageData,b as default};
+import{_ as e,c as t,o as d,N as c}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: lib/break_eternity","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/lib/break_eternity.md","lastUpdated":null}'),a={name:"api/modules/lib/break_eternity.md"},o=c('
',18),l=[o];function r(i,f,n,u,s,y){return d(),t("div",null,l)}const b=e(a,[["render",r]]);export{m as __pageData,b as default};
diff --git a/assets/api_modules_lib_break_eternity.md.10391c7b.lean.js b/assets/api_modules_lib_break_eternity.md.70037e83.lean.js
similarity index 100%
rename from assets/api_modules_lib_break_eternity.md.10391c7b.lean.js
rename to assets/api_modules_lib_break_eternity.md.70037e83.lean.js
diff --git a/assets/api_modules_lib_lru-cache.md.e899c8cb.js b/assets/api_modules_lib_lru-cache.md.0d6df6b0.js
similarity index 98%
rename from assets/api_modules_lib_lru-cache.md.e899c8cb.js
rename to assets/api_modules_lib_lru-cache.md.0d6df6b0.js
index f7fc41e4..e5422aac 100644
--- a/assets/api_modules_lib_lru-cache.md.e899c8cb.js
+++ b/assets/api_modules_lib_lru-cache.md.0d6df6b0.js
@@ -1 +1 @@
-import{_ as e,c as t,o as d,N as c}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: lib/lru-cache","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/lib/lru-cache.md","lastUpdated":null}'),a={name:"api/modules/lib/lru-cache.md"},o=c('
',10),l=[o];function r(s,i,n,h,f,u){return d(),t("div",null,l)}const p=e(a,[["render",r]]);export{b as __pageData,p as default};
+import{_ as e,c as t,o as d,N as c}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: lib/lru-cache","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/lib/lru-cache.md","lastUpdated":null}'),a={name:"api/modules/lib/lru-cache.md"},o=c('
',10),l=[o];function r(s,i,n,h,f,u){return d(),t("div",null,l)}const p=e(a,[["render",r]]);export{b as __pageData,p as default};
diff --git a/assets/api_modules_lib_lru-cache.md.e899c8cb.lean.js b/assets/api_modules_lib_lru-cache.md.0d6df6b0.lean.js
similarity index 100%
rename from assets/api_modules_lib_lru-cache.md.e899c8cb.lean.js
rename to assets/api_modules_lib_lru-cache.md.0d6df6b0.lean.js
diff --git a/assets/api_modules_lib_pwa-register.md.dcf3fc0d.js b/assets/api_modules_lib_pwa-register.md.1bd3c6c7.js
similarity index 96%
rename from assets/api_modules_lib_pwa-register.md.dcf3fc0d.js
rename to assets/api_modules_lib_pwa-register.md.1bd3c6c7.js
index ccff3d6d..e9437bf4 100644
--- a/assets/api_modules_lib_pwa-register.md.dcf3fc0d.js
+++ b/assets/api_modules_lib_pwa-register.md.1bd3c6c7.js
@@ -1 +1 @@
-import{_ as e,c as t,o as r,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: lib/pwa-register","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/lib/pwa-register.md","lastUpdated":null}'),o={name:"api/modules/lib/pwa-register.md"},i=a('
',13),d=[i];function s(l,n,c,g,f,h){return r(),t("div",null,d)}const u=e(o,[["render",s]]);export{b as __pageData,u as default};
+import{_ as e,c as t,o as r,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: lib/pwa-register","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/lib/pwa-register.md","lastUpdated":null}'),o={name:"api/modules/lib/pwa-register.md"},i=a('
',13),d=[i];function s(l,n,c,g,f,h){return r(),t("div",null,d)}const u=e(o,[["render",s]]);export{b as __pageData,u as default};
diff --git a/assets/api_modules_lib_pwa-register.md.dcf3fc0d.lean.js b/assets/api_modules_lib_pwa-register.md.1bd3c6c7.lean.js
similarity index 100%
rename from assets/api_modules_lib_pwa-register.md.dcf3fc0d.lean.js
rename to assets/api_modules_lib_pwa-register.md.1bd3c6c7.lean.js
diff --git a/assets/api_modules_util_bignum.md.b875362c.js b/assets/api_modules_util_bignum.md.1a9c9e50.js
similarity index 93%
rename from assets/api_modules_util_bignum.md.b875362c.js
rename to assets/api_modules_util_bignum.md.1a9c9e50.js
index 3002e19d..9b39ff7b 100644
--- a/assets/api_modules_util_bignum.md.b875362c.js
+++ b/assets/api_modules_util_bignum.md.1a9c9e50.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: util/bignum","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/bignum.md","lastUpdated":null}'),o={name:"api/modules/util/bignum.md"},l=r('
',63),i=[l];function d(n,c,s,h,f,u){return a(),t("div",null,i)}const g=e(o,[["render",d]]);export{m as __pageData,g as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/bignum","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/bignum.md","lastUpdated":null}'),o={name:"api/modules/util/bignum.md"},l=r('
',63),i=[l];function d(n,c,s,h,f,u){return a(),t("div",null,i)}const g=e(o,[["render",d]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_util_bignum.md.b875362c.lean.js b/assets/api_modules_util_bignum.md.1a9c9e50.lean.js
similarity index 75%
rename from assets/api_modules_util_bignum.md.b875362c.lean.js
rename to assets/api_modules_util_bignum.md.1a9c9e50.lean.js
index 483464fd..b61c0833 100644
--- a/assets/api_modules_util_bignum.md.b875362c.lean.js
+++ b/assets/api_modules_util_bignum.md.1a9c9e50.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: util/bignum","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/bignum.md","lastUpdated":null}'),o={name:"api/modules/util/bignum.md"},l=r("",63),i=[l];function d(n,c,s,h,f,u){return a(),t("div",null,i)}const g=e(o,[["render",d]]);export{m as __pageData,g as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/bignum","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/bignum.md","lastUpdated":null}'),o={name:"api/modules/util/bignum.md"},l=r("",63),i=[l];function d(n,c,s,h,f,u){return a(),t("div",null,i)}const g=e(o,[["render",d]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_util_break_eternity.md.ce26b3f3.js b/assets/api_modules_util_break_eternity.md.3003c947.js
similarity index 93%
rename from assets/api_modules_util_break_eternity.md.ce26b3f3.js
rename to assets/api_modules_util_break_eternity.md.3003c947.js
index 4ee0874b..c7f6ffa8 100644
--- a/assets/api_modules_util_break_eternity.md.ce26b3f3.js
+++ b/assets/api_modules_util_break_eternity.md.3003c947.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: util/break_eternity","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/break_eternity.md","lastUpdated":null}'),o={name:"api/modules/util/break_eternity.md"},l=r('
',58),d=[l];function i(n,c,s,f,h,b){return a(),t("div",null,d)}const y=e(o,[["render",i]]);export{m as __pageData,y as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: util/break_eternity","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/break_eternity.md","lastUpdated":null}'),o={name:"api/modules/util/break_eternity.md"},l=r('
',58),d=[l];function i(n,c,s,f,h,u){return a(),t("div",null,d)}const y=e(o,[["render",i]]);export{m as __pageData,y as default};
diff --git a/assets/api_modules_util_break_eternity.md.ce26b3f3.lean.js b/assets/api_modules_util_break_eternity.md.3003c947.lean.js
similarity index 85%
rename from assets/api_modules_util_break_eternity.md.ce26b3f3.lean.js
rename to assets/api_modules_util_break_eternity.md.3003c947.lean.js
index c56e80fb..40093198 100644
--- a/assets/api_modules_util_break_eternity.md.ce26b3f3.lean.js
+++ b/assets/api_modules_util_break_eternity.md.3003c947.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: util/break_eternity","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/break_eternity.md","lastUpdated":null}'),o={name:"api/modules/util/break_eternity.md"},l=r("",58),d=[l];function i(n,c,s,f,h,b){return a(),t("div",null,d)}const y=e(o,[["render",i]]);export{m as __pageData,y as default};
+import{_ as e,c as t,o as a,N as r}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Module: util/break_eternity","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/break_eternity.md","lastUpdated":null}'),o={name:"api/modules/util/break_eternity.md"},l=r("",58),d=[l];function i(n,c,s,f,h,u){return a(),t("div",null,d)}const y=e(o,[["render",i]]);export{m as __pageData,y as default};
diff --git a/assets/api_modules_util_common.md.19b562fd.js b/assets/api_modules_util_common.md.343953e6.js
similarity index 93%
rename from assets/api_modules_util_common.md.19b562fd.js
rename to assets/api_modules_util_common.md.343953e6.js
index 0c3f90f6..a0627950 100644
--- a/assets/api_modules_util_common.md.19b562fd.js
+++ b/assets/api_modules_util_common.md.343953e6.js
@@ -1 +1 @@
-import{_ as o,c as r,o as l,N as a,x as e,a as t}from"./chunks/framework.0799945b.js";const x=JSON.parse('{"title":"Module: util/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/common.md","lastUpdated":null}'),d={name:"api/modules/util/common.md"},n=a('
',16),s=[n,i,c];function h(u,f,m,b,p,y){return l(),r("div",null,s)}const _=o(d,[["render",h]]);export{x as __pageData,_ as default};
+import{_ as o,c as r,o as l,N as a,x as e,a as t}from"./chunks/framework.0799945b.js";const x=JSON.parse('{"title":"Module: util/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/common.md","lastUpdated":null}'),d={name:"api/modules/util/common.md"},n=a('
',16),s=[n,i,c];function h(u,f,m,p,b,y){return l(),r("div",null,s)}const _=o(d,[["render",h]]);export{x as __pageData,_ as default};
diff --git a/assets/api_modules_util_common.md.19b562fd.lean.js b/assets/api_modules_util_common.md.343953e6.lean.js
similarity index 89%
rename from assets/api_modules_util_common.md.19b562fd.lean.js
rename to assets/api_modules_util_common.md.343953e6.lean.js
index 4d5f7dd1..49b94c7a 100644
--- a/assets/api_modules_util_common.md.19b562fd.lean.js
+++ b/assets/api_modules_util_common.md.343953e6.lean.js
@@ -1 +1 @@
-import{_ as o,c as r,o as l,N as a,x as e,a as t}from"./chunks/framework.0799945b.js";const x=JSON.parse('{"title":"Module: util/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/common.md","lastUpdated":null}'),d={name:"api/modules/util/common.md"},n=a("",16),i=e("p",{"[P":"",in:"","K]-?:":"","T[P]":""},[t("Ƭ "),e("strong",null,"WithRequired"),t("<"),e("code",null,"T"),t(", "),e("code",null,"K"),t(">: "),e("code",null,"T"),t(" &")],-1),c=a("",16),s=[n,i,c];function h(u,f,m,b,p,y){return l(),r("div",null,s)}const _=o(d,[["render",h]]);export{x as __pageData,_ as default};
+import{_ as o,c as r,o as l,N as a,x as e,a as t}from"./chunks/framework.0799945b.js";const x=JSON.parse('{"title":"Module: util/common","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/common.md","lastUpdated":null}'),d={name:"api/modules/util/common.md"},n=a("",16),i=e("p",{"[P":"",in:"","K]-?:":"","T[P]":""},[t("Ƭ "),e("strong",null,"WithRequired"),t("<"),e("code",null,"T"),t(", "),e("code",null,"K"),t(">: "),e("code",null,"T"),t(" &")],-1),c=a("",16),s=[n,i,c];function h(u,f,m,p,b,y){return l(),r("div",null,s)}const _=o(d,[["render",h]]);export{x as __pageData,_ as default};
diff --git a/assets/api_modules_util_computed.md.88db1dec.js b/assets/api_modules_util_computed.md.661874a7.js
similarity index 94%
rename from assets/api_modules_util_computed.md.88db1dec.js
rename to assets/api_modules_util_computed.md.661874a7.js
index f0f6d282..44eef9c9 100644
--- a/assets/api_modules_util_computed.md.88db1dec.js
+++ b/assets/api_modules_util_computed.md.661874a7.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Module: util/computed","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/computed.md","lastUpdated":null}'),r={name:"api/modules/util/computed.md"},d=o('
',60),l=[d];function c(n,i,s,p,h,u){return a(),t("div",null,l)}const m=e(r,[["render",c]]);export{f as __pageData,m as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Module: util/computed","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/computed.md","lastUpdated":null}'),r={name:"api/modules/util/computed.md"},d=o('
',60),l=[d];function c(n,i,s,p,h,u){return a(),t("div",null,l)}const m=e(r,[["render",c]]);export{f as __pageData,m as default};
diff --git a/assets/api_modules_util_computed.md.88db1dec.lean.js b/assets/api_modules_util_computed.md.661874a7.lean.js
similarity index 100%
rename from assets/api_modules_util_computed.md.88db1dec.lean.js
rename to assets/api_modules_util_computed.md.661874a7.lean.js
diff --git a/assets/api_modules_util_proxies.md.4a793e44.js b/assets/api_modules_util_proxies.md.350b0054.js
similarity index 95%
rename from assets/api_modules_util_proxies.md.4a793e44.js
rename to assets/api_modules_util_proxies.md.350b0054.js
index 406058ec..eb6b74c1 100644
--- a/assets/api_modules_util_proxies.md.4a793e44.js
+++ b/assets/api_modules_util_proxies.md.350b0054.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/proxies","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/proxies.md","lastUpdated":null}'),r={name:"api/modules/util/proxies.md"},d=o('
',31),l=[d];function i(n,c,s,h,p,u){return a(),t("div",null,l)}const y=e(r,[["render",i]]);export{b as __pageData,y as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/proxies","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/proxies.md","lastUpdated":null}'),r={name:"api/modules/util/proxies.md"},d=o('
',31),l=[d];function i(n,c,s,h,p,u){return a(),t("div",null,l)}const y=e(r,[["render",i]]);export{b as __pageData,y as default};
diff --git a/assets/api_modules_util_proxies.md.4a793e44.lean.js b/assets/api_modules_util_proxies.md.350b0054.lean.js
similarity index 100%
rename from assets/api_modules_util_proxies.md.4a793e44.lean.js
rename to assets/api_modules_util_proxies.md.350b0054.lean.js
diff --git a/assets/api_modules_util_save.md.3fb3841f.js b/assets/api_modules_util_save.md.44f096e7.js
similarity index 89%
rename from assets/api_modules_util_save.md.3fb3841f.js
rename to assets/api_modules_util_save.md.44f096e7.js
index 5993b28a..1ff466c6 100644
--- a/assets/api_modules_util_save.md.3fb3841f.js
+++ b/assets/api_modules_util_save.md.44f096e7.js
@@ -1 +1 @@
-import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: util/save","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/save.md","lastUpdated":null}'),o={name:"api/modules/util/save.md"},l=r('
',49),i=[l];function n(s,d,c,h,f,u){return t(),a("div",null,i)}const g=e(o,[["render",n]]);export{p as __pageData,g as default};
+import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/save","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/save.md","lastUpdated":null}'),o={name:"api/modules/util/save.md"},l=r('
',49),i=[l];function n(s,d,c,h,f,u){return t(),a("div",null,i)}const g=e(o,[["render",n]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_util_save.md.3fb3841f.lean.js b/assets/api_modules_util_save.md.44f096e7.lean.js
similarity index 76%
rename from assets/api_modules_util_save.md.3fb3841f.lean.js
rename to assets/api_modules_util_save.md.44f096e7.lean.js
index 7068307e..60fe057d 100644
--- a/assets/api_modules_util_save.md.3fb3841f.lean.js
+++ b/assets/api_modules_util_save.md.44f096e7.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const p=JSON.parse('{"title":"Module: util/save","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/save.md","lastUpdated":null}'),o={name:"api/modules/util/save.md"},l=r("",49),i=[l];function n(s,d,c,h,f,u){return t(),a("div",null,i)}const g=e(o,[["render",n]]);export{p as __pageData,g as default};
+import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/save","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/save.md","lastUpdated":null}'),o={name:"api/modules/util/save.md"},l=r("",49),i=[l];function n(s,d,c,h,f,u){return t(),a("div",null,i)}const g=e(o,[["render",n]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_util_vue.md.284b139c.js b/assets/api_modules_util_vue.md.cc419912.js
similarity index 93%
rename from assets/api_modules_util_vue.md.284b139c.js
rename to assets/api_modules_util_vue.md.cc419912.js
index 731b3a2f..8998ffcc 100644
--- a/assets/api_modules_util_vue.md.284b139c.js
+++ b/assets/api_modules_util_vue.md.cc419912.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/vue","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/vue.md","lastUpdated":null}'),r={name:"api/modules/util/vue.md"},d=a('
',120),l=[d];function n(c,i,s,f,h,u){return o(),t("div",null,l)}const g=e(r,[["render",n]]);export{b as __pageData,g as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Module: util/vue","description":"","frontmatter":{"editLink":false},"headers":[],"relativePath":"api/modules/util/vue.md","lastUpdated":null}'),r={name:"api/modules/util/vue.md"},d=a('
',120),l=[d];function n(c,i,s,f,h,u){return o(),t("div",null,l)}const g=e(r,[["render",n]]);export{b as __pageData,g as default};
diff --git a/assets/api_modules_util_vue.md.284b139c.lean.js b/assets/api_modules_util_vue.md.cc419912.lean.js
similarity index 100%
rename from assets/api_modules_util_vue.md.284b139c.lean.js
rename to assets/api_modules_util_vue.md.cc419912.lean.js
diff --git a/assets/guide_advanced-concepts_creating-features.md.4c4ef16d.js b/assets/guide_advanced-concepts_creating-features.md.b9dbab89.js
similarity index 99%
rename from assets/guide_advanced-concepts_creating-features.md.4c4ef16d.js
rename to assets/guide_advanced-concepts_creating-features.md.b9dbab89.js
index 54732fab..71622793 100644
--- a/assets/guide_advanced-concepts_creating-features.md.4c4ef16d.js
+++ b/assets/guide_advanced-concepts_creating-features.md.b9dbab89.js
@@ -1,4 +1,4 @@
-import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Creating Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/creating-features.md","lastUpdated":1681878045000}'),o={name:"guide/advanced-concepts/creating-features.md"},t=n(`
Profectus is designed to encourage the developer to eventually start designing their own features for use in specific games. Features are designed to work where they require minimal (and typically zero) modifications around the code base - you simply write a single file for the feature, and any vue components it needs, and the act of importing that feature will set everything up. This also means you can share these features with others in entire collections, and any they don't use won't be present in the build output, won't be loaded, and won't affect the project in any way.
Every feature has a couple of types. They have the feature themselves, a generic version for convenience, and any constructor typically has an options type and a type that gets "added" to it to create the feature itself. These typically involve replacing some types to denote how various properties change from, for example, Computable<X> to ProcessedComputable<X>. You should be able to use any of the existing features as a reference for how these types look and work.
Most significantly, the base type should typically always have a type property pointing to a symbol unique to this feature, so they can be easily differentiated at runtime. If it's a feature that should be renderable, then it'll also need [Component] and [GatherProps] properties, which describe the vue component to use and how to get the props for it from this feature, as well as a unique ID for the feature's node. You can use the getUniqueID utility to help.
The constructor itself should do several things. They should take their options within a function, so that they're not resolved when the object is constructed. It should return a lazy proxy of the feature, which allows features to reference each other and only resolve themselves once every feature is defined. The constructor should create any persistent refs it may require outside of the lazy proxy - it won't have access to the options at this point, so it should make any it potentially may require. Any that turn out not being needed can be deleted. Inside the lazy proxy the constructor should create the options object, assign onto it every property from the base type, call processComputable on every computable type, and setDefault on any property with a default value. Then you should be able to simply return the options object, likely with a type cast, and the constructor will be complete.
Because typescript does not emit JS, if a property is supposed to be a function it is impossible to differentiate between a function that is itself the intended value or a function that returns the actual value. For this reason it is not recommended for any feature types to include properties that are Computable<Function>s, and all functions will be wrapped in computed. The notable exception to this is JSX, which uses a utility function to mark that a function should not be wrapped.
Any vue components you write need to do a couple things. Typically they'll need to type any props that come from computed properties appropriately, for which you can use the processedPropType utility - using it will look something like style: processedPropType<StyleValue>(String, Object, Array). You'll also want to make sure to unref any of these props you use in the template. The template should make sure to include a Node component with the feature's ID. Also, if there are custom displays this feature may have, you'll want to convert the CoercableComponent into a Vue component inside the setup function, typically using the computeComponent or computeOptionalComponent utilities.
To add a setting to the options menu specific to this feature, you'll need to do three things, all inside the feature's file. First, extend the settings type with the name of the new setting. For example, here's how the challenge feature adds a setting to hide completed challenges:
ts
declaremodule"game/settings"{
+import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Creating Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/creating-features.md","lastUpdated":1681880763000}'),o={name:"guide/advanced-concepts/creating-features.md"},t=n(`
Profectus is designed to encourage the developer to eventually start designing their own features for use in specific games. Features are designed to work where they require minimal (and typically zero) modifications around the code base - you simply write a single file for the feature, and any vue components it needs, and the act of importing that feature will set everything up. This also means you can share these features with others in entire collections, and any they don't use won't be present in the build output, won't be loaded, and won't affect the project in any way.
Every feature has a couple of types. They have the feature themselves, a generic version for convenience, and any constructor typically has an options type and a type that gets "added" to it to create the feature itself. These typically involve replacing some types to denote how various properties change from, for example, Computable<X> to ProcessedComputable<X>. You should be able to use any of the existing features as a reference for how these types look and work.
Most significantly, the base type should typically always have a type property pointing to a symbol unique to this feature, so they can be easily differentiated at runtime. If it's a feature that should be renderable, then it'll also need [Component] and [GatherProps] properties, which describe the vue component to use and how to get the props for it from this feature, as well as a unique ID for the feature's node. You can use the getUniqueID utility to help.
The constructor itself should do several things. They should take their options within a function, so that they're not resolved when the object is constructed. It should return a lazy proxy of the feature, which allows features to reference each other and only resolve themselves once every feature is defined. The constructor should create any persistent refs it may require outside of the lazy proxy - it won't have access to the options at this point, so it should make any it potentially may require. Any that turn out not being needed can be deleted. Inside the lazy proxy the constructor should create the options object, assign onto it every property from the base type, call processComputable on every computable type, and setDefault on any property with a default value. Then you should be able to simply return the options object, likely with a type cast, and the constructor will be complete.
Because typescript does not emit JS, if a property is supposed to be a function it is impossible to differentiate between a function that is itself the intended value or a function that returns the actual value. For this reason it is not recommended for any feature types to include properties that are Computable<Function>s, and all functions will be wrapped in computed. The notable exception to this is JSX, which uses a utility function to mark that a function should not be wrapped.
Any vue components you write need to do a couple things. Typically they'll need to type any props that come from computed properties appropriately, for which you can use the processedPropType utility - using it will look something like style: processedPropType<StyleValue>(String, Object, Array). You'll also want to make sure to unref any of these props you use in the template. The template should make sure to include a Node component with the feature's ID. Also, if there are custom displays this feature may have, you'll want to convert the CoercableComponent into a Vue component inside the setup function, typically using the computeComponent or computeOptionalComponent utilities.
To add a setting to the options menu specific to this feature, you'll need to do three things, all inside the feature's file. First, extend the settings type with the name of the new setting. For example, here's how the challenge feature adds a setting to hide completed challenges:
ts
declaremodule"game/settings"{interfaceSettings{ hideChallenges:boolean;}
diff --git a/assets/guide_advanced-concepts_creating-features.md.4c4ef16d.lean.js b/assets/guide_advanced-concepts_creating-features.md.b9dbab89.lean.js
similarity index 85%
rename from assets/guide_advanced-concepts_creating-features.md.4c4ef16d.lean.js
rename to assets/guide_advanced-concepts_creating-features.md.b9dbab89.lean.js
index 7535a3f3..fe42d2f1 100644
--- a/assets/guide_advanced-concepts_creating-features.md.4c4ef16d.lean.js
+++ b/assets/guide_advanced-concepts_creating-features.md.b9dbab89.lean.js
@@ -1 +1 @@
-import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Creating Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/creating-features.md","lastUpdated":1681878045000}'),o={name:"guide/advanced-concepts/creating-features.md"},t=n("",19),l=[t];function p(r,c,y,i,F,D){return a(),e("div",null,l)}const C=s(o,[["render",p]]);export{d as __pageData,C as default};
+import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Creating Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/creating-features.md","lastUpdated":1681880763000}'),o={name:"guide/advanced-concepts/creating-features.md"},t=n("",19),l=[t];function p(r,c,y,i,F,D){return a(),e("div",null,l)}const C=s(o,[["render",p]]);export{d as __pageData,C as default};
diff --git a/assets/guide_advanced-concepts_dynamic-layers.md.42dd7b45.js b/assets/guide_advanced-concepts_dynamic-layers.md.11479b19.js
similarity index 98%
rename from assets/guide_advanced-concepts_dynamic-layers.md.42dd7b45.js
rename to assets/guide_advanced-concepts_dynamic-layers.md.11479b19.js
index 44f4278d..ad785c3e 100644
--- a/assets/guide_advanced-concepts_dynamic-layers.md.42dd7b45.js
+++ b/assets/guide_advanced-concepts_dynamic-layers.md.11479b19.js
@@ -1,4 +1,4 @@
-import{_ as a,c as s,o as e,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Dynamic Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/dynamic-layers.md","lastUpdated":1681878045000}'),o={name:"guide/advanced-concepts/dynamic-layers.md"},l=n(`
You can dynamically add and remove layers using the addLayer and removeLayer functions. It's important to note that removing a layer does not affect the player's save data. You can safely add and remove the same layer without losing any progress. For instances where the structure of a layer changes, such as when adding a new feature, use the reloadLayer function.
When procedurally generating layers with similar structures, consider using a utility function like the one below. This function allows you to access a correctly typed reference to a layer with a specified ID easily:
ts
functiongetDynLayer(id:string):DynamicLayer{
+import{_ as a,c as s,o as e,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Dynamic Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/dynamic-layers.md","lastUpdated":1681880763000}'),o={name:"guide/advanced-concepts/dynamic-layers.md"},l=n(`
You can dynamically add and remove layers using the addLayer and removeLayer functions. It's important to note that removing a layer does not affect the player's save data. You can safely add and remove the same layer without losing any progress. For instances where the structure of a layer changes, such as when adding a new feature, use the reloadLayer function.
When procedurally generating layers with similar structures, consider using a utility function like the one below. This function allows you to access a correctly typed reference to a layer with a specified ID easily:
ts
functiongetDynLayer(id:string):DynamicLayer{constlayer=layers[id];if (!layer) throw"Layer does not exist";returnlayerasDynamicLayer;// you might need an "as unknown" after layer
diff --git a/assets/guide_advanced-concepts_dynamic-layers.md.42dd7b45.lean.js b/assets/guide_advanced-concepts_dynamic-layers.md.11479b19.lean.js
similarity index 85%
rename from assets/guide_advanced-concepts_dynamic-layers.md.42dd7b45.lean.js
rename to assets/guide_advanced-concepts_dynamic-layers.md.11479b19.lean.js
index f63cdb24..99c60a3a 100644
--- a/assets/guide_advanced-concepts_dynamic-layers.md.42dd7b45.lean.js
+++ b/assets/guide_advanced-concepts_dynamic-layers.md.11479b19.lean.js
@@ -1 +1 @@
-import{_ as a,c as s,o as e,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Dynamic Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/dynamic-layers.md","lastUpdated":1681878045000}'),o={name:"guide/advanced-concepts/dynamic-layers.md"},l=n("",6),t=[l];function r(p,c,y,i,d,u){return e(),s("div",null,t)}const h=a(o,[["render",r]]);export{D as __pageData,h as default};
+import{_ as a,c as s,o as e,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Dynamic Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/dynamic-layers.md","lastUpdated":1681880763000}'),o={name:"guide/advanced-concepts/dynamic-layers.md"},l=n("",6),t=[l];function r(p,c,y,i,d,u){return e(),s("div",null,t)}const h=a(o,[["render",r]]);export{D as __pageData,h as default};
diff --git a/assets/guide_advanced-concepts_nodes.md.2dc4bc54.js b/assets/guide_advanced-concepts_nodes.md.7755470e.js
similarity index 99%
rename from assets/guide_advanced-concepts_nodes.md.2dc4bc54.js
rename to assets/guide_advanced-concepts_nodes.md.7755470e.js
index 2f4f12f5..1aa3276f 100644
--- a/assets/guide_advanced-concepts_nodes.md.2dc4bc54.js
+++ b/assets/guide_advanced-concepts_nodes.md.7755470e.js
@@ -1,4 +1,4 @@
-import{_ as s,c as n,o as a,N as o}from"./chunks/framework.0799945b.js";const C=JSON.parse('{"title":"Nodes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/nodes.md","lastUpdated":1681878045000}'),l={name:"guide/advanced-concepts/nodes.md"},e=o(`
Features rendered in the DOM should include a Node component, which registers itself to the nearest Context component (usually within the Layer's component) and tracks the bounding rect (both size and position) of the DOM element. Access the DOM element for a feature via its unique id property within layer.nodes, provided it currently exists.
This is useful for features with complex displays, such as particle effects positioned relative to another feature or drawing links between different nodes. To illustrate this, let's look at a complete example of using layer.nodes to get a node's bounding rect and then placing a particle effect using it. Here's an example from Kronos:
ts
const particlesEmitter =ref(particles.addEmitter(element.particlesConfig));
+import{_ as s,c as n,o as a,N as o}from"./chunks/framework.0799945b.js";const C=JSON.parse('{"title":"Nodes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/nodes.md","lastUpdated":1681880763000}'),l={name:"guide/advanced-concepts/nodes.md"},e=o(`
Features rendered in the DOM should include a Node component, which registers itself to the nearest Context component (usually within the Layer's component) and tracks the bounding rect (both size and position) of the DOM element. Access the DOM element for a feature via its unique id property within layer.nodes, provided it currently exists.
This is useful for features with complex displays, such as particle effects positioned relative to another feature or drawing links between different nodes. To illustrate this, let's look at a complete example of using layer.nodes to get a node's bounding rect and then placing a particle effect using it. Here's an example from Kronos:
ts
const particlesEmitter =ref(particles.addEmitter(element.particlesConfig));const updateParticleEffect =async ([shouldEmit, rect, boundingRect]: [boolean,DOMRect|undefined,
diff --git a/assets/guide_advanced-concepts_nodes.md.2dc4bc54.lean.js b/assets/guide_advanced-concepts_nodes.md.7755470e.lean.js
similarity index 84%
rename from assets/guide_advanced-concepts_nodes.md.2dc4bc54.lean.js
rename to assets/guide_advanced-concepts_nodes.md.7755470e.lean.js
index 1db6b70e..89b765ee 100644
--- a/assets/guide_advanced-concepts_nodes.md.2dc4bc54.lean.js
+++ b/assets/guide_advanced-concepts_nodes.md.7755470e.lean.js
@@ -1 +1 @@
-import{_ as s,c as n,o as a,N as o}from"./chunks/framework.0799945b.js";const C=JSON.parse('{"title":"Nodes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/nodes.md","lastUpdated":1681878045000}'),l={name:"guide/advanced-concepts/nodes.md"},e=o("",6),p=[e];function t(c,r,y,D,F,i){return a(),n("div",null,p)}const d=s(l,[["render",t]]);export{C as __pageData,d as default};
+import{_ as s,c as n,o as a,N as o}from"./chunks/framework.0799945b.js";const C=JSON.parse('{"title":"Nodes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/advanced-concepts/nodes.md","lastUpdated":1681880763000}'),l={name:"guide/advanced-concepts/nodes.md"},e=o("",6),p=[e];function t(c,r,y,D,F,i){return a(),n("div",null,p)}const d=s(l,[["render",t]]);export{C as __pageData,d as default};
diff --git a/assets/guide_creating-your-project_changelog.md.8ee4e9ee.js b/assets/guide_creating-your-project_changelog.md.6f39eb0d.js
similarity index 98%
rename from assets/guide_creating-your-project_changelog.md.8ee4e9ee.js
rename to assets/guide_creating-your-project_changelog.md.6f39eb0d.js
index 4193bf3c..b59bed2d 100644
--- a/assets/guide_creating-your-project_changelog.md.8ee4e9ee.js
+++ b/assets/guide_creating-your-project_changelog.md.6f39eb0d.js
@@ -1,4 +1,4 @@
-import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Changelog","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/changelog.md","lastUpdated":1681878045000}'),l={name:"guide/creating-your-project/changelog.md"},o=e(`
This is a Vue component stored at /src/data/Changelog.vue used to display all the changes version to version. You can use any features you'd like within here, but it's recommended to simply add new <details> elements for each new major release, and mark the most recent one as open by default. It is strongly advised to not change any of the code relating to making the changelog appear in a modal.
There is a single version included by default that can serve as a reference of how it is recommended to add a version to the changelog:
html
<detailsopen>
+import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Changelog","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/changelog.md","lastUpdated":1681880763000}'),l={name:"guide/creating-your-project/changelog.md"},o=e(`
This is a Vue component stored at /src/data/Changelog.vue used to display all the changes version to version. You can use any features you'd like within here, but it's recommended to simply add new <details> elements for each new major release, and mark the most recent one as open by default. It is strongly advised to not change any of the code relating to making the changelog appear in a modal.
There is a single version included by default that can serve as a reference of how it is recommended to add a version to the changelog:
html
<detailsopen><summary>v0.0 Initial Commit - <time>2021-09-04</time></summary> This is the first release :D<ul>
diff --git a/assets/guide_creating-your-project_changelog.md.8ee4e9ee.lean.js b/assets/guide_creating-your-project_changelog.md.6f39eb0d.lean.js
similarity index 85%
rename from assets/guide_creating-your-project_changelog.md.8ee4e9ee.lean.js
rename to assets/guide_creating-your-project_changelog.md.6f39eb0d.lean.js
index 4fc16dff..4ffd48fc 100644
--- a/assets/guide_creating-your-project_changelog.md.8ee4e9ee.lean.js
+++ b/assets/guide_creating-your-project_changelog.md.6f39eb0d.lean.js
@@ -1 +1 @@
-import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Changelog","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/changelog.md","lastUpdated":1681878045000}'),l={name:"guide/creating-your-project/changelog.md"},o=e("",6),t=[o];function p(c,r,D,i,F,y){return n(),a("div",null,t)}const h=s(l,[["render",p]]);export{g as __pageData,h as default};
+import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Changelog","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/changelog.md","lastUpdated":1681880763000}'),l={name:"guide/creating-your-project/changelog.md"},o=e("",6),t=[o];function p(c,r,D,i,F,y){return n(),a("div",null,t)}const h=s(l,[["render",p]]);export{g as __pageData,h as default};
diff --git a/assets/guide_creating-your-project_project-entry.md.f0a6c223.js b/assets/guide_creating-your-project_project-entry.md.d9f79299.js
similarity index 98%
rename from assets/guide_creating-your-project_project-entry.md.f0a6c223.js
rename to assets/guide_creating-your-project_project-entry.md.d9f79299.js
index 6ba69d7e..70617f03 100644
--- a/assets/guide_creating-your-project_project-entry.md.f0a6c223.js
+++ b/assets/guide_creating-your-project_project-entry.md.d9f79299.js
@@ -1 +1 @@
-import{_ as e,c as a,o as t,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Project Entry","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-entry.md","lastUpdated":1681878045000}'),s={name:"guide/creating-your-project/project-entry.md"},r=o('
This is a TypeScript file containing the non-static parts of your project, and acts as the entry point for it.
It is stored at /src/data/projEntry.jsx.
This file has 3 things it must export, but beyond that can export anything the creator wants it to. Typically in addition to the required 3, the initial/"main" layer will be exported. Typically utilites belong in common.tsx, which exists next to projEntry.tsx.
A function that is given a player save data object currently being loaded, and returns a list of layers that should be active for that player. If a project does not have dynamic layers, this should always return a list of all layers.
This function will be run whenever a save is loaded that has a different version than the one in project info. It will be given the old version number, and the player save data object currently being loaded.
The purpose of this function is to perform any necessary migrations, such as capping a resource that accidentally inflated in a previous version of the project. By default it will do nothing.
',17),n=[r];function l(i,p,c,d,h,y){return t(),a("div",null,n)}const g=e(s,[["render",l]]);export{f as __pageData,g as default};
+import{_ as e,c as a,o as t,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Project Entry","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-entry.md","lastUpdated":1681880763000}'),s={name:"guide/creating-your-project/project-entry.md"},r=o('
This is a TypeScript file containing the non-static parts of your project, and acts as the entry point for it.
It is stored at /src/data/projEntry.jsx.
This file has 3 things it must export, but beyond that can export anything the creator wants it to. Typically in addition to the required 3, the initial/"main" layer will be exported. Typically utilites belong in common.tsx, which exists next to projEntry.tsx.
A function that is given a player save data object currently being loaded, and returns a list of layers that should be active for that player. If a project does not have dynamic layers, this should always return a list of all layers.
This function will be run whenever a save is loaded that has a different version than the one in project info. It will be given the old version number, and the player save data object currently being loaded.
The purpose of this function is to perform any necessary migrations, such as capping a resource that accidentally inflated in a previous version of the project. By default it will do nothing.
',17),n=[r];function l(i,p,c,d,h,y){return t(),a("div",null,n)}const g=e(s,[["render",l]]);export{f as __pageData,g as default};
diff --git a/assets/guide_creating-your-project_project-entry.md.f0a6c223.lean.js b/assets/guide_creating-your-project_project-entry.md.d9f79299.lean.js
similarity index 85%
rename from assets/guide_creating-your-project_project-entry.md.f0a6c223.lean.js
rename to assets/guide_creating-your-project_project-entry.md.d9f79299.lean.js
index ec2c22ef..287b09a3 100644
--- a/assets/guide_creating-your-project_project-entry.md.f0a6c223.lean.js
+++ b/assets/guide_creating-your-project_project-entry.md.d9f79299.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o as t,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Project Entry","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-entry.md","lastUpdated":1681878045000}'),s={name:"guide/creating-your-project/project-entry.md"},r=o("",17),n=[r];function l(i,p,c,d,h,y){return t(),a("div",null,n)}const g=e(s,[["render",l]]);export{f as __pageData,g as default};
+import{_ as e,c as a,o as t,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Project Entry","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-entry.md","lastUpdated":1681880763000}'),s={name:"guide/creating-your-project/project-entry.md"},r=o("",17),n=[r];function l(i,p,c,d,h,y){return t(),a("div",null,n)}const g=e(s,[["render",l]]);export{f as __pageData,g as default};
diff --git a/assets/guide_creating-your-project_project-info.md.a3cc873e.js b/assets/guide_creating-your-project_project-info.md.2ed5ca94.js
similarity index 99%
rename from assets/guide_creating-your-project_project-info.md.a3cc873e.js
rename to assets/guide_creating-your-project_project-info.md.2ed5ca94.js
index 5040cf8d..343c3cd5 100644
--- a/assets/guide_creating-your-project_project-info.md.a3cc873e.js
+++ b/assets/guide_creating-your-project_project-info.md.2ed5ca94.js
@@ -1 +1 @@
-import{_ as e,c as a,o,N as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Project Info","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-info.md","lastUpdated":1681878045000}'),i={name:"guide/creating-your-project/project-info.md"},l=t('
This is a unique ID used when saving player data. Changing this will effectively erase all save data for all players.
WARNING
This ID MUST be unique to your project, and should not be left as the default value. Otherwise, your project may use the save data from another project and cause issues for both projects.
The text to display for the discord server to point users to. This will appear when hovering over the discord icon, inside the info tab, the game over screen, as well as the NaN detected screen.
By default, this is The Paper Pilot Community, which can act as a catch-all for any Profectus projects without their own servers. If you change the discord server with your own, The Paper Pilot Community will still display underneath the custom server when hovering over the discord icon and within the info tab. Those places will also contain a link to the Modding Tree discord server.
The current version of the project loaded. If the player data was last saved in a different version of the project, fixOldSave will be run, so you can perform any save migrations necessary. This will also appear in the nav, the info tab, and the game over screen.
The display name for the current version of the project loaded. This will also appear in the nav, the info tab, and the game over screen unless set to an empty string.
Whether or not to allow resources to display small values (<.001). If false they'll just display as 0. Individual resources can also be configured to override this value.
Default precision to display numbers at when passed into format. Individual format calls can override this value, and resources can be configured with a custom precision as well.
Whether or not to display the nav as a header at the top of the screen. If disabled, the nav will appear on the left side of the screen laid over the first tab.
A path to an image file to display as the logo of the app. If null, the title will be shown instead. This will appear in the nav when useHeader is true.
The list of initial tabs to display on new saves. This value must have at least one element. Each element should be the ID of the layer to display in that tab.
The longest duration a single tick can be, in seconds. When calculating things like offline time, a single tick will be forced to be this amount or lower. This will make calculating offline time spread out across many ticks as necessary. The default value is 1 hour.
Whether or not to allow the player to pause the game. Turning this off disables the toggle from the options menu as well as the NaN screen. Developers can still manually pause by just running player.devSpeed = 0 in console (or = 1 to resume).
The encoding to use when exporting to the clipboard. Plain-text is fast to generate but is easiest for the player to manipulate and cheat with. Base 64 is slightly slower and the string will be longer but will offer a small barrier to people trying to cheat. LZ-String is the slowest method, but produces the smallest strings and still offers a small barrier to those trying to cheat. Some sharing platforms like pastebin may automatically delete base64 encoded text, and some sites might not support all the characters used in lz-string exports.
',66),r=[l];function n(s,d,c,h,u,p){return o(),a("div",null,r)}const m=e(i,[["render",n]]);export{b as __pageData,m as default};
+import{_ as e,c as a,o,N as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Project Info","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-info.md","lastUpdated":1681880763000}'),i={name:"guide/creating-your-project/project-info.md"},l=t('
This is a unique ID used when saving player data. Changing this will effectively erase all save data for all players.
WARNING
This ID MUST be unique to your project, and should not be left as the default value. Otherwise, your project may use the save data from another project and cause issues for both projects.
The text to display for the discord server to point users to. This will appear when hovering over the discord icon, inside the info tab, the game over screen, as well as the NaN detected screen.
By default, this is The Paper Pilot Community, which can act as a catch-all for any Profectus projects without their own servers. If you change the discord server with your own, The Paper Pilot Community will still display underneath the custom server when hovering over the discord icon and within the info tab. Those places will also contain a link to the Modding Tree discord server.
The current version of the project loaded. If the player data was last saved in a different version of the project, fixOldSave will be run, so you can perform any save migrations necessary. This will also appear in the nav, the info tab, and the game over screen.
The display name for the current version of the project loaded. This will also appear in the nav, the info tab, and the game over screen unless set to an empty string.
Whether or not to allow resources to display small values (<.001). If false they'll just display as 0. Individual resources can also be configured to override this value.
Default precision to display numbers at when passed into format. Individual format calls can override this value, and resources can be configured with a custom precision as well.
Whether or not to display the nav as a header at the top of the screen. If disabled, the nav will appear on the left side of the screen laid over the first tab.
A path to an image file to display as the logo of the app. If null, the title will be shown instead. This will appear in the nav when useHeader is true.
The list of initial tabs to display on new saves. This value must have at least one element. Each element should be the ID of the layer to display in that tab.
The longest duration a single tick can be, in seconds. When calculating things like offline time, a single tick will be forced to be this amount or lower. This will make calculating offline time spread out across many ticks as necessary. The default value is 1 hour.
Whether or not to allow the player to pause the game. Turning this off disables the toggle from the options menu as well as the NaN screen. Developers can still manually pause by just running player.devSpeed = 0 in console (or = 1 to resume).
The encoding to use when exporting to the clipboard. Plain-text is fast to generate but is easiest for the player to manipulate and cheat with. Base 64 is slightly slower and the string will be longer but will offer a small barrier to people trying to cheat. LZ-String is the slowest method, but produces the smallest strings and still offers a small barrier to those trying to cheat. Some sharing platforms like pastebin may automatically delete base64 encoded text, and some sites might not support all the characters used in lz-string exports.
',66),r=[l];function n(s,d,c,h,u,p){return o(),a("div",null,r)}const m=e(i,[["render",n]]);export{b as __pageData,m as default};
diff --git a/assets/guide_creating-your-project_project-info.md.a3cc873e.lean.js b/assets/guide_creating-your-project_project-info.md.2ed5ca94.lean.js
similarity index 85%
rename from assets/guide_creating-your-project_project-info.md.a3cc873e.lean.js
rename to assets/guide_creating-your-project_project-info.md.2ed5ca94.lean.js
index 41c591fd..648c9612 100644
--- a/assets/guide_creating-your-project_project-info.md.a3cc873e.lean.js
+++ b/assets/guide_creating-your-project_project-info.md.2ed5ca94.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o,N as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Project Info","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-info.md","lastUpdated":1681878045000}'),i={name:"guide/creating-your-project/project-info.md"},l=t("",66),r=[l];function n(s,d,c,h,u,p){return o(),a("div",null,r)}const m=e(i,[["render",n]]);export{b as __pageData,m as default};
+import{_ as e,c as a,o,N as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Project Info","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/project-info.md","lastUpdated":1681880763000}'),i={name:"guide/creating-your-project/project-info.md"},l=t("",66),r=[l];function n(s,d,c,h,u,p){return o(),a("div",null,r)}const m=e(i,[["render",n]]);export{b as __pageData,m as default};
diff --git a/assets/guide_creating-your-project_themes.md.2250bb2d.js b/assets/guide_creating-your-project_themes.md.7e3e475d.js
similarity index 97%
rename from assets/guide_creating-your-project_themes.md.2250bb2d.js
rename to assets/guide_creating-your-project_themes.md.7e3e475d.js
index bf00844d..33232d8d 100644
--- a/assets/guide_creating-your-project_themes.md.2250bb2d.js
+++ b/assets/guide_creating-your-project_themes.md.7e3e475d.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Themes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/themes.md","lastUpdated":1681878045000}'),i={name:"guide/creating-your-project/themes.md"},s=o('
Themes are objects that change how the project's interface should look. This is done mostly by changing the values of various CSS variables. You can look at the existing themes as a reference for the kind of values these CSS variables expect. They can also set various theme options that change how parts of the screen are laid out, which are described below.
You can add a theme by adding a property to the Themes enum and then including the theme in the exported object. It's recommended to use the spread operator if you'd like to have a theme look like another, but override specific options / CSS variables.
Themes added in this way will be automatically included in the Themes dropdown in the Options tab. Removing themes from the enum and exported object will similarly hide them from the dropdown.
If you'd like to change which theme is the default, you may modify the initial player settings object in the /src/game/settings.ts file. Keep in mind you'll also want to change it in the hardResetSettings function in the same file.
Toggles whether to display tab buttons in a tab list, similar to how a browser displays tabs; or to display them as floating buttons, similar to how TMT displays buttons.
If true, elements in a row or column will have their margins removed and border radiuses set to 0 between elements. This will cause the elements to appear as segments in a single object.
Currently, this can only merge in a single dimension. Rows of columns or columns of rows will not merge into a single rectangular object.
',15),n=[s];function r(h,l,d,c,m,p){return a(),t("div",null,n)}const b=e(i,[["render",r]]);export{g as __pageData,b as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Themes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/themes.md","lastUpdated":1681880763000}'),i={name:"guide/creating-your-project/themes.md"},s=o('
Themes are objects that change how the project's interface should look. This is done mostly by changing the values of various CSS variables. You can look at the existing themes as a reference for the kind of values these CSS variables expect. They can also set various theme options that change how parts of the screen are laid out, which are described below.
You can add a theme by adding a property to the Themes enum and then including the theme in the exported object. It's recommended to use the spread operator if you'd like to have a theme look like another, but override specific options / CSS variables.
Themes added in this way will be automatically included in the Themes dropdown in the Options tab. Removing themes from the enum and exported object will similarly hide them from the dropdown.
If you'd like to change which theme is the default, you may modify the initial player settings object in the /src/game/settings.ts file. Keep in mind you'll also want to change it in the hardResetSettings function in the same file.
Toggles whether to display tab buttons in a tab list, similar to how a browser displays tabs; or to display them as floating buttons, similar to how TMT displays buttons.
If true, elements in a row or column will have their margins removed and border radiuses set to 0 between elements. This will cause the elements to appear as segments in a single object.
Currently, this can only merge in a single dimension. Rows of columns or columns of rows will not merge into a single rectangular object.
',15),n=[s];function r(h,l,d,c,m,p){return a(),t("div",null,n)}const b=e(i,[["render",r]]);export{g as __pageData,b as default};
diff --git a/assets/guide_creating-your-project_themes.md.2250bb2d.lean.js b/assets/guide_creating-your-project_themes.md.7e3e475d.lean.js
similarity index 84%
rename from assets/guide_creating-your-project_themes.md.2250bb2d.lean.js
rename to assets/guide_creating-your-project_themes.md.7e3e475d.lean.js
index 36068baa..9fe2e07a 100644
--- a/assets/guide_creating-your-project_themes.md.2250bb2d.lean.js
+++ b/assets/guide_creating-your-project_themes.md.7e3e475d.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Themes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/themes.md","lastUpdated":1681878045000}'),i={name:"guide/creating-your-project/themes.md"},s=o("",15),n=[s];function r(h,l,d,c,m,p){return a(),t("div",null,n)}const b=e(i,[["render",r]]);export{g as __pageData,b as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Themes","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/themes.md","lastUpdated":1681880763000}'),i={name:"guide/creating-your-project/themes.md"},s=o("",15),n=[s];function r(h,l,d,c,m,p){return a(),t("div",null,n)}const b=e(i,[["render",r]]);export{g as __pageData,b as default};
diff --git a/assets/guide_creating-your-project_utils.md.8665c69a.js b/assets/guide_creating-your-project_utils.md.90e87938.js
similarity index 95%
rename from assets/guide_creating-your-project_utils.md.8665c69a.js
rename to assets/guide_creating-your-project_utils.md.90e87938.js
index 12fd671f..7519d126 100644
--- a/assets/guide_creating-your-project_utils.md.8665c69a.js
+++ b/assets/guide_creating-your-project_utils.md.90e87938.js
@@ -1 +1 @@
-import{_ as a,c as o,o as s,x as e,a as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Utilities","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/utils.md","lastUpdated":1681878045000}'),i={name:"guide/creating-your-project/utils.md"},n=e("h1",{id:"utilities",tabindex:"-1"},[t("Utilities "),e("a",{class:"header-anchor",href:"#utilities","aria-label":'Permalink to "Utilities"'},"​")],-1),r=e("p",null,"There are often concepts that aren't inherent to a single feature, but rather work with joining different features together. For example, a reset clickable that activates a conversion and resets a tree, which happens to be a common use case but isn't inherent to clickables, conversions, or trees.",-1),c=e("p",null,[t("These are perfect situations for utilities, and so to encourage creators to learn to identify and take advantage of these situations, a file called "),e("code",null,"src/data/common.tsx"),t(" has been created to demo some of the more common utility functions a project might use. Adding new utilities to this file is encouraged, as is creating utils in general. It also works as a good stepping stone to creating your own features.")],-1),l=[n,r,c];function d(u,h,p,f,m,_){return s(),o("div",null,l)}const k=a(i,[["render",d]]);export{b as __pageData,k as default};
+import{_ as a,c as o,o as s,x as e,a as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Utilities","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/utils.md","lastUpdated":1681880763000}'),i={name:"guide/creating-your-project/utils.md"},n=e("h1",{id:"utilities",tabindex:"-1"},[t("Utilities "),e("a",{class:"header-anchor",href:"#utilities","aria-label":'Permalink to "Utilities"'},"​")],-1),r=e("p",null,"There are often concepts that aren't inherent to a single feature, but rather work with joining different features together. For example, a reset clickable that activates a conversion and resets a tree, which happens to be a common use case but isn't inherent to clickables, conversions, or trees.",-1),c=e("p",null,[t("These are perfect situations for utilities, and so to encourage creators to learn to identify and take advantage of these situations, a file called "),e("code",null,"src/data/common.tsx"),t(" has been created to demo some of the more common utility functions a project might use. Adding new utilities to this file is encouraged, as is creating utils in general. It also works as a good stepping stone to creating your own features.")],-1),l=[n,r,c];function d(u,h,p,f,m,_){return s(),o("div",null,l)}const k=a(i,[["render",d]]);export{b as __pageData,k as default};
diff --git a/assets/guide_creating-your-project_utils.md.8665c69a.lean.js b/assets/guide_creating-your-project_utils.md.90e87938.lean.js
similarity index 95%
rename from assets/guide_creating-your-project_utils.md.8665c69a.lean.js
rename to assets/guide_creating-your-project_utils.md.90e87938.lean.js
index 12fd671f..7519d126 100644
--- a/assets/guide_creating-your-project_utils.md.8665c69a.lean.js
+++ b/assets/guide_creating-your-project_utils.md.90e87938.lean.js
@@ -1 +1 @@
-import{_ as a,c as o,o as s,x as e,a as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Utilities","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/utils.md","lastUpdated":1681878045000}'),i={name:"guide/creating-your-project/utils.md"},n=e("h1",{id:"utilities",tabindex:"-1"},[t("Utilities "),e("a",{class:"header-anchor",href:"#utilities","aria-label":'Permalink to "Utilities"'},"​")],-1),r=e("p",null,"There are often concepts that aren't inherent to a single feature, but rather work with joining different features together. For example, a reset clickable that activates a conversion and resets a tree, which happens to be a common use case but isn't inherent to clickables, conversions, or trees.",-1),c=e("p",null,[t("These are perfect situations for utilities, and so to encourage creators to learn to identify and take advantage of these situations, a file called "),e("code",null,"src/data/common.tsx"),t(" has been created to demo some of the more common utility functions a project might use. Adding new utilities to this file is encouraged, as is creating utils in general. It also works as a good stepping stone to creating your own features.")],-1),l=[n,r,c];function d(u,h,p,f,m,_){return s(),o("div",null,l)}const k=a(i,[["render",d]]);export{b as __pageData,k as default};
+import{_ as a,c as o,o as s,x as e,a as t}from"./chunks/framework.0799945b.js";const b=JSON.parse('{"title":"Utilities","description":"","frontmatter":{},"headers":[],"relativePath":"guide/creating-your-project/utils.md","lastUpdated":1681880763000}'),i={name:"guide/creating-your-project/utils.md"},n=e("h1",{id:"utilities",tabindex:"-1"},[t("Utilities "),e("a",{class:"header-anchor",href:"#utilities","aria-label":'Permalink to "Utilities"'},"​")],-1),r=e("p",null,"There are often concepts that aren't inherent to a single feature, but rather work with joining different features together. For example, a reset clickable that activates a conversion and resets a tree, which happens to be a common use case but isn't inherent to clickables, conversions, or trees.",-1),c=e("p",null,[t("These are perfect situations for utilities, and so to encourage creators to learn to identify and take advantage of these situations, a file called "),e("code",null,"src/data/common.tsx"),t(" has been created to demo some of the more common utility functions a project might use. Adding new utilities to this file is encouraged, as is creating utils in general. It also works as a good stepping stone to creating your own features.")],-1),l=[n,r,c];function d(u,h,p,f,m,_){return s(),o("div",null,l)}const k=a(i,[["render",d]]);export{b as __pageData,k as default};
diff --git a/assets/guide_getting-started_examples.md.fb789ba9.js b/assets/guide_getting-started_examples.md.34b6f344.js
similarity index 97%
rename from assets/guide_getting-started_examples.md.fb789ba9.js
rename to assets/guide_getting-started_examples.md.34b6f344.js
index 50e192f5..df4d8810 100644
--- a/assets/guide_getting-started_examples.md.fb789ba9.js
+++ b/assets/guide_getting-started_examples.md.34b6f344.js
@@ -1 +1 @@
-import{_ as o,c as n,x as e,a as t,C as a,o as s,D as i}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Example Projects","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/examples.md","lastUpdated":1681878045000}'),l={name:"guide/getting-started/examples.md"},c=e("h1",{id:"example-projects",tabindex:"-1"},[t("Example Projects "),e("a",{class:"header-anchor",href:"#example-projects","aria-label":'Permalink to "Example Projects"'},"​")],-1),d={id:"advent-incremental",tabindex:"-1"},p=e("a",{class:"header-anchor",href:"#advent-incremental","aria-label":'Permalink to "Advent Incremental "'},"​",-1),h=e("p",null,[e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://www.thepaperpilot.org/advent/",target:"_blank",rel:"noreferrer"},"View Project")],-1),m=e("p",null,[t("An incremental game with 25 different layers of content. A good example of what a large project looks like. There's also a partial port to 0.6 available "),e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/tree/next",target:"_blank",rel:"noreferrer"},"here"),t(".")],-1),f={id:"primordia",tabindex:"-1"},_=e("a",{class:"header-anchor",href:"#primordia","aria-label":'Permalink to "Primordia "'},"​",-1),g=e("p",null,[e("a",{href:"https://github.com/Jacorb90/Primordial-Tree",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://jacorb90.me/Primordial-Tree/",target:"_blank",rel:"noreferrer"},"View Project")],-1),u=e("p",null,'A "The Prestige Tree" style incremental game, developed by the original creator of TPT.',-1),b={id:"tmt-demo",tabindex:"-1"},x=e("a",{class:"header-anchor",href:"#tmt-demo","aria-label":'Permalink to "TMT-Demo "'},"​",-1),P=e("p",null,[e("a",{href:"https://github.com/profectus-engine/tmt-demo",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://profectus-engine.github.io/TMT-Demo/",target:"_blank",rel:"noreferrer"},"View Project")],-1),T=e("p",null,"A project loosely based off the Demo project for TMT. Uses most of the different features of Profectus, but doesn't have any real gameplay.",-1);function k(w,v,j,y,V,B){const r=i("Badge");return s(),n("div",null,[c,e("h2",d,[t("Advent Incremental "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),p]),h,m,e("h2",f,[t("Primordia "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),_]),g,u,e("h2",b,[t("TMT-Demo "),a(r,{type:"tip",text:"Profectus 0.6"}),t(),x]),P,T])}const E=o(l,[["render",k]]);export{D as __pageData,E as default};
+import{_ as o,c as n,x as e,a as t,C as a,o as s,D as i}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Example Projects","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/examples.md","lastUpdated":1681880763000}'),l={name:"guide/getting-started/examples.md"},c=e("h1",{id:"example-projects",tabindex:"-1"},[t("Example Projects "),e("a",{class:"header-anchor",href:"#example-projects","aria-label":'Permalink to "Example Projects"'},"​")],-1),d={id:"advent-incremental",tabindex:"-1"},p=e("a",{class:"header-anchor",href:"#advent-incremental","aria-label":'Permalink to "Advent Incremental "'},"​",-1),h=e("p",null,[e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://www.thepaperpilot.org/advent/",target:"_blank",rel:"noreferrer"},"View Project")],-1),m=e("p",null,[t("An incremental game with 25 different layers of content. A good example of what a large project looks like. There's also a partial port to 0.6 available "),e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/tree/next",target:"_blank",rel:"noreferrer"},"here"),t(".")],-1),f={id:"primordia",tabindex:"-1"},_=e("a",{class:"header-anchor",href:"#primordia","aria-label":'Permalink to "Primordia "'},"​",-1),g=e("p",null,[e("a",{href:"https://github.com/Jacorb90/Primordial-Tree",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://jacorb90.me/Primordial-Tree/",target:"_blank",rel:"noreferrer"},"View Project")],-1),u=e("p",null,'A "The Prestige Tree" style incremental game, developed by the original creator of TPT.',-1),b={id:"tmt-demo",tabindex:"-1"},x=e("a",{class:"header-anchor",href:"#tmt-demo","aria-label":'Permalink to "TMT-Demo "'},"​",-1),P=e("p",null,[e("a",{href:"https://github.com/profectus-engine/tmt-demo",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://profectus-engine.github.io/TMT-Demo/",target:"_blank",rel:"noreferrer"},"View Project")],-1),T=e("p",null,"A project loosely based off the Demo project for TMT. Uses most of the different features of Profectus, but doesn't have any real gameplay.",-1);function k(w,v,j,y,V,B){const r=i("Badge");return s(),n("div",null,[c,e("h2",d,[t("Advent Incremental "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),p]),h,m,e("h2",f,[t("Primordia "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),_]),g,u,e("h2",b,[t("TMT-Demo "),a(r,{type:"tip",text:"Profectus 0.6"}),t(),x]),P,T])}const E=o(l,[["render",k]]);export{D as __pageData,E as default};
diff --git a/assets/guide_getting-started_examples.md.fb789ba9.lean.js b/assets/guide_getting-started_examples.md.34b6f344.lean.js
similarity index 97%
rename from assets/guide_getting-started_examples.md.fb789ba9.lean.js
rename to assets/guide_getting-started_examples.md.34b6f344.lean.js
index 50e192f5..df4d8810 100644
--- a/assets/guide_getting-started_examples.md.fb789ba9.lean.js
+++ b/assets/guide_getting-started_examples.md.34b6f344.lean.js
@@ -1 +1 @@
-import{_ as o,c as n,x as e,a as t,C as a,o as s,D as i}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Example Projects","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/examples.md","lastUpdated":1681878045000}'),l={name:"guide/getting-started/examples.md"},c=e("h1",{id:"example-projects",tabindex:"-1"},[t("Example Projects "),e("a",{class:"header-anchor",href:"#example-projects","aria-label":'Permalink to "Example Projects"'},"​")],-1),d={id:"advent-incremental",tabindex:"-1"},p=e("a",{class:"header-anchor",href:"#advent-incremental","aria-label":'Permalink to "Advent Incremental "'},"​",-1),h=e("p",null,[e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://www.thepaperpilot.org/advent/",target:"_blank",rel:"noreferrer"},"View Project")],-1),m=e("p",null,[t("An incremental game with 25 different layers of content. A good example of what a large project looks like. There's also a partial port to 0.6 available "),e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/tree/next",target:"_blank",rel:"noreferrer"},"here"),t(".")],-1),f={id:"primordia",tabindex:"-1"},_=e("a",{class:"header-anchor",href:"#primordia","aria-label":'Permalink to "Primordia "'},"​",-1),g=e("p",null,[e("a",{href:"https://github.com/Jacorb90/Primordial-Tree",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://jacorb90.me/Primordial-Tree/",target:"_blank",rel:"noreferrer"},"View Project")],-1),u=e("p",null,'A "The Prestige Tree" style incremental game, developed by the original creator of TPT.',-1),b={id:"tmt-demo",tabindex:"-1"},x=e("a",{class:"header-anchor",href:"#tmt-demo","aria-label":'Permalink to "TMT-Demo "'},"​",-1),P=e("p",null,[e("a",{href:"https://github.com/profectus-engine/tmt-demo",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://profectus-engine.github.io/TMT-Demo/",target:"_blank",rel:"noreferrer"},"View Project")],-1),T=e("p",null,"A project loosely based off the Demo project for TMT. Uses most of the different features of Profectus, but doesn't have any real gameplay.",-1);function k(w,v,j,y,V,B){const r=i("Badge");return s(),n("div",null,[c,e("h2",d,[t("Advent Incremental "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),p]),h,m,e("h2",f,[t("Primordia "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),_]),g,u,e("h2",b,[t("TMT-Demo "),a(r,{type:"tip",text:"Profectus 0.6"}),t(),x]),P,T])}const E=o(l,[["render",k]]);export{D as __pageData,E as default};
+import{_ as o,c as n,x as e,a as t,C as a,o as s,D as i}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Example Projects","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/examples.md","lastUpdated":1681880763000}'),l={name:"guide/getting-started/examples.md"},c=e("h1",{id:"example-projects",tabindex:"-1"},[t("Example Projects "),e("a",{class:"header-anchor",href:"#example-projects","aria-label":'Permalink to "Example Projects"'},"​")],-1),d={id:"advent-incremental",tabindex:"-1"},p=e("a",{class:"header-anchor",href:"#advent-incremental","aria-label":'Permalink to "Advent Incremental "'},"​",-1),h=e("p",null,[e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://www.thepaperpilot.org/advent/",target:"_blank",rel:"noreferrer"},"View Project")],-1),m=e("p",null,[t("An incremental game with 25 different layers of content. A good example of what a large project looks like. There's also a partial port to 0.6 available "),e("a",{href:"https://github.com/thepaperpilot/advent-Incremental/tree/next",target:"_blank",rel:"noreferrer"},"here"),t(".")],-1),f={id:"primordia",tabindex:"-1"},_=e("a",{class:"header-anchor",href:"#primordia","aria-label":'Permalink to "Primordia "'},"​",-1),g=e("p",null,[e("a",{href:"https://github.com/Jacorb90/Primordial-Tree",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://jacorb90.me/Primordial-Tree/",target:"_blank",rel:"noreferrer"},"View Project")],-1),u=e("p",null,'A "The Prestige Tree" style incremental game, developed by the original creator of TPT.',-1),b={id:"tmt-demo",tabindex:"-1"},x=e("a",{class:"header-anchor",href:"#tmt-demo","aria-label":'Permalink to "TMT-Demo "'},"​",-1),P=e("p",null,[e("a",{href:"https://github.com/profectus-engine/tmt-demo",target:"_blank",rel:"noreferrer"},"View Source"),t(" | "),e("a",{href:"https://profectus-engine.github.io/TMT-Demo/",target:"_blank",rel:"noreferrer"},"View Project")],-1),T=e("p",null,"A project loosely based off the Demo project for TMT. Uses most of the different features of Profectus, but doesn't have any real gameplay.",-1);function k(w,v,j,y,V,B){const r=i("Badge");return s(),n("div",null,[c,e("h2",d,[t("Advent Incremental "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),p]),h,m,e("h2",f,[t("Primordia "),a(r,{type:"warning",text:"Profectus 0.5"}),t(),_]),g,u,e("h2",b,[t("TMT-Demo "),a(r,{type:"tip",text:"Profectus 0.6"}),t(),x]),P,T])}const E=o(l,[["render",k]]);export{D as __pageData,E as default};
diff --git a/assets/guide_getting-started_first-layer.md.59823253.js b/assets/guide_getting-started_first-layer.md.fd59573f.js
similarity index 99%
rename from assets/guide_getting-started_first-layer.md.59823253.js
rename to assets/guide_getting-started_first-layer.md.fd59573f.js
index 3991e0da..84a28674 100644
--- a/assets/guide_getting-started_first-layer.md.59823253.js
+++ b/assets/guide_getting-started_first-layer.md.fd59573f.js
@@ -1,4 +1,4 @@
-import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Your First Layer","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/first-layer.md","lastUpdated":1681878045000}'),o={name:"guide/getting-started/first-layer.md"},l=e(`
The template comes with a layer in projEntry.tsx and another in prestige.tsx. You can use those as a base instead of creating a new one from scratch.
To add a new layer, first create it via the createLayer function. You typically create a single layer per file, the first being in projEntry. After it is created, you'll need to add it to the returned array in getInitialLayers.
The createLayer function will need a unique ID for your layer and a function that constructs the layer. At a minimum, it needs a display property so Profectus knows what to render. It will look something like this:
ts
const id ="p";
+import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Your First Layer","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/first-layer.md","lastUpdated":1681880763000}'),o={name:"guide/getting-started/first-layer.md"},l=e(`
The template comes with a layer in projEntry.tsx and another in prestige.tsx. You can use those as a base instead of creating a new one from scratch.
To add a new layer, first create it via the createLayer function. You typically create a single layer per file, the first being in projEntry. After it is created, you'll need to add it to the returned array in getInitialLayers.
The createLayer function will need a unique ID for your layer and a function that constructs the layer. At a minimum, it needs a display property so Profectus knows what to render. It will look something like this:
ts
const id ="p";const layer =createLayer(id,function(this:BaseLayer){return{ display:jsx(()=> <>Mylayer</>)
diff --git a/assets/guide_getting-started_first-layer.md.59823253.lean.js b/assets/guide_getting-started_first-layer.md.fd59573f.lean.js
similarity index 85%
rename from assets/guide_getting-started_first-layer.md.59823253.lean.js
rename to assets/guide_getting-started_first-layer.md.fd59573f.lean.js
index b6c4a619..43489a46 100644
--- a/assets/guide_getting-started_first-layer.md.59823253.lean.js
+++ b/assets/guide_getting-started_first-layer.md.fd59573f.lean.js
@@ -1 +1 @@
-import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Your First Layer","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/first-layer.md","lastUpdated":1681878045000}'),o={name:"guide/getting-started/first-layer.md"},l=e("",32),p=[l];function t(r,c,i,y,D,F){return n(),a("div",null,p)}const C=s(o,[["render",t]]);export{d as __pageData,C as default};
+import{_ as s,c as a,o as n,N as e}from"./chunks/framework.0799945b.js";const d=JSON.parse('{"title":"Your First Layer","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/first-layer.md","lastUpdated":1681880763000}'),o={name:"guide/getting-started/first-layer.md"},l=e("",32),p=[l];function t(r,c,i,y,D,F){return n(),a("div",null,p)}const C=s(o,[["render",t]]);export{d as __pageData,C as default};
diff --git a/assets/guide_getting-started_setup.md.43cc29ed.js b/assets/guide_getting-started_setup.md.114644a7.js
similarity index 99%
rename from assets/guide_getting-started_setup.md.43cc29ed.js
rename to assets/guide_getting-started_setup.md.114644a7.js
index e2c0a50b..a083cfb9 100644
--- a/assets/guide_getting-started_setup.md.43cc29ed.js
+++ b/assets/guide_getting-started_setup.md.114644a7.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const r="/assets/workflow-perms.afbb596c.png",i="/assets/actionsbutton.f1ba9d8e.png",n="/assets/gh-pages.a24cefcf.png",y=JSON.parse('{"title":"Setting Up","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/setup.md","lastUpdated":1681878045000}'),s={name:"guide/getting-started/setup.md"},l=a('
Profectus requires a Node.js development environment for working on a project. If you are comfortable with the command line, a local development environment is recommended.
Create a new project from the Profectus repository by clicking the "Use this template" button. Then, clone the repository locally using the provided link.
INFO
The template repository allows easy creation of multiple projects from one repository. However, updating an existing project to a newer version of Profectus can be challenging. Consider updating Profectusbefore starting development to avoid issues with unrelated histories.
It's recommended to create a new Git branch for development, allowing you to push changes without affecting the live build. The GitHub workflow will automatically rebuild the page when you push to the main branch.
Next, install Profectus' dependencies by running npm install. Run npm run serve to start a local server hosting your project. The site will automatically reload as you modify files.
Also, follow the steps to update Profectus before starting to make future updates easier without worrying about unrelated histories.
Using Git, the repository's workflow action automates deployment. However, you need to grant write permissions for the action in the repository settings. Go to Actions, General, Workflow permissions, and select "Read and write permissions".
To deploy, push changes to the main branch. The site will be updated automatically in a few minutes. Check progress or errors from the Actions tab on your repository.
Enable GitHub Pages in the repo settings to host the generated site. Select the gh-pages branch. Perform this step once. This will automatically start another GitHub action to deploy the website.
As an alternative to local development, you may use Replit. Replit sets up your development and hosts your project.
On the free plan, you'll face limitations, and the program may need occasional startups.
To create a Profectus project on Replit, all you have to do is click this button:
Click the "Run" button at the top of the screen to start development. This will also make the project publicly accessible, essentially auto-deploying it. However, this means you cannot separate your development and production environments.
Glitch is a site similar to Replit, with many of the same pros and cons. To create a Profectus project on Glitch, select "New Project", "Import from GitHub", and enter profectus-engine/Profectus. The new project will be automatically configured and ready to go.
',30),p=[l];function c(u,d,h,m,g,f){return o(),t("div",null,p)}const v=e(s,[["render",c]]);export{y as __pageData,v as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const r="/assets/workflow-perms.afbb596c.png",i="/assets/actionsbutton.f1ba9d8e.png",n="/assets/gh-pages.a24cefcf.png",y=JSON.parse('{"title":"Setting Up","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/setup.md","lastUpdated":1681880763000}'),s={name:"guide/getting-started/setup.md"},l=a('
Profectus requires a Node.js development environment for working on a project. If you are comfortable with the command line, a local development environment is recommended.
Create a new project from the Profectus repository by clicking the "Use this template" button. Then, clone the repository locally using the provided link.
INFO
The template repository allows easy creation of multiple projects from one repository. However, updating an existing project to a newer version of Profectus can be challenging. Consider updating Profectusbefore starting development to avoid issues with unrelated histories.
It's recommended to create a new Git branch for development, allowing you to push changes without affecting the live build. The GitHub workflow will automatically rebuild the page when you push to the main branch.
Next, install Profectus' dependencies by running npm install. Run npm run serve to start a local server hosting your project. The site will automatically reload as you modify files.
Also, follow the steps to update Profectus before starting to make future updates easier without worrying about unrelated histories.
Using Git, the repository's workflow action automates deployment. However, you need to grant write permissions for the action in the repository settings. Go to Actions, General, Workflow permissions, and select "Read and write permissions".
To deploy, push changes to the main branch. The site will be updated automatically in a few minutes. Check progress or errors from the Actions tab on your repository.
Enable GitHub Pages in the repo settings to host the generated site. Select the gh-pages branch. Perform this step once. This will automatically start another GitHub action to deploy the website.
As an alternative to local development, you may use Replit. Replit sets up your development and hosts your project.
On the free plan, you'll face limitations, and the program may need occasional startups.
To create a Profectus project on Replit, all you have to do is click this button:
Click the "Run" button at the top of the screen to start development. This will also make the project publicly accessible, essentially auto-deploying it. However, this means you cannot separate your development and production environments.
Glitch is a site similar to Replit, with many of the same pros and cons. To create a Profectus project on Glitch, select "New Project", "Import from GitHub", and enter profectus-engine/Profectus. The new project will be automatically configured and ready to go.
',30),p=[l];function c(u,d,h,m,g,f){return o(),t("div",null,p)}const v=e(s,[["render",c]]);export{y as __pageData,v as default};
diff --git a/assets/guide_getting-started_setup.md.43cc29ed.lean.js b/assets/guide_getting-started_setup.md.114644a7.lean.js
similarity index 87%
rename from assets/guide_getting-started_setup.md.43cc29ed.lean.js
rename to assets/guide_getting-started_setup.md.114644a7.lean.js
index 912375d2..1b105d51 100644
--- a/assets/guide_getting-started_setup.md.43cc29ed.lean.js
+++ b/assets/guide_getting-started_setup.md.114644a7.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const r="/assets/workflow-perms.afbb596c.png",i="/assets/actionsbutton.f1ba9d8e.png",n="/assets/gh-pages.a24cefcf.png",y=JSON.parse('{"title":"Setting Up","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/setup.md","lastUpdated":1681878045000}'),s={name:"guide/getting-started/setup.md"},l=a("",30),p=[l];function c(u,d,h,m,g,f){return o(),t("div",null,p)}const v=e(s,[["render",c]]);export{y as __pageData,v as default};
+import{_ as e,c as t,o,N as a}from"./chunks/framework.0799945b.js";const r="/assets/workflow-perms.afbb596c.png",i="/assets/actionsbutton.f1ba9d8e.png",n="/assets/gh-pages.a24cefcf.png",y=JSON.parse('{"title":"Setting Up","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/setup.md","lastUpdated":1681880763000}'),s={name:"guide/getting-started/setup.md"},l=a("",30),p=[l];function c(u,d,h,m,g,f){return o(),t("div",null,p)}const v=e(s,[["render",c]]);export{y as __pageData,v as default};
diff --git a/assets/guide_getting-started_updating.md.0eb1ee3c.js b/assets/guide_getting-started_updating.md.b60594d2.js
similarity index 98%
rename from assets/guide_getting-started_updating.md.0eb1ee3c.js
rename to assets/guide_getting-started_updating.md.b60594d2.js
index 38c1c0d2..dc467f0b 100644
--- a/assets/guide_getting-started_updating.md.0eb1ee3c.js
+++ b/assets/guide_getting-started_updating.md.b60594d2.js
@@ -1,3 +1,3 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Updating Profectus","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/updating.md","lastUpdated":1681878045000}'),s={name:"guide/getting-started/updating.md"},n=o(`
Due to Profectus being a template repository, your projects do not share a git history with Profectus. To update changes, you will need to run the following:
bash
gitremoteaddtemplatehttps://github.com/profectus-engine/Profectus
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Updating Profectus","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/updating.md","lastUpdated":1681880763000}'),s={name:"guide/getting-started/updating.md"},n=o(`
Due to Profectus being a template repository, your projects do not share a git history with Profectus. To update changes, you will need to run the following:
The first command only has to be performed once. The third command may require you to merge conflicts between code both you and Profectus have changed - however, due to the modularity of Profectus, this should be fairly rare. Unfortunately, due to the unrelated histories the first time you do this every change will be marked as a conflict, and you'll need to accept each one.
The sidebar has a tab labeled "Version Control", which you can use to merge all changes made to Profectus into your project. Unfortunately, Replit does not have a merge tool so this process may irrecoverably erase changes you've made - I'd recommend making a backup first.
Unfortunately, Glitch does not provide any method by which to update a project from a Github repository. If you've only changed things in the data folder you may consider creating a new project, importing the current version of Profectus, and then placing your data folder in the new project.
`,9),r=[n];function l(i,c,p,d,h,u){return a(),t("div",null,r)}const m=e(s,[["render",l]]);export{g as __pageData,m as default};
diff --git a/assets/guide_getting-started_updating.md.0eb1ee3c.lean.js b/assets/guide_getting-started_updating.md.b60594d2.lean.js
similarity index 85%
rename from assets/guide_getting-started_updating.md.0eb1ee3c.lean.js
rename to assets/guide_getting-started_updating.md.b60594d2.lean.js
index e56f50e8..7d4778b9 100644
--- a/assets/guide_getting-started_updating.md.0eb1ee3c.lean.js
+++ b/assets/guide_getting-started_updating.md.b60594d2.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Updating Profectus","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/updating.md","lastUpdated":1681878045000}'),s={name:"guide/getting-started/updating.md"},n=o("",9),r=[n];function l(i,c,p,d,h,u){return a(),t("div",null,r)}const m=e(s,[["render",l]]);export{g as __pageData,m as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const g=JSON.parse('{"title":"Updating Profectus","description":"","frontmatter":{},"headers":[],"relativePath":"guide/getting-started/updating.md","lastUpdated":1681880763000}'),s={name:"guide/getting-started/updating.md"},n=o("",9),r=[n];function l(i,c,p,d,h,u){return a(),t("div",null,r)}const m=e(s,[["render",l]]);export{g as __pageData,m as default};
diff --git a/assets/guide_important-concepts_coercable.md.bb8af927.js b/assets/guide_important-concepts_coercable.md.7f79c379.js
similarity index 99%
rename from assets/guide_important-concepts_coercable.md.bb8af927.js
rename to assets/guide_important-concepts_coercable.md.7f79c379.js
index e315ea73..0dc52b77 100644
--- a/assets/guide_important-concepts_coercable.md.bb8af927.js
+++ b/assets/guide_important-concepts_coercable.md.7f79c379.js
@@ -1,4 +1,4 @@
-import{_ as e,c as a,o as s,N as n}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Coercable Components","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/coercable.md","lastUpdated":1681878045000}'),o={name:"guide/important-concepts/coercable.md"},t=n(`
Most times a feature has some sort of dynamic display, it'll allow you to pass a "Coercable Component", or rather, something that can be coerced into a Vue component. This page goes over the different types of values you can use
If you provide a string, it will be wrapped in a component using it as the template. This is the simplest method, although not suitable for complex displays, and realistically cannot use Vue components as none are registered globally (by default). Recommended for static or simple dynamic displays, such as displays on features.
Template strings need to be wrapped in some HTML element. By default, they'll be wrapped in a <span> element, although certain features may wrap things in div or header elements instead, as appropriate.
You can provide a render function and it will be wrapped in a component as well. The intended use for this is to write JSX inside a function, which will get automatically converted into a render function. You can read more about that process on the Vue docs on Render Functions & JSX. Note that JSX must be returned in a function - it does not work "standalone". The CoercableComponent type will enforce this for you.
JSX can use imported components, making this suited for writing the display properties on things like Tabs or Layers. There are also built-in functions to render features (either as their own or in a layout via renderRow and renderCol), so you don't need to import the Vue component for every feature you plan on using.
Typically a feature will accept a Computable<CoercableComponent>, which means functions would (normally) be wrapped in a computed (see Computable for more details). This would break render functions, so when passing a render function as a CoercableComponent it must be specially marked that it shouldn't be cached. You can use the built-in jsx function to mark a function for you.
{
+import{_ as e,c as a,o as s,N as n}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Coercable Components","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/coercable.md","lastUpdated":1681880763000}'),o={name:"guide/important-concepts/coercable.md"},t=n(`
Most times a feature has some sort of dynamic display, it'll allow you to pass a "Coercable Component", or rather, something that can be coerced into a Vue component. This page goes over the different types of values you can use
If you provide a string, it will be wrapped in a component using it as the template. This is the simplest method, although not suitable for complex displays, and realistically cannot use Vue components as none are registered globally (by default). Recommended for static or simple dynamic displays, such as displays on features.
Template strings need to be wrapped in some HTML element. By default, they'll be wrapped in a <span> element, although certain features may wrap things in div or header elements instead, as appropriate.
You can provide a render function and it will be wrapped in a component as well. The intended use for this is to write JSX inside a function, which will get automatically converted into a render function. You can read more about that process on the Vue docs on Render Functions & JSX. Note that JSX must be returned in a function - it does not work "standalone". The CoercableComponent type will enforce this for you.
JSX can use imported components, making this suited for writing the display properties on things like Tabs or Layers. There are also built-in functions to render features (either as their own or in a layout via renderRow and renderCol), so you don't need to import the Vue component for every feature you plan on using.
Typically a feature will accept a Computable<CoercableComponent>, which means functions would (normally) be wrapped in a computed (see Computable for more details). This would break render functions, so when passing a render function as a CoercableComponent it must be specially marked that it shouldn't be cached. You can use the built-in jsx function to mark a function for you.
{display:jsx(()=> (<><MainDisplayresource={points}color={color}/>
diff --git a/assets/guide_important-concepts_coercable.md.bb8af927.lean.js b/assets/guide_important-concepts_coercable.md.7f79c379.lean.js
similarity index 85%
rename from assets/guide_important-concepts_coercable.md.bb8af927.lean.js
rename to assets/guide_important-concepts_coercable.md.7f79c379.lean.js
index 79934e35..d8c2dcab 100644
--- a/assets/guide_important-concepts_coercable.md.bb8af927.lean.js
+++ b/assets/guide_important-concepts_coercable.md.7f79c379.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o as s,N as n}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Coercable Components","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/coercable.md","lastUpdated":1681878045000}'),o={name:"guide/important-concepts/coercable.md"},t=n("",13),l=[t];function p(r,c,i,d,u,y){return s(),a("div",null,l)}const F=e(o,[["render",p]]);export{h as __pageData,F as default};
+import{_ as e,c as a,o as s,N as n}from"./chunks/framework.0799945b.js";const h=JSON.parse('{"title":"Coercable Components","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/coercable.md","lastUpdated":1681880763000}'),o={name:"guide/important-concepts/coercable.md"},t=n("",13),l=[t];function p(r,c,i,d,u,y){return s(),a("div",null,l)}const F=e(o,[["render",p]]);export{h as __pageData,F as default};
diff --git a/assets/guide_important-concepts_features.md.398c5921.js b/assets/guide_important-concepts_features.md.96e4ae56.js
similarity index 99%
rename from assets/guide_important-concepts_features.md.398c5921.js
rename to assets/guide_important-concepts_features.md.96e4ae56.js
index 148e123f..aead1d4a 100644
--- a/assets/guide_important-concepts_features.md.398c5921.js
+++ b/assets/guide_important-concepts_features.md.96e4ae56.js
@@ -1,4 +1,4 @@
-import{_ as e,c as s,o as a,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/features.md","lastUpdated":1681878045000}'),t={name:"guide/important-concepts/features.md"},o=n(`
A layer is made up of features. There are many types of features included in Profectus, and more can be created once you become familiar with the engine.
To create a feature, the feature type will have one or more functions to help you. They'll typically look something like this:
ts
const addGainUpgrade =createUpgrade(()=> ({
+import{_ as e,c as s,o as a,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/features.md","lastUpdated":1681880763000}'),t={name:"guide/important-concepts/features.md"},o=n(`
A layer is made up of features. There are many types of features included in Profectus, and more can be created once you become familiar with the engine.
To create a feature, the feature type will have one or more functions to help you. They'll typically look something like this:
ts
const addGainUpgrade =createUpgrade(()=> ({display:{title:"Generator of Genericness",description:"Gain 1 point every second"
diff --git a/assets/guide_important-concepts_features.md.398c5921.lean.js b/assets/guide_important-concepts_features.md.96e4ae56.lean.js
similarity index 84%
rename from assets/guide_important-concepts_features.md.398c5921.lean.js
rename to assets/guide_important-concepts_features.md.96e4ae56.lean.js
index f92c7b73..8f34c03a 100644
--- a/assets/guide_important-concepts_features.md.398c5921.lean.js
+++ b/assets/guide_important-concepts_features.md.96e4ae56.lean.js
@@ -1 +1 @@
-import{_ as e,c as s,o as a,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/features.md","lastUpdated":1681878045000}'),t={name:"guide/important-concepts/features.md"},o=n("",12),l=[o];function p(r,c,i,y,d,u){return a(),s("div",null,l)}const C=e(t,[["render",p]]);export{D as __pageData,C as default};
+import{_ as e,c as s,o as a,N as n}from"./chunks/framework.0799945b.js";const D=JSON.parse('{"title":"Features","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/features.md","lastUpdated":1681880763000}'),t={name:"guide/important-concepts/features.md"},o=n("",12),l=[o];function p(r,c,i,y,d,u){return a(),s("div",null,l)}const C=e(t,[["render",p]]);export{D as __pageData,C as default};
diff --git a/assets/guide_important-concepts_formulas.md.2ee3b037.js b/assets/guide_important-concepts_formulas.md.580bb12f.js
similarity index 99%
rename from assets/guide_important-concepts_formulas.md.2ee3b037.js
rename to assets/guide_important-concepts_formulas.md.580bb12f.js
index acfc8088..9f60adae 100644
--- a/assets/guide_important-concepts_formulas.md.2ee3b037.js
+++ b/assets/guide_important-concepts_formulas.md.580bb12f.js
@@ -1,4 +1,4 @@
-import{_ as e,c as a,o as s,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Formulas","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/formulas.md","lastUpdated":1681878045000}'),n={name:"guide/important-concepts/formulas.md"},t=o(`
Profectus utilizes formulas for various features, such as increasing requirements for repeatables and challenges or determining resource gains in conversions. These formulas often need to be inverted or integrated to enable features like buying multiple levels of a repeatable at once or determining when a conversion will increase resource gains. The Formula class can handle these operations, supporting every function Decimal does, while tracking the operations internally.
For example, a cost function like Decimal.pow(this.amount, 1.05).times(100) can be represented using a Formula: Formula.variable(this.amount).pow(1.05).times(100).
ts
const myRepeatable =createRepeatable(()=> ({
+import{_ as e,c as a,o as s,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Formulas","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/formulas.md","lastUpdated":1681880763000}'),n={name:"guide/important-concepts/formulas.md"},t=o(`
Profectus utilizes formulas for various features, such as increasing requirements for repeatables and challenges or determining resource gains in conversions. These formulas often need to be inverted or integrated to enable features like buying multiple levels of a repeatable at once or determining when a conversion will increase resource gains. The Formula class can handle these operations, supporting every function Decimal does, while tracking the operations internally.
For example, a cost function like Decimal.pow(this.amount, 1.05).times(100) can be represented using a Formula: Formula.variable(this.amount).pow(1.05).times(100).
ts
const myRepeatable =createRepeatable(()=> ({requirements:createCostRequirement(()=> ({resource: points,cost: Formula.variable(myRepeatable.amount).pow(1.05).times(100)
diff --git a/assets/guide_important-concepts_formulas.md.2ee3b037.lean.js b/assets/guide_important-concepts_formulas.md.580bb12f.lean.js
similarity index 84%
rename from assets/guide_important-concepts_formulas.md.2ee3b037.lean.js
rename to assets/guide_important-concepts_formulas.md.580bb12f.lean.js
index d0ab84f4..aa91ab7f 100644
--- a/assets/guide_important-concepts_formulas.md.2ee3b037.lean.js
+++ b/assets/guide_important-concepts_formulas.md.580bb12f.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o as s,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Formulas","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/formulas.md","lastUpdated":1681878045000}'),n={name:"guide/important-concepts/formulas.md"},t=o("",18),r=[t];function l(i,p,c,u,h,m){return s(),a("div",null,r)}const y=e(n,[["render",l]]);export{f as __pageData,y as default};
+import{_ as e,c as a,o as s,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Formulas","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/formulas.md","lastUpdated":1681880763000}'),n={name:"guide/important-concepts/formulas.md"},t=o("",18),r=[t];function l(i,p,c,u,h,m){return s(),a("div",null,r)}const y=e(n,[["render",l]]);export{f as __pageData,y as default};
diff --git a/assets/guide_important-concepts_layers.md.dbe23475.js b/assets/guide_important-concepts_layers.md.75cf9109.js
similarity index 96%
rename from assets/guide_important-concepts_layers.md.dbe23475.js
rename to assets/guide_important-concepts_layers.md.75cf9109.js
index 080dcf72..481bd46d 100644
--- a/assets/guide_important-concepts_layers.md.dbe23475.js
+++ b/assets/guide_important-concepts_layers.md.75cf9109.js
@@ -1 +1 @@
-import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/layers.md","lastUpdated":1681878045000}'),o={name:"guide/important-concepts/layers.md"},s=r('
Profectus content is organized into units called "Layers". When displaying content to the user, the screen will be divided into several tabs that each display the content of a layer. These layers are stored in /src/data/layers.
Each layer is ultimately a collection of different features, and a display function. While there are a couple reserved properties for layers, most of its structure is fully up to the creator.
Layers can be dynamically added or removed at any time, which also allows for effectively disabling or enabling content based on arbitrary conditions. Just make sure getInitialLayers can process the player save data object and determine which layers should be currently active.
Layers (and features) are not actually created immediately. Instead, their options are gotten through a function which is then run the first time something inside the layer is accessed. This is a concept called lazy evaluation, which is also used for things like computed, and allows for features to reference each other without worrying about cyclical dependencies.
',6),i=[s];function n(c,l,d,h,y,p){return t(),a("div",null,i)}const _=e(o,[["render",n]]);export{f as __pageData,_ as default};
+import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/layers.md","lastUpdated":1681880763000}'),o={name:"guide/important-concepts/layers.md"},s=r('
Profectus content is organized into units called "Layers". When displaying content to the user, the screen will be divided into several tabs that each display the content of a layer. These layers are stored in /src/data/layers.
Each layer is ultimately a collection of different features, and a display function. While there are a couple reserved properties for layers, most of its structure is fully up to the creator.
Layers can be dynamically added or removed at any time, which also allows for effectively disabling or enabling content based on arbitrary conditions. Just make sure getInitialLayers can process the player save data object and determine which layers should be currently active.
Layers (and features) are not actually created immediately. Instead, their options are gotten through a function which is then run the first time something inside the layer is accessed. This is a concept called lazy evaluation, which is also used for things like computed, and allows for features to reference each other without worrying about cyclical dependencies.
',6),i=[s];function n(c,l,d,h,y,p){return t(),a("div",null,i)}const _=e(o,[["render",n]]);export{f as __pageData,_ as default};
diff --git a/assets/guide_important-concepts_layers.md.dbe23475.lean.js b/assets/guide_important-concepts_layers.md.75cf9109.lean.js
similarity index 84%
rename from assets/guide_important-concepts_layers.md.dbe23475.lean.js
rename to assets/guide_important-concepts_layers.md.75cf9109.lean.js
index 590e6b69..8def4697 100644
--- a/assets/guide_important-concepts_layers.md.dbe23475.lean.js
+++ b/assets/guide_important-concepts_layers.md.75cf9109.lean.js
@@ -1 +1 @@
-import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/layers.md","lastUpdated":1681878045000}'),o={name:"guide/important-concepts/layers.md"},s=r("",6),i=[s];function n(c,l,d,h,y,p){return t(),a("div",null,i)}const _=e(o,[["render",n]]);export{f as __pageData,_ as default};
+import{_ as e,c as a,o as t,N as r}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Layers","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/layers.md","lastUpdated":1681880763000}'),o={name:"guide/important-concepts/layers.md"},s=r("",6),i=[s];function n(c,l,d,h,y,p){return t(),a("div",null,i)}const _=e(o,[["render",n]]);export{f as __pageData,_ as default};
diff --git a/assets/guide_important-concepts_persistence.md.7dd1a275.js b/assets/guide_important-concepts_persistence.md.739ab814.js
similarity index 98%
rename from assets/guide_important-concepts_persistence.md.7dd1a275.js
rename to assets/guide_important-concepts_persistence.md.739ab814.js
index ed52a950..f51757a0 100644
--- a/assets/guide_important-concepts_persistence.md.7dd1a275.js
+++ b/assets/guide_important-concepts_persistence.md.739ab814.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as s}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Persistence","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/persistence.md","lastUpdated":1681878045000}'),r={name:"guide/important-concepts/persistence.md"},n=s('
Persistence refers to data that is saved so that it persists when the user closes the tab and opens it again in the future.
In Profectus, this is handled by creating "persistent refs", which act like refs but whose value is stored in an object that gets saved to localStorage. Other than that you can treat them like any other ref - when adding the layer, any persistent refs will automatically have their values updated to the ones saved in localStorage. If there isn't a saved value, it'll use the default value passed to the persistent ref constructor.
Many features in Profectus, such as upgrades, milestones, and challenges, internally have persistent refs to save things like whether the upgrade has been purchased, the milestone achieved, or the challenge completed. Creators can also create their own custom persistent refs to store any arbitrary (but serializable) data they need - that means Numbers (including big numbers), strings, booleans, or objects containing only serializable values. Another notable function is the resource constructor. If you pass a default value into its constructor, it will automatically create a persistent ref for that resource. If you pass in a ref, it will NOT make the ref persistent.
It's important for saving and loading these properties for these refs to be in a well-known location. This is implemented based on the location of the persistent ref within a layer. That means it's important that all persistent refs are located within the object returned by the createLayer options function. If a persistent ref is not within that object, it will NOT be saved and loaded - regardless of whether it's a persistent ref within a feature, one you manually created, or otherwise.
Additionally, this structure should typically remain consistent between project versions. If a value is in a new location, it will not load the value from localStorage correctly. This is exacerbated if two values swap places, such as when an array is re-ordered. In the event a creator changes this structure anyways, the fixOldSave function can be used to migrate the old player save data to the new structure expected by the current version of the project.
As of Profectus 0.6, save data will now report warnings whenever there is redundancy - two locations for the same persistent data, which creates larger saves that can cause issues when loading after updates. To fix redundancies, wrap all but one location for the data in noPersist.
',7),i=[n];function o(c,l,h,d,p,u){return a(),t("div",null,i)}const w=e(r,[["render",o]]);export{m as __pageData,w as default};
+import{_ as e,c as t,o as a,N as s}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Persistence","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/persistence.md","lastUpdated":1681880763000}'),r={name:"guide/important-concepts/persistence.md"},n=s('
Persistence refers to data that is saved so that it persists when the user closes the tab and opens it again in the future.
In Profectus, this is handled by creating "persistent refs", which act like refs but whose value is stored in an object that gets saved to localStorage. Other than that you can treat them like any other ref - when adding the layer, any persistent refs will automatically have their values updated to the ones saved in localStorage. If there isn't a saved value, it'll use the default value passed to the persistent ref constructor.
Many features in Profectus, such as upgrades, milestones, and challenges, internally have persistent refs to save things like whether the upgrade has been purchased, the milestone achieved, or the challenge completed. Creators can also create their own custom persistent refs to store any arbitrary (but serializable) data they need - that means Numbers (including big numbers), strings, booleans, or objects containing only serializable values. Another notable function is the resource constructor. If you pass a default value into its constructor, it will automatically create a persistent ref for that resource. If you pass in a ref, it will NOT make the ref persistent.
It's important for saving and loading these properties for these refs to be in a well-known location. This is implemented based on the location of the persistent ref within a layer. That means it's important that all persistent refs are located within the object returned by the createLayer options function. If a persistent ref is not within that object, it will NOT be saved and loaded - regardless of whether it's a persistent ref within a feature, one you manually created, or otherwise.
Additionally, this structure should typically remain consistent between project versions. If a value is in a new location, it will not load the value from localStorage correctly. This is exacerbated if two values swap places, such as when an array is re-ordered. In the event a creator changes this structure anyways, the fixOldSave function can be used to migrate the old player save data to the new structure expected by the current version of the project.
As of Profectus 0.6, save data will now report warnings whenever there is redundancy - two locations for the same persistent data, which creates larger saves that can cause issues when loading after updates. To fix redundancies, wrap all but one location for the data in noPersist.
',7),i=[n];function o(c,l,h,d,p,u){return a(),t("div",null,i)}const w=e(r,[["render",o]]);export{m as __pageData,w as default};
diff --git a/assets/guide_important-concepts_persistence.md.7dd1a275.lean.js b/assets/guide_important-concepts_persistence.md.739ab814.lean.js
similarity index 85%
rename from assets/guide_important-concepts_persistence.md.7dd1a275.lean.js
rename to assets/guide_important-concepts_persistence.md.739ab814.lean.js
index cbc3a430..8ea12fec 100644
--- a/assets/guide_important-concepts_persistence.md.7dd1a275.lean.js
+++ b/assets/guide_important-concepts_persistence.md.739ab814.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as s}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Persistence","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/persistence.md","lastUpdated":1681878045000}'),r={name:"guide/important-concepts/persistence.md"},n=s("",7),i=[n];function o(c,l,h,d,p,u){return a(),t("div",null,i)}const w=e(r,[["render",o]]);export{m as __pageData,w as default};
+import{_ as e,c as t,o as a,N as s}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Persistence","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/persistence.md","lastUpdated":1681880763000}'),r={name:"guide/important-concepts/persistence.md"},n=s("",7),i=[n];function o(c,l,h,d,p,u){return a(),t("div",null,i)}const w=e(r,[["render",o]]);export{m as __pageData,w as default};
diff --git a/assets/guide_important-concepts_reactivity.md.f7d1641f.js b/assets/guide_important-concepts_reactivity.md.d97ef4ad.js
similarity index 97%
rename from assets/guide_important-concepts_reactivity.md.f7d1641f.js
rename to assets/guide_important-concepts_reactivity.md.d97ef4ad.js
index 320bb0d7..50c4375e 100644
--- a/assets/guide_important-concepts_reactivity.md.f7d1641f.js
+++ b/assets/guide_important-concepts_reactivity.md.d97ef4ad.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Reactivity","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/reactivity.md","lastUpdated":1681878045000}'),r={name:"guide/important-concepts/reactivity.md"},s=o('
Profectus takes large advantage of Vue's reactivity system. It's recommended to read up on how refs and computed refs work. Ultimately this means that sometimes you'll need to type .value to get the actual value of something, but also you are able to pass things around by reference instead of by value. Indeed, it is recommended to only unwrap the actual value when you actually need it. .value is guaranteed to be correct and up to date only on the exact moment it is accessed.
With a proper IDE, such as Visual Studio Code, you should be able to see whether or not something is a ref or not from type hints. If in doubt, you can always wrap the property in an unref call.
Vue's reactivity is probably the "quirkiest" part of Profectus, and not even the documentation makes all of those quirks clear. It is recommend to read this thread of common misconceptions around Vue reactivity.
Most properties on features will accept Computable values. Computable values can either be a raw value, a ref to the value, or a function that returns the value. In the lattermost case it will be wrapped in computed, turning it into a ref. The feature type will handle it being a ref or a raw value by using unref when accessing those values. With type hints, your IDE should correctly identify these values as refs or raw values so you can treat them as the types they actually are.
Because functions are automatically wrapped in computed for many properties, it might be expected to happen to custom properties you add to a feature that isn't defined by the feature type. These functions will not be wrapped, and if you want it cached you should wrap it in a computed yourself. This does, however, allow you to include custom methods on a feature without worry.
',7),i=[s];function n(c,u,d,l,p,h){return a(),t("div",null,i)}const y=e(r,[["render",n]]);export{f as __pageData,y as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Reactivity","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/reactivity.md","lastUpdated":1681880763000}'),r={name:"guide/important-concepts/reactivity.md"},s=o('
Profectus takes large advantage of Vue's reactivity system. It's recommended to read up on how refs and computed refs work. Ultimately this means that sometimes you'll need to type .value to get the actual value of something, but also you are able to pass things around by reference instead of by value. Indeed, it is recommended to only unwrap the actual value when you actually need it. .value is guaranteed to be correct and up to date only on the exact moment it is accessed.
With a proper IDE, such as Visual Studio Code, you should be able to see whether or not something is a ref or not from type hints. If in doubt, you can always wrap the property in an unref call.
Vue's reactivity is probably the "quirkiest" part of Profectus, and not even the documentation makes all of those quirks clear. It is recommend to read this thread of common misconceptions around Vue reactivity.
Most properties on features will accept Computable values. Computable values can either be a raw value, a ref to the value, or a function that returns the value. In the lattermost case it will be wrapped in computed, turning it into a ref. The feature type will handle it being a ref or a raw value by using unref when accessing those values. With type hints, your IDE should correctly identify these values as refs or raw values so you can treat them as the types they actually are.
Because functions are automatically wrapped in computed for many properties, it might be expected to happen to custom properties you add to a feature that isn't defined by the feature type. These functions will not be wrapped, and if you want it cached you should wrap it in a computed yourself. This does, however, allow you to include custom methods on a feature without worry.
',7),i=[s];function n(c,u,d,l,p,h){return a(),t("div",null,i)}const y=e(r,[["render",n]]);export{f as __pageData,y as default};
diff --git a/assets/guide_important-concepts_reactivity.md.f7d1641f.lean.js b/assets/guide_important-concepts_reactivity.md.d97ef4ad.lean.js
similarity index 85%
rename from assets/guide_important-concepts_reactivity.md.f7d1641f.lean.js
rename to assets/guide_important-concepts_reactivity.md.d97ef4ad.lean.js
index fa217ccd..413ee3fd 100644
--- a/assets/guide_important-concepts_reactivity.md.f7d1641f.lean.js
+++ b/assets/guide_important-concepts_reactivity.md.d97ef4ad.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Reactivity","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/reactivity.md","lastUpdated":1681878045000}'),r={name:"guide/important-concepts/reactivity.md"},s=o("",7),i=[s];function n(c,u,d,l,p,h){return a(),t("div",null,i)}const y=e(r,[["render",n]]);export{f as __pageData,y as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const f=JSON.parse('{"title":"Reactivity","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/reactivity.md","lastUpdated":1681880763000}'),r={name:"guide/important-concepts/reactivity.md"},s=o("",7),i=[s];function n(c,u,d,l,p,h){return a(),t("div",null,i)}const y=e(r,[["render",n]]);export{f as __pageData,y as default};
diff --git a/assets/guide_important-concepts_requirements.md.9f91cdbe.js b/assets/guide_important-concepts_requirements.md.bc54f098.js
similarity index 98%
rename from assets/guide_important-concepts_requirements.md.9f91cdbe.js
rename to assets/guide_important-concepts_requirements.md.bc54f098.js
index 094dafdc..9848cbd4 100644
--- a/assets/guide_important-concepts_requirements.md.9f91cdbe.js
+++ b/assets/guide_important-concepts_requirements.md.bc54f098.js
@@ -1 +1 @@
-import{_ as e,c as t,o as i,N as r}from"./chunks/framework.0799945b.js";const q=JSON.parse('{"title":"Requirements","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/requirements.md","lastUpdated":1681878045000}'),a={name:"guide/important-concepts/requirements.md"},n=r('
The requirements system in Profectus is designed to handle various conditions that must be met before certain actions or features can be accessed by the player. These conditions can include resource amounts, completed challenges, or other milestones within the game.
Several features will have a requirements property that takes one or more requirements that must be fulfilled for a certain action to be performed with that feature.
When implementing requirements, you can use the displayRequirements utility. This utility is designed to give a human-readable string generated by the requirement(s) given, making it easier for players to understand the conditions needed to progress in the game. Typically features that support requirements will already use this utility internally.
You may need to "pay" requirements upon meeting their conditions and performing the associated action. This action typically involves spending resources or making other adjustments to the game state. The payRequirements function simplifies this process by handling the payment for one or more requirements, considering the number of levels to pay for. Additionally, custom pay functions like payByDivision and payByReset can be passed into createCostRequirement for more specialized cases.
Requirements can have multiple "levels", which are typically used for things like multi-level challenges with scaling requirements. When checking if requirements are met, the requirementsMet function can be used. It accepts a single requirement or an array of requirements.
Requirements that are just on/off, such as boolean or visibility requirements, will count as infinite levels when in the same array. This allows you to combine different types of requirements in the same array and use the maxRequirementsMet function to calculate the maximum number of levels that could be acquired with the current requirement states.
',11),s=[n];function o(u,m,l,c,h,d){return i(),t("div",null,s)}const f=e(a,[["render",o]]);export{q as __pageData,f as default};
+import{_ as e,c as t,o as i,N as r}from"./chunks/framework.0799945b.js";const q=JSON.parse('{"title":"Requirements","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/requirements.md","lastUpdated":1681880763000}'),a={name:"guide/important-concepts/requirements.md"},n=r('
The requirements system in Profectus is designed to handle various conditions that must be met before certain actions or features can be accessed by the player. These conditions can include resource amounts, completed challenges, or other milestones within the game.
Several features will have a requirements property that takes one or more requirements that must be fulfilled for a certain action to be performed with that feature.
When implementing requirements, you can use the displayRequirements utility. This utility is designed to give a human-readable string generated by the requirement(s) given, making it easier for players to understand the conditions needed to progress in the game. Typically features that support requirements will already use this utility internally.
You may need to "pay" requirements upon meeting their conditions and performing the associated action. This action typically involves spending resources or making other adjustments to the game state. The payRequirements function simplifies this process by handling the payment for one or more requirements, considering the number of levels to pay for. Additionally, custom pay functions like payByDivision and payByReset can be passed into createCostRequirement for more specialized cases.
Requirements can have multiple "levels", which are typically used for things like multi-level challenges with scaling requirements. When checking if requirements are met, the requirementsMet function can be used. It accepts a single requirement or an array of requirements.
Requirements that are just on/off, such as boolean or visibility requirements, will count as infinite levels when in the same array. This allows you to combine different types of requirements in the same array and use the maxRequirementsMet function to calculate the maximum number of levels that could be acquired with the current requirement states.
',11),s=[n];function o(u,m,l,c,h,d){return i(),t("div",null,s)}const f=e(a,[["render",o]]);export{q as __pageData,f as default};
diff --git a/assets/guide_important-concepts_requirements.md.9f91cdbe.lean.js b/assets/guide_important-concepts_requirements.md.bc54f098.lean.js
similarity index 85%
rename from assets/guide_important-concepts_requirements.md.9f91cdbe.lean.js
rename to assets/guide_important-concepts_requirements.md.bc54f098.lean.js
index 08c5ea52..887abec4 100644
--- a/assets/guide_important-concepts_requirements.md.9f91cdbe.lean.js
+++ b/assets/guide_important-concepts_requirements.md.bc54f098.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as i,N as r}from"./chunks/framework.0799945b.js";const q=JSON.parse('{"title":"Requirements","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/requirements.md","lastUpdated":1681878045000}'),a={name:"guide/important-concepts/requirements.md"},n=r("",11),s=[n];function o(u,m,l,c,h,d){return i(),t("div",null,s)}const f=e(a,[["render",o]]);export{q as __pageData,f as default};
+import{_ as e,c as t,o as i,N as r}from"./chunks/framework.0799945b.js";const q=JSON.parse('{"title":"Requirements","description":"","frontmatter":{},"headers":[],"relativePath":"guide/important-concepts/requirements.md","lastUpdated":1681880763000}'),a={name:"guide/important-concepts/requirements.md"},n=r("",11),s=[n];function o(u,m,l,c,h,d){return i(),t("div",null,s)}const f=e(a,[["render",o]]);export{q as __pageData,f as default};
diff --git a/assets/guide_index.md.e6e5f738.js b/assets/guide_index.md.999c12b6.js
similarity index 98%
rename from assets/guide_index.md.e6e5f738.js
rename to assets/guide_index.md.999c12b6.js
index 99a8e08e..70879b6c 100644
--- a/assets/guide_index.md.e6e5f738.js
+++ b/assets/guide_index.md.999c12b6.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[],"relativePath":"guide/index.md","lastUpdated":1681878045000}'),n={name:"guide/index.md"},r=o('
Profectus is a web-based game engine. You can write your content using many built in features, write your own features, and build up complex gameplay quickly and easily.
The purpose of creating profectus was to create an easy to use engine that does not create a ceiling for a programmer's personal growth. This engine will grow in complexity with you, empowering you to create increasingly complex designs and mechanics.
While this engine is intended to make game development (and web app development) easier, it still requires you to be comfortable with programming in general and javascript in particular. Fortunately, that is a solvable problem.
If you've never used Javascript before, learn-js.org is a good resource for learning the important concepts. If you'd like a more thorough lesson on all the ins and outs of web development, javascript.info and MDN's tutorials should have you covered. MDN is also a great resource to use as a reference - for example, if you want to know more about something and you google it, there'll typically be a MDN link that'll explain it thoroughly.
Beyond the basics, Profectus uses a modern web development pipeline, using tools like node, typescript, and JSX. While most of it should be relatively easy to pick up through context, if this becomes too complicated you may be interested in The Modding Tree, a predecessor of Profectus that uses plain old javascript.
There are many popular game engines out there, such as GameMaker Studio 2, Unity3D, Unreal Engine 4, and Godot, that are all general purpose and also more useful if you're planning on going into a career in game development. These are all more mature and robust game engines compared to Profectus, and are used by actual game development studios.
Profectus, on the other hand, is a very opinionated engine that is better at specific types of projects. Where the above engines will require you to design and create your own interfaces, menus, save management systems, etc. Profectus will include those out of the box. Profectus will also output games that run natively in the browser, and will typically be easier for players to play than traditional engines.
If you are not interested in programming but still want to get into game development, the above engines also all support "visual programming", which may be more amenable to you. Each engine will have varying levels of support, and of course with varying complexities, but ultimately any of these will help you learn the concepts of programming and game development, and all of them also offer traditional programming for when you think you're ready.
',14),i=[r];function s(l,u,h,d,p,c){return a(),t("div",null,i)}const f=e(n,[["render",s]]);export{m as __pageData,f as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[],"relativePath":"guide/index.md","lastUpdated":1681880763000}'),n={name:"guide/index.md"},r=o('
Profectus is a web-based game engine. You can write your content using many built in features, write your own features, and build up complex gameplay quickly and easily.
The purpose of creating profectus was to create an easy to use engine that does not create a ceiling for a programmer's personal growth. This engine will grow in complexity with you, empowering you to create increasingly complex designs and mechanics.
While this engine is intended to make game development (and web app development) easier, it still requires you to be comfortable with programming in general and javascript in particular. Fortunately, that is a solvable problem.
If you've never used Javascript before, learn-js.org is a good resource for learning the important concepts. If you'd like a more thorough lesson on all the ins and outs of web development, javascript.info and MDN's tutorials should have you covered. MDN is also a great resource to use as a reference - for example, if you want to know more about something and you google it, there'll typically be a MDN link that'll explain it thoroughly.
Beyond the basics, Profectus uses a modern web development pipeline, using tools like node, typescript, and JSX. While most of it should be relatively easy to pick up through context, if this becomes too complicated you may be interested in The Modding Tree, a predecessor of Profectus that uses plain old javascript.
There are many popular game engines out there, such as GameMaker Studio 2, Unity3D, Unreal Engine 4, and Godot, that are all general purpose and also more useful if you're planning on going into a career in game development. These are all more mature and robust game engines compared to Profectus, and are used by actual game development studios.
Profectus, on the other hand, is a very opinionated engine that is better at specific types of projects. Where the above engines will require you to design and create your own interfaces, menus, save management systems, etc. Profectus will include those out of the box. Profectus will also output games that run natively in the browser, and will typically be easier for players to play than traditional engines.
If you are not interested in programming but still want to get into game development, the above engines also all support "visual programming", which may be more amenable to you. Each engine will have varying levels of support, and of course with varying complexities, but ultimately any of these will help you learn the concepts of programming and game development, and all of them also offer traditional programming for when you think you're ready.
',14),i=[r];function s(l,u,h,d,p,c){return a(),t("div",null,i)}const f=e(n,[["render",s]]);export{m as __pageData,f as default};
diff --git a/assets/guide_index.md.e6e5f738.lean.js b/assets/guide_index.md.999c12b6.lean.js
similarity index 84%
rename from assets/guide_index.md.e6e5f738.lean.js
rename to assets/guide_index.md.999c12b6.lean.js
index 1d2473eb..bf3d3272 100644
--- a/assets/guide_index.md.e6e5f738.lean.js
+++ b/assets/guide_index.md.999c12b6.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[],"relativePath":"guide/index.md","lastUpdated":1681878045000}'),n={name:"guide/index.md"},r=o("",14),i=[r];function s(l,u,h,d,p,c){return a(),t("div",null,i)}const f=e(n,[["render",s]]);export{m as __pageData,f as default};
+import{_ as e,c as t,o as a,N as o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Introduction","description":"","frontmatter":{"title":"Introduction"},"headers":[],"relativePath":"guide/index.md","lastUpdated":1681880763000}'),n={name:"guide/index.md"},r=o("",14),i=[r];function s(l,u,h,d,p,c){return a(),t("div",null,i)}const f=e(n,[["render",s]]);export{m as __pageData,f as default};
diff --git a/assets/guide_migrations_0-6.md.b3a02ef7.js b/assets/guide_migrations_0-6.md.aefb2bb2.js
similarity index 99%
rename from assets/guide_migrations_0-6.md.b3a02ef7.js
rename to assets/guide_migrations_0-6.md.aefb2bb2.js
index d18ff07a..ec7d2cd7 100644
--- a/assets/guide_migrations_0-6.md.b3a02ef7.js
+++ b/assets/guide_migrations_0-6.md.aefb2bb2.js
@@ -1,4 +1,4 @@
-import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const o="/assets/persistence-error.537e237b.png",d=JSON.parse('{"title":"Migrating to Profectus 0.6","description":"","frontmatter":{},"headers":[],"relativePath":"guide/migrations/0-6.md","lastUpdated":1681878045000}'),l={name:"guide/migrations/0-6.md"},t=n(`
Alongside the standard steps for Updating Profectus, this update contains numerous large or breaking changes. This guide will cover additional steps to follow after updating Profectus.
This update introduces a major change in save data collection and storage. The change reduces save data size and fixes issues that can cause persistent values to reset to default values. Unfortunately, developers will need to mark which persistent value uses should be included in the save data and which are merely references. Let's go through an example:
ts
const flowers =createResource<DecimalSource>(0,"moly");
+import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const o="/assets/persistence-error.537e237b.png",d=JSON.parse('{"title":"Migrating to Profectus 0.6","description":"","frontmatter":{},"headers":[],"relativePath":"guide/migrations/0-6.md","lastUpdated":1681880763000}'),l={name:"guide/migrations/0-6.md"},t=n(`
Alongside the standard steps for Updating Profectus, this update contains numerous large or breaking changes. This guide will cover additional steps to follow after updating Profectus.
This update introduces a major change in save data collection and storage. The change reduces save data size and fixes issues that can cause persistent values to reset to default values. Unfortunately, developers will need to mark which persistent value uses should be included in the save data and which are merely references. Let's go through an example:
ts
const flowers =createResource<DecimalSource>(0,"moly");const job =createJob(name,()=> ({/** snip **/resource: flowers
diff --git a/assets/guide_migrations_0-6.md.b3a02ef7.lean.js b/assets/guide_migrations_0-6.md.aefb2bb2.lean.js
similarity index 86%
rename from assets/guide_migrations_0-6.md.b3a02ef7.lean.js
rename to assets/guide_migrations_0-6.md.aefb2bb2.lean.js
index ca61593c..1d0b944f 100644
--- a/assets/guide_migrations_0-6.md.b3a02ef7.lean.js
+++ b/assets/guide_migrations_0-6.md.aefb2bb2.lean.js
@@ -1 +1 @@
-import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const o="/assets/persistence-error.537e237b.png",d=JSON.parse('{"title":"Migrating to Profectus 0.6","description":"","frontmatter":{},"headers":[],"relativePath":"guide/migrations/0-6.md","lastUpdated":1681878045000}'),l={name:"guide/migrations/0-6.md"},t=n("",50),p=[t];function r(c,i,y,D,A,C){return a(),e("div",null,p)}const u=s(l,[["render",r]]);export{d as __pageData,u as default};
+import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const o="/assets/persistence-error.537e237b.png",d=JSON.parse('{"title":"Migrating to Profectus 0.6","description":"","frontmatter":{},"headers":[],"relativePath":"guide/migrations/0-6.md","lastUpdated":1681880763000}'),l={name:"guide/migrations/0-6.md"},t=n("",50),p=[t];function r(c,i,y,D,A,C){return a(),e("div",null,p)}const u=s(l,[["render",r]]);export{d as __pageData,u as default};
diff --git a/assets/guide_recipes_particles.md.e7d7ddf3.js b/assets/guide_recipes_particles.md.9a58c965.js
similarity index 99%
rename from assets/guide_recipes_particles.md.e7d7ddf3.js
rename to assets/guide_recipes_particles.md.9a58c965.js
index 955e0227..25b30c4c 100644
--- a/assets/guide_recipes_particles.md.e7d7ddf3.js
+++ b/assets/guide_recipes_particles.md.9a58c965.js
@@ -1,4 +1,4 @@
-import{_ as s,c as a,o as n,N as l}from"./chunks/framework.0799945b.js";const i=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/particles.md","lastUpdated":1681878045000}'),p={name:"guide/recipes/particles.md"},o=l(`
This is a more comprehensive example based on the Kronos example used in the nodes docs. You will design a particle effect, make it appear on another feature, and ensure it adapts to the game state.
First, design the particle effect. Profectus uses pixi-particles, and you can use the online particle effect editor here. However, the editor returns an older format of the particle effect emitter config, so you'll need to convert it like this:
ts
import myParticleEffect from"myParticleEffect.json";
+import{_ as s,c as a,o as n,N as l}from"./chunks/framework.0799945b.js";const i=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/particles.md","lastUpdated":1681880763000}'),p={name:"guide/recipes/particles.md"},o=l(`
This is a more comprehensive example based on the Kronos example used in the nodes docs. You will design a particle effect, make it appear on another feature, and ensure it adapts to the game state.
First, design the particle effect. Profectus uses pixi-particles, and you can use the online particle effect editor here. However, the editor returns an older format of the particle effect emitter config, so you'll need to convert it like this:
Next, create the particles feature and render it. You'll also want to track the bounding rect of the particle effects. Consider the following step:
ts
const particles =createParticles(()=> ({
diff --git a/assets/guide_recipes_particles.md.e7d7ddf3.lean.js b/assets/guide_recipes_particles.md.9a58c965.lean.js
similarity index 84%
rename from assets/guide_recipes_particles.md.e7d7ddf3.lean.js
rename to assets/guide_recipes_particles.md.9a58c965.lean.js
index 687d78e2..12e1e3d5 100644
--- a/assets/guide_recipes_particles.md.e7d7ddf3.lean.js
+++ b/assets/guide_recipes_particles.md.9a58c965.lean.js
@@ -1 +1 @@
-import{_ as s,c as a,o as n,N as l}from"./chunks/framework.0799945b.js";const i=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/particles.md","lastUpdated":1681878045000}'),p={name:"guide/recipes/particles.md"},o=l("",18),e=[o];function t(c,r,y,F,D,A){return n(),a("div",null,e)}const d=s(p,[["render",t]]);export{i as __pageData,d as default};
+import{_ as s,c as a,o as n,N as l}from"./chunks/framework.0799945b.js";const i=JSON.parse('{"title":"Particles","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/particles.md","lastUpdated":1681880763000}'),p={name:"guide/recipes/particles.md"},o=l("",18),e=[o];function t(c,r,y,F,D,A){return n(),a("div",null,e)}const d=s(p,[["render",t]]);export{i as __pageData,d as default};
diff --git a/assets/guide_recipes_prestige.md.2325dec7.js b/assets/guide_recipes_prestige.md.2325dec7.js
new file mode 100644
index 00000000..c311814f
--- /dev/null
+++ b/assets/guide_recipes_prestige.md.2325dec7.js
@@ -0,0 +1,18 @@
+import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const F=JSON.parse('{"title":"Prestige Mechanic","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/prestige.md","lastUpdated":1681880763000}'),o={name:"guide/recipes/prestige.md"},t=n(`
Prestige mechanics are a common feature in incremental games. They involve resetting a portion of the game's progress in exchange for a new currency that persists between these resets. Many games even have multiple layers of reset mechanics, each resetting everything that came before them.
The first step is to create a conversion that will handle calculating the amount of prestige currency generated. In our example, let's assume there's a base layer called main and a prestige layer called prestige. This conversion will be based on the amount of points the player has, a resource within main. Here's an example conversion, using the formula from The Prestige Tree's prestige layer:
This creates a simple clickable that can only be clicked when the player will gain some amount of the prestige currency, and it displays how much they'll get. This can be further improved by displaying how many points the player will need to generate one more prestige point.
Now, return to the main layer. Create a reset feature that receives a list of all the things it needs to reset - in this example, we'll just reset the entire layer:
If you have multiple tiers of resets, you may add an onReset function to each reset that triggers the next reset before it, causing the resets to cascade.
A common pattern for reset mechanics is to display these various layers in a tree and have the tree propagate the resets for you. There are a couple of utility functions to help you accomplish this: createResetButton and createLayerTreeNode. You'll typically place the tree itself in the main layer and create a tree node for each layer. Then you can call the tree's reset function with the layer that's resetting, and it will propagate the reset as appropriate.
`,18),l=[t];function p(r,c,i,y,D,A){return a(),e("div",null,l)}const h=s(o,[["render",p]]);export{F as __pageData,h as default};
diff --git a/assets/guide_recipes_prestige.md.3b2c684a.lean.js b/assets/guide_recipes_prestige.md.2325dec7.lean.js
similarity index 84%
rename from assets/guide_recipes_prestige.md.3b2c684a.lean.js
rename to assets/guide_recipes_prestige.md.2325dec7.lean.js
index b16f13b6..29a2f950 100644
--- a/assets/guide_recipes_prestige.md.3b2c684a.lean.js
+++ b/assets/guide_recipes_prestige.md.2325dec7.lean.js
@@ -1 +1 @@
-import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const F=JSON.parse('{"title":"Prestige Mechanic","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/prestige.md","lastUpdated":1681878045000}'),o={name:"guide/recipes/prestige.md"},t=n("",18),l=[t];function p(r,c,i,y,D,A){return a(),e("div",null,l)}const h=s(o,[["render",p]]);export{F as __pageData,h as default};
+import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const F=JSON.parse('{"title":"Prestige Mechanic","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/prestige.md","lastUpdated":1681880763000}'),o={name:"guide/recipes/prestige.md"},t=n("",18),l=[t];function p(r,c,i,y,D,A){return a(),e("div",null,l)}const h=s(o,[["render",p]]);export{F as __pageData,h as default};
diff --git a/assets/guide_recipes_prestige.md.3b2c684a.js b/assets/guide_recipes_prestige.md.3b2c684a.js
deleted file mode 100644
index db9d2fac..00000000
--- a/assets/guide_recipes_prestige.md.3b2c684a.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import{_ as s,c as e,o as a,N as n}from"./chunks/framework.0799945b.js";const F=JSON.parse('{"title":"Prestige Mechanic","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/prestige.md","lastUpdated":1681878045000}'),o={name:"guide/recipes/prestige.md"},t=n(`
Prestige mechanics are a common feature within incremental games. They involve resetting some amount of progress within the game in exchange for a new currency that persists between these resets. Many games will even have multiple layers of reset mechanics that each reset everything before them.
The first step is creating a conversion that'll handle calculating how much of the prestige currency gets generated. For our example, let's assume there's a base layer called main and a prestige layer called prestige. This conversion will be based on the amount of points the player has, a resource within main. Here's an example conversion, using the formula from The Prestige Tree's prestige layer:
This creates a simple clickable that can only be clicked when we'll gain some amount of the prestige currency, and it tells us how much we'll get. This could be further improved by making the display convey how many points the player will need to generate 1 more prestige point.
Now we need to go back to the main layer. Here we'll create a reset feature that gets a list of all the things it needs to reset - for this example, we'll just reset the entire layer:
If you have multiple tiers of resets, you may add a onReset function to each reset that triggers the next reset before it. That will cause the resets to cascade.
A common pattern for reset mechanics is to display these various layers in a tree and have the tree propagate the resets for you. There are a couple utility functions to help you accomplish this: createResetButton and createLayerTreeNode. You'll typically place the tree itself in the main layer, and create a tree node for each layer. Then you can call the tree's reset function with the layer that's resetting and it'll propagate the reset as appropriate.
`,18),l=[t];function p(r,c,i,y,D,A){return a(),e("div",null,l)}const h=s(o,[["render",p]]);export{F as __pageData,h as default};
diff --git a/assets/guide_recipes_save-progress.md.e8f8b6fc.js b/assets/guide_recipes_save-progress.md.ff3bd908.js
similarity index 99%
rename from assets/guide_recipes_save-progress.md.e8f8b6fc.js
rename to assets/guide_recipes_save-progress.md.ff3bd908.js
index abafdae6..3c14cb14 100644
--- a/assets/guide_recipes_save-progress.md.e8f8b6fc.js
+++ b/assets/guide_recipes_save-progress.md.ff3bd908.js
@@ -1,4 +1,4 @@
-import{_ as s,c as a,o as e,N as n}from"./chunks/framework.0799945b.js";const o="/assets/save-progress.2c9d1bae.png",u=JSON.parse('{"title":"Display Save Progress","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/save-progress.md","lastUpdated":1681878045000}'),t={name:"guide/recipes/save-progress.md"},l=n('
This is a recipe to add a section to each save in the Saves Manager that will describe the amount of progress within that save. This can allow the player to more easily compare the saves to determine which is which. This would be in addition to the game version, last time played, and the name of the save itself, which can already be used for comparing saves without any configuration.
This recipe will involve modifying the Save.vue file within your project to include an extra component in the saves details. It will go over creating the new component, how to work with the save data object, and then displaying the component.
Let's start with creating the coerced component. For this recipe we're going to make a couple assumptions about what this display should be. We'll assume the text will be more complex than displaying a single value. That is, at different stages of the game progress will be indicated by different metrics. We'll also assume it will be a single line of descriptive text - no images or anything else that would justify making a new .vue component. Breaking these assumptions is left as an exercise for the reader. But for now, with those assumptions in mind, we'll write our component (in the <script> tag in Save.vue) similar to this example:
ts
const progressDisplay =computeComponent(
+import{_ as s,c as a,o as e,N as n}from"./chunks/framework.0799945b.js";const o="/assets/save-progress.2c9d1bae.png",u=JSON.parse('{"title":"Display Save Progress","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/save-progress.md","lastUpdated":1681880763000}'),t={name:"guide/recipes/save-progress.md"},l=n('
This is a recipe to add a section to each save in the Saves Manager that will describe the amount of progress within that save. This can allow the player to more easily compare the saves to determine which is which. This would be in addition to the game version, last time played, and the name of the save itself, which can already be used for comparing saves without any configuration.
This recipe will involve modifying the Save.vue file within your project to include an extra component in the saves details. It will go over creating the new component, how to work with the save data object, and then displaying the component.
Let's start with creating the coerced component. For this recipe we're going to make a couple assumptions about what this display should be. We'll assume the text will be more complex than displaying a single value. That is, at different stages of the game progress will be indicated by different metrics. We'll also assume it will be a single line of descriptive text - no images or anything else that would justify making a new .vue component. Breaking these assumptions is left as an exercise for the reader. But for now, with those assumptions in mind, we'll write our component (in the <script> tag in Save.vue) similar to this example:
ts
const progressDisplay =computeComponent(computed(()=>{if (someCondition) {return"Just started";
diff --git a/assets/guide_recipes_save-progress.md.e8f8b6fc.lean.js b/assets/guide_recipes_save-progress.md.ff3bd908.lean.js
similarity index 86%
rename from assets/guide_recipes_save-progress.md.e8f8b6fc.lean.js
rename to assets/guide_recipes_save-progress.md.ff3bd908.lean.js
index 9b907af3..2eb37c29 100644
--- a/assets/guide_recipes_save-progress.md.e8f8b6fc.lean.js
+++ b/assets/guide_recipes_save-progress.md.ff3bd908.lean.js
@@ -1 +1 @@
-import{_ as s,c as a,o as e,N as n}from"./chunks/framework.0799945b.js";const o="/assets/save-progress.2c9d1bae.png",u=JSON.parse('{"title":"Display Save Progress","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/save-progress.md","lastUpdated":1681878045000}'),t={name:"guide/recipes/save-progress.md"},l=n("",16),p=[l];function r(c,i,y,D,F,d){return e(),a("div",null,p)}const m=s(t,[["render",r]]);export{u as __pageData,m as default};
+import{_ as s,c as a,o as e,N as n}from"./chunks/framework.0799945b.js";const o="/assets/save-progress.2c9d1bae.png",u=JSON.parse('{"title":"Display Save Progress","description":"","frontmatter":{},"headers":[],"relativePath":"guide/recipes/save-progress.md","lastUpdated":1681880763000}'),t={name:"guide/recipes/save-progress.md"},l=n("",16),p=[l];function r(c,i,y,D,F,d){return e(),a("div",null,p)}const m=s(t,[["render",r]]);export{u as __pageData,m as default};
diff --git a/assets/index.md.aeace616.js b/assets/index.md.c1c0481e.js
similarity index 94%
rename from assets/index.md.aeace616.js
rename to assets/index.md.c1c0481e.js
index 9eaf8f13..35c31539 100644
--- a/assets/index.md.aeace616.js
+++ b/assets/index.md.c1c0481e.js
@@ -1 +1 @@
-import{_ as e,c as t,o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"Profectus","text":"A game engine that grows with you","tagline":"Starts at your skill level and encourages your ambition to make your projects bigger and better.","actions":[{"theme":"brand","text":"Get Started","link":"/guide/getting-started/setup"},{"theme":"alt","text":"Learn More","link":"/guide/"}]},"features":[{"title":"Easy to Use","details":"Everything is written to be as intuitive to use as possible, through consistent design."},{"title":"Helpful","details":"Built with TypeScript to guide you as you write. Seamlessly deploy your project with pre-configured github workflows, and more."},{"title":"Incremental","details":"Designed to actively encourage you to become better at programming. The engine will never limit you."}]},"headers":[],"relativePath":"index.md","lastUpdated":1681878045000}'),i={name:"index.md"};function a(r,n,s,l,d,u){return o(),t("div")}const g=e(i,[["render",a]]);export{m as __pageData,g as default};
+import{_ as e,c as t,o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"Profectus","text":"A game engine that grows with you","tagline":"Starts at your skill level and encourages your ambition to make your projects bigger and better.","actions":[{"theme":"brand","text":"Get Started","link":"/guide/getting-started/setup"},{"theme":"alt","text":"Learn More","link":"/guide/"}]},"features":[{"title":"Easy to Use","details":"Everything is written to be as intuitive to use as possible, through consistent design."},{"title":"Helpful","details":"Built with TypeScript to guide you as you write. Seamlessly deploy your project with pre-configured github workflows, and more."},{"title":"Incremental","details":"Designed to actively encourage you to become better at programming. The engine will never limit you."}]},"headers":[],"relativePath":"index.md","lastUpdated":1681880763000}'),i={name:"index.md"};function a(r,n,s,l,d,u){return o(),t("div")}const g=e(i,[["render",a]]);export{m as __pageData,g as default};
diff --git a/assets/index.md.aeace616.lean.js b/assets/index.md.c1c0481e.lean.js
similarity index 94%
rename from assets/index.md.aeace616.lean.js
rename to assets/index.md.c1c0481e.lean.js
index 9eaf8f13..35c31539 100644
--- a/assets/index.md.aeace616.lean.js
+++ b/assets/index.md.c1c0481e.lean.js
@@ -1 +1 @@
-import{_ as e,c as t,o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"Profectus","text":"A game engine that grows with you","tagline":"Starts at your skill level and encourages your ambition to make your projects bigger and better.","actions":[{"theme":"brand","text":"Get Started","link":"/guide/getting-started/setup"},{"theme":"alt","text":"Learn More","link":"/guide/"}]},"features":[{"title":"Easy to Use","details":"Everything is written to be as intuitive to use as possible, through consistent design."},{"title":"Helpful","details":"Built with TypeScript to guide you as you write. Seamlessly deploy your project with pre-configured github workflows, and more."},{"title":"Incremental","details":"Designed to actively encourage you to become better at programming. The engine will never limit you."}]},"headers":[],"relativePath":"index.md","lastUpdated":1681878045000}'),i={name:"index.md"};function a(r,n,s,l,d,u){return o(),t("div")}const g=e(i,[["render",a]]);export{m as __pageData,g as default};
+import{_ as e,c as t,o}from"./chunks/framework.0799945b.js";const m=JSON.parse('{"title":"Home","description":"","frontmatter":{"layout":"home","title":"Home","hero":{"name":"Profectus","text":"A game engine that grows with you","tagline":"Starts at your skill level and encourages your ambition to make your projects bigger and better.","actions":[{"theme":"brand","text":"Get Started","link":"/guide/getting-started/setup"},{"theme":"alt","text":"Learn More","link":"/guide/"}]},"features":[{"title":"Easy to Use","details":"Everything is written to be as intuitive to use as possible, through consistent design."},{"title":"Helpful","details":"Built with TypeScript to guide you as you write. Seamlessly deploy your project with pre-configured github workflows, and more."},{"title":"Incremental","details":"Designed to actively encourage you to become better at programming. The engine will never limit you."}]},"headers":[],"relativePath":"index.md","lastUpdated":1681880763000}'),i={name:"index.md"};function a(r,n,s,l,d,u){return o(),t("div")}const g=e(i,[["render",a]]);export{m as __pageData,g as default};
diff --git a/guide/advanced-concepts/creating-features.html b/guide/advanced-concepts/creating-features.html
index 91c67508..d7ff80ff 100644
--- a/guide/advanced-concepts/creating-features.html
+++ b/guide/advanced-concepts/creating-features.html
@@ -10,7 +10,7 @@
-
+
@@ -51,8 +51,8 @@
// unsubscribe from postUpdatelisteners[layer.id]?.();listeners[layer.id] =undefined;
-});
This is a TypeScript file containing the non-static parts of your project, and acts as the entry point for it.
It is stored at /src/data/projEntry.jsx.
This file has 3 things it must export, but beyond that can export anything the creator wants it to. Typically in addition to the required 3, the initial/"main" layer will be exported. Typically utilites belong in common.tsx, which exists next to projEntry.tsx.
A function that is given a player save data object currently being loaded, and returns a list of layers that should be active for that player. If a project does not have dynamic layers, this should always return a list of all layers.
This function will be run whenever a save is loaded that has a different version than the one in project info. It will be given the old version number, and the player save data object currently being loaded.
The purpose of this function is to perform any necessary migrations, such as capping a resource that accidentally inflated in a previous version of the project. By default it will do nothing.
This is a unique ID used when saving player data. Changing this will effectively erase all save data for all players.
WARNING
This ID MUST be unique to your project, and should not be left as the default value. Otherwise, your project may use the save data from another project and cause issues for both projects.
The text to display for the discord server to point users to. This will appear when hovering over the discord icon, inside the info tab, the game over screen, as well as the NaN detected screen.
By default, this is The Paper Pilot Community, which can act as a catch-all for any Profectus projects without their own servers. If you change the discord server with your own, The Paper Pilot Community will still display underneath the custom server when hovering over the discord icon and within the info tab. Those places will also contain a link to the Modding Tree discord server.
The current version of the project loaded. If the player data was last saved in a different version of the project, fixOldSave will be run, so you can perform any save migrations necessary. This will also appear in the nav, the info tab, and the game over screen.
The display name for the current version of the project loaded. This will also appear in the nav, the info tab, and the game over screen unless set to an empty string.
Whether or not to allow resources to display small values (<.001). If false they'll just display as 0. Individual resources can also be configured to override this value.
Default precision to display numbers at when passed into format. Individual format calls can override this value, and resources can be configured with a custom precision as well.
Whether or not to display the nav as a header at the top of the screen. If disabled, the nav will appear on the left side of the screen laid over the first tab.
A path to an image file to display as the logo of the app. If null, the title will be shown instead. This will appear in the nav when useHeader is true.
The list of initial tabs to display on new saves. This value must have at least one element. Each element should be the ID of the layer to display in that tab.
The longest duration a single tick can be, in seconds. When calculating things like offline time, a single tick will be forced to be this amount or lower. This will make calculating offline time spread out across many ticks as necessary. The default value is 1 hour.
Whether or not to allow the player to pause the game. Turning this off disables the toggle from the options menu as well as the NaN screen. Developers can still manually pause by just running player.devSpeed = 0 in console (or = 1 to resume).
The encoding to use when exporting to the clipboard. Plain-text is fast to generate but is easiest for the player to manipulate and cheat with. Base 64 is slightly slower and the string will be longer but will offer a small barrier to people trying to cheat. LZ-String is the slowest method, but produces the smallest strings and still offers a small barrier to those trying to cheat. Some sharing platforms like pastebin may automatically delete base64 encoded text, and some sites might not support all the characters used in lz-string exports.
Themes are objects that change how the project's interface should look. This is done mostly by changing the values of various CSS variables. You can look at the existing themes as a reference for the kind of values these CSS variables expect. They can also set various theme options that change how parts of the screen are laid out, which are described below.
You can add a theme by adding a property to the Themes enum and then including the theme in the exported object. It's recommended to use the spread operator if you'd like to have a theme look like another, but override specific options / CSS variables.
Themes added in this way will be automatically included in the Themes dropdown in the Options tab. Removing themes from the enum and exported object will similarly hide them from the dropdown.
If you'd like to change which theme is the default, you may modify the initial player settings object in the /src/game/settings.ts file. Keep in mind you'll also want to change it in the hardResetSettings function in the same file.
Toggles whether to display tab buttons in a tab list, similar to how a browser displays tabs; or to display them as floating buttons, similar to how TMT displays buttons.
If true, elements in a row or column will have their margins removed and border radiuses set to 0 between elements. This will cause the elements to appear as segments in a single object.
Currently, this can only merge in a single dimension. Rows of columns or columns of rows will not merge into a single rectangular object.
There are often concepts that aren't inherent to a single feature, but rather work with joining different features together. For example, a reset clickable that activates a conversion and resets a tree, which happens to be a common use case but isn't inherent to clickables, conversions, or trees.
These are perfect situations for utilities, and so to encourage creators to learn to identify and take advantage of these situations, a file called src/data/common.tsx has been created to demo some of the more common utility functions a project might use. Adding new utilities to this file is encouraged, as is creating utils in general. It also works as a good stepping stone to creating your own features.
An incremental game with 25 different layers of content. A good example of what a large project looks like. There's also a partial port to 0.6 available here.
Profectus requires a Node.js development environment for working on a project. If you are comfortable with the command line, a local development environment is recommended.
Create a new project from the Profectus repository by clicking the "Use this template" button. Then, clone the repository locally using the provided link.
INFO
The template repository allows easy creation of multiple projects from one repository. However, updating an existing project to a newer version of Profectus can be challenging. Consider updating Profectusbefore starting development to avoid issues with unrelated histories.
It's recommended to create a new Git branch for development, allowing you to push changes without affecting the live build. The GitHub workflow will automatically rebuild the page when you push to the main branch.
Next, install Profectus' dependencies by running npm install. Run npm run serve to start a local server hosting your project. The site will automatically reload as you modify files.
Also, follow the steps to update Profectus before starting to make future updates easier without worrying about unrelated histories.
Using Git, the repository's workflow action automates deployment. However, you need to grant write permissions for the action in the repository settings. Go to Actions, General, Workflow permissions, and select "Read and write permissions".
To deploy, push changes to the main branch. The site will be updated automatically in a few minutes. Check progress or errors from the Actions tab on your repository.
Enable GitHub Pages in the repo settings to host the generated site. Select the gh-pages branch. Perform this step once. This will automatically start another GitHub action to deploy the website.
As an alternative to local development, you may use Replit. Replit sets up your development and hosts your project.
On the free plan, you'll face limitations, and the program may need occasional startups.
To create a Profectus project on Replit, all you have to do is click this button:
Click the "Run" button at the top of the screen to start development. This will also make the project publicly accessible, essentially auto-deploying it. However, this means you cannot separate your development and production environments.
Glitch is a site similar to Replit, with many of the same pros and cons. To create a Profectus project on Glitch, select "New Project", "Import from GitHub", and enter profectus-engine/Profectus. The new project will be automatically configured and ready to go.
Due to Profectus being a template repository, your projects do not share a git history with Profectus. To update changes, you will need to run the following:
The first command only has to be performed once. The third command may require you to merge conflicts between code both you and Profectus have changed - however, due to the modularity of Profectus, this should be fairly rare. Unfortunately, due to the unrelated histories the first time you do this every change will be marked as a conflict, and you'll need to accept each one.
The sidebar has a tab labeled "Version Control", which you can use to merge all changes made to Profectus into your project. Unfortunately, Replit does not have a merge tool so this process may irrecoverably erase changes you've made - I'd recommend making a backup first.
Unfortunately, Glitch does not provide any method by which to update a project from a Github repository. If you've only changed things in the data folder you may consider creating a new project, importing the current version of Profectus, and then placing your data folder in the new project.
Profectus content is organized into units called "Layers". When displaying content to the user, the screen will be divided into several tabs that each display the content of a layer. These layers are stored in /src/data/layers.
Each layer is ultimately a collection of different features, and a display function. While there are a couple reserved properties for layers, most of its structure is fully up to the creator.
Layers can be dynamically added or removed at any time, which also allows for effectively disabling or enabling content based on arbitrary conditions. Just make sure getInitialLayers can process the player save data object and determine which layers should be currently active.
Layers (and features) are not actually created immediately. Instead, their options are gotten through a function which is then run the first time something inside the layer is accessed. This is a concept called lazy evaluation, which is also used for things like computed, and allows for features to reference each other without worrying about cyclical dependencies.
Persistence refers to data that is saved so that it persists when the user closes the tab and opens it again in the future.
In Profectus, this is handled by creating "persistent refs", which act like refs but whose value is stored in an object that gets saved to localStorage. Other than that you can treat them like any other ref - when adding the layer, any persistent refs will automatically have their values updated to the ones saved in localStorage. If there isn't a saved value, it'll use the default value passed to the persistent ref constructor.
Many features in Profectus, such as upgrades, milestones, and challenges, internally have persistent refs to save things like whether the upgrade has been purchased, the milestone achieved, or the challenge completed. Creators can also create their own custom persistent refs to store any arbitrary (but serializable) data they need - that means Numbers (including big numbers), strings, booleans, or objects containing only serializable values. Another notable function is the resource constructor. If you pass a default value into its constructor, it will automatically create a persistent ref for that resource. If you pass in a ref, it will NOT make the ref persistent.
It's important for saving and loading these properties for these refs to be in a well-known location. This is implemented based on the location of the persistent ref within a layer. That means it's important that all persistent refs are located within the object returned by the createLayer options function. If a persistent ref is not within that object, it will NOT be saved and loaded - regardless of whether it's a persistent ref within a feature, one you manually created, or otherwise.
Additionally, this structure should typically remain consistent between project versions. If a value is in a new location, it will not load the value from localStorage correctly. This is exacerbated if two values swap places, such as when an array is re-ordered. In the event a creator changes this structure anyways, the fixOldSave function can be used to migrate the old player save data to the new structure expected by the current version of the project.
As of Profectus 0.6, save data will now report warnings whenever there is redundancy - two locations for the same persistent data, which creates larger saves that can cause issues when loading after updates. To fix redundancies, wrap all but one location for the data in noPersist.
Profectus takes large advantage of Vue's reactivity system. It's recommended to read up on how refs and computed refs work. Ultimately this means that sometimes you'll need to type .value to get the actual value of something, but also you are able to pass things around by reference instead of by value. Indeed, it is recommended to only unwrap the actual value when you actually need it. .value is guaranteed to be correct and up to date only on the exact moment it is accessed.
With a proper IDE, such as Visual Studio Code, you should be able to see whether or not something is a ref or not from type hints. If in doubt, you can always wrap the property in an unref call.
Vue's reactivity is probably the "quirkiest" part of Profectus, and not even the documentation makes all of those quirks clear. It is recommend to read this thread of common misconceptions around Vue reactivity.
Most properties on features will accept Computable values. Computable values can either be a raw value, a ref to the value, or a function that returns the value. In the lattermost case it will be wrapped in computed, turning it into a ref. The feature type will handle it being a ref or a raw value by using unref when accessing those values. With type hints, your IDE should correctly identify these values as refs or raw values so you can treat them as the types they actually are.
Because functions are automatically wrapped in computed for many properties, it might be expected to happen to custom properties you add to a feature that isn't defined by the feature type. These functions will not be wrapped, and if you want it cached you should wrap it in a computed yourself. This does, however, allow you to include custom methods on a feature without worry.
The requirements system in Profectus is designed to handle various conditions that must be met before certain actions or features can be accessed by the player. These conditions can include resource amounts, completed challenges, or other milestones within the game.
Several features will have a requirements property that takes one or more requirements that must be fulfilled for a certain action to be performed with that feature.
When implementing requirements, you can use the displayRequirements utility. This utility is designed to give a human-readable string generated by the requirement(s) given, making it easier for players to understand the conditions needed to progress in the game. Typically features that support requirements will already use this utility internally.
You may need to "pay" requirements upon meeting their conditions and performing the associated action. This action typically involves spending resources or making other adjustments to the game state. The payRequirements function simplifies this process by handling the payment for one or more requirements, considering the number of levels to pay for. Additionally, custom pay functions like payByDivision and payByReset can be passed into createCostRequirement for more specialized cases.
Requirements can have multiple "levels", which are typically used for things like multi-level challenges with scaling requirements. When checking if requirements are met, the requirementsMet function can be used. It accepts a single requirement or an array of requirements.
Requirements that are just on/off, such as boolean or visibility requirements, will count as infinite levels when in the same array. This allows you to combine different types of requirements in the same array and use the maxRequirementsMet function to calculate the maximum number of levels that could be acquired with the current requirement states.
Profectus is a web-based game engine. You can write your content using many built in features, write your own features, and build up complex gameplay quickly and easily.
The purpose of creating profectus was to create an easy to use engine that does not create a ceiling for a programmer's personal growth. This engine will grow in complexity with you, empowering you to create increasingly complex designs and mechanics.
While this engine is intended to make game development (and web app development) easier, it still requires you to be comfortable with programming in general and javascript in particular. Fortunately, that is a solvable problem.
If you've never used Javascript before, learn-js.org is a good resource for learning the important concepts. If you'd like a more thorough lesson on all the ins and outs of web development, javascript.info and MDN's tutorials should have you covered. MDN is also a great resource to use as a reference - for example, if you want to know more about something and you google it, there'll typically be a MDN link that'll explain it thoroughly.
Beyond the basics, Profectus uses a modern web development pipeline, using tools like node, typescript, and JSX. While most of it should be relatively easy to pick up through context, if this becomes too complicated you may be interested in The Modding Tree, a predecessor of Profectus that uses plain old javascript.
There are many popular game engines out there, such as GameMaker Studio 2, Unity3D, Unreal Engine 4, and Godot, that are all general purpose and also more useful if you're planning on going into a career in game development. These are all more mature and robust game engines compared to Profectus, and are used by actual game development studios.
Profectus, on the other hand, is a very opinionated engine that is better at specific types of projects. Where the above engines will require you to design and create your own interfaces, menus, save management systems, etc. Profectus will include those out of the box. Profectus will also output games that run natively in the browser, and will typically be easier for players to play than traditional engines.
If you are not interested in programming but still want to get into game development, the above engines also all support "visual programming", which may be more amenable to you. Each engine will have varying levels of support, and of course with varying complexities, but ultimately any of these will help you learn the concepts of programming and game development, and all of them also offer traditional programming for when you think you're ready.
Prestige mechanics are a common feature within incremental games. They involve resetting some amount of progress within the game in exchange for a new currency that persists between these resets. Many games will even have multiple layers of reset mechanics that each reset everything before them.
The first step is creating a conversion that'll handle calculating how much of the prestige currency gets generated. For our example, let's assume there's a base layer called main and a prestige layer called prestige. This conversion will be based on the amount of points the player has, a resource within main. Here's an example conversion, using the formula from The Prestige Tree's prestige layer:
Prestige mechanics are a common feature in incremental games. They involve resetting a portion of the game's progress in exchange for a new currency that persists between these resets. Many games even have multiple layers of reset mechanics, each resetting everything that came before them.
The first step is to create a conversion that will handle calculating the amount of prestige currency generated. In our example, let's assume there's a base layer called main and a prestige layer called prestige. This conversion will be based on the amount of points the player has, a resource within main. Here's an example conversion, using the formula from The Prestige Tree's prestige layer:
This creates a simple clickable that can only be clicked when we'll gain some amount of the prestige currency, and it tells us how much we'll get. This could be further improved by making the display convey how many points the player will need to generate 1 more prestige point.
Now we need to go back to the main layer. Here we'll create a reset feature that gets a list of all the things it needs to reset - for this example, we'll just reset the entire layer:
ts
const reset =createReset(()=> ({
+}));
This creates a simple clickable that can only be clicked when the player will gain some amount of the prestige currency, and it displays how much they'll get. This can be further improved by displaying how many points the player will need to generate one more prestige point.
Now, return to the main layer. Create a reset feature that receives a list of all the things it needs to reset - in this example, we'll just reset the entire layer:
And then we can modify the convert button to trigger the reset:
ts
onClick() {
+}));
Then, modify the convert button to trigger the reset:
ts
onClick() {conversion.convert();reset.reset();
-}
If you have multiple tiers of resets, you may add a onReset function to each reset that triggers the next reset before it. That will cause the resets to cascade.
A common pattern for reset mechanics is to display these various layers in a tree and have the tree propagate the resets for you. There are a couple utility functions to help you accomplish this: createResetButton and createLayerTreeNode. You'll typically place the tree itself in the main layer, and create a tree node for each layer. Then you can call the tree's reset function with the layer that's resetting and it'll propagate the reset as appropriate.