Core Architecture: Model: StoryComponents - UA-ScriptEase/scriptease GitHub Wiki
#Atomic Story Components Atomics are the simplest form of Story Component. They do not contain any children, and represent a simple piece of a function like a function call or variable.
##KnowIt and KnowItBindings KnowIts can be thought of as variables in code. They represent a piece of data within a script and can be bound to a value (simple type) or object (complex type). KnowIts have the potential to be multiple Types, but they can only be bound to (or assigned the value of ) a single object which must share one of the KnowIt's types. Every KnowIt has a binding attached to it.
###KnowIt Bindings Bindings are the resolved value of the KnowIt. Bindings have a Type, a Value, and a ScriptValue.
KnowItBindingResource | Binding for a game Resource to which the KnowIt is bound |
KnowItBindingFunction | Binding for a ScriptIt, for which the KnowIt is the return value. Mainly used in DescribeIts. |
KnowItBindingNull | Empty binding. Throws an exception when the value is requested |
KnowItBindingReference | Binding for another KnowIt. It's value and type resolves to that KnowIt's Binding's value. |
KnowItBindingStoryPoint | Binding for a StoryPoint. |
KnowItBindingStoryGroup | Binding for a StoryGroup. |
KnowItBindingAutomatic | Automatic binding for a KnowIt. Intended to be used as automatic bindings for causes without a subject (attached to the module in NWN/ active scene's ScriptEaseObject in Unity. |
KnowItBindingUninitialized | Binding that references a KnowIt slot. Used in the library editor in ActivityIts to reference parameters with unknown bindings yet. |
##CodeBlocks
Codeblock
s contain the actual code with attached format tags that is then used to add code to scripts. In addition to code, a CodeBlock
can have parameters, types, required include files, a subject and slot, and implicits. Implicits are a set of KnowIt
s that are known by the code block. For example, a Cause for "When door opens" may have the person who opened the door as an implicit. This implicit would be stored in the CodeBlock
.
We have two different classes of CodeBlocks
: CodeBlockSource
and CodeBlockReference
.
CodeBlockSource
is only present in the APIDictionary. We save a CodeBlockReference
to the story file. When a person loads the story file, ScriptEase finds the CodeBlockSource
that it belongs to by using the unique "ID". Make sure the IDs are unique if you are editing the APIDictionary by hand!
The reason we separate these is so that we do not save any code in the saved story file. All code stays in the APIDictionary. This way, we can update the CodeBlockSource
with improved code in case something is wrong with it, and the user won't have to do anything.
##Notes Notes are only structural. Adding a note should not impact the way a script is run. We can add a note format in the language dictionary to generate comments in code, but we should never generate anything else with them.
#Complex Story Components Complex Story Components are Story Components that collect together other Story Components and add some additional stuff - like function calls, for example.
##ScriptIt A representation for one or more functions which will be generated into code. ScriptIts contain one or more CodeBlocks which contains code to execute and may also contain a slot reference, and the subject on which the script is fired. CodeBlocks do not necessarily need to have their subject and slot defined. If neither is provided, they will inherit the subject and/or slot from their ScriptIt parent's CodeBlock. There are three typical usages for ScriptIts.
- Effect: ScriptIt with one or more CodeBlocks usually without a subject and slot (since they inherit from their Cause CauseIt). These ScriptIts do not have children.
- CauseIt: See the subpage.
- ControlIt: See the subpage. ScriptIts are a generic representation of a function calls in a script. They can be user defined, or API driven and may or may not be shareable across multiple games. CodeBlocks have a types which represents the return type of the method call CodeBlocks may or may not have parameters (arguments) CodeBlocks may or may not have implicit parameters which will not appear in the header of the function
###ActivityIt ActivityIts are ScriptIts that represent a container of components (Effects, Descriptions, Controls, other Activities).
They are unique from a StoryComponentContainer because their components can have attached KnowItBindingUninitialized's bound to their KnowIts. These KnowItBindingUninitialized are tied to the parameters in the ActivityIt.
Right now they are being created in the library editor, but there probably should be a new builder in the future specifically for it and behaviours.
###CauseIt CauseIts are a extension of ScriptIts that have a subject and a slot. They represent the Causes in ScriptEase II and often contain one of more ScriptIt children.
##AskIt The AskIt story component represents conditional statements to the story author.
Constructed with a boolean typed KnowIt that represents the if-condition
Maintains 2 StoryItemSequence
(generic containers) as children
- If-Block - the
StoryComponent
list which should be run if the condition is true - Else-Block - the
StoryComponent
list which should be run if the condition is false
###ControlIt ControlIts are special ScriptIts that have some code wrapped around them. For example, we have a "for loop" control it that does things x amount of times.
The format for the ControlIt is defined in LanguageDictionary. We limit our ControlIts to type of Control in the APIDictionary. Right now, these are DELAY, QUESTION, and REPEAT. We also define these in the ControlIt class as an enum. The names of these are linked to formats in the LanguageDictionary with the same name.
Right now, we are not using Question, since we have AskIts. However, AskIts should really be made in the APIDictionary just like ControlIts are.
##PickIt
The PickIt
component represents a choice between StoryComponentContainer
s with a given probability each. The selected StoryComponentContainer
will then execute all children components.
Represented as a series of if, else if statements, where each statement composes of boundary numbers. eg. if a choice had a probability of 50 and it was the first choice, the code would generate as follows:
if (choice >= 0 && choice < 50) { ... }
By default there are two choices, each with 50 probability. The number is not a percent or measurement. A larger number simply means a choice has a greater chance of being selected relative to its counterparts. Choices can be added indefinitely. All subsequent choices can also be removed (except for the default two).
##StoryNode At first it may seem weird to have StoryNodes here since they are represented in the graph and not in the bottom part with all of the Causes and Effects. However, that bottom pane is called the "StoryNode Pane" because everything inside it belongs inside of a StoryNode. In that respect, StoryNodes are the top level after the Story Model as a whole.
StoryNodes are represented by two subcategories: StoryGroup: A group of StoryPoints and/or StoryGroups (Composite Design Pattern) StoryPoint: A point in the current story. See more in their respective subpages.
For information on the Story System, see that page.
###StoryPoint Story Points have Children, which are Causes, Effects, and other Story Components, but they also have Successors, which are other Story Points. The Story Model has one root story point, and all of the other story points have the root as their eventual ancestor.
The Start Story Point is immutable because of concurrency problems.
###StoryGroup Story Groups are a collection of Story Points and/or Story Groups as per the composite design pattern.
The greatest purpose they serve is to graphically organize the way in which the story is represented; reducing clutter.
There is a specific definition into what StoryNodes are capable of becoming a group. We follow the rule that there is at most one exit node and one entrant node. This means that all parents of the group must be parents of the entrant node and only the entrant node. Similarly, all children of the group must be children of the exit node and only the exit node.