Replies: 5 comments 12 replies
-
I really like the idea of "condition groups". When messing around with the new Harlowe implementation I found myself retyping The Macros in your proposal are a little under-documented. For users that are less Javascript savvy it might be easier for them to provide feedback if they could get a robust understanding of how everything would work just from the description of the Macros. Speaking of the macros, from what I see here it seems that I'd have to have some kind of master passage run at startup that has one It's also a little unclear to me what the difference between priority and weight are? Does priority work like the exclusivity value in Harlowe? |
Beta Was this translation helpful? Give feedback.
-
A thought on naming: Is layer a better name for what you want to capture with priority? Priority, to me, doesn't immediately imply what you want to capture here (Harlowe's "exclusivity" is also not intuitive). I find it easy to confuse with sorting order, since that's also in play. I like layer because occlusion is baked into the concept. If I bake a cake with layers, I expect to see only the top layer, and if multiple elements are on the same layer, I expect them all to be visible. |
Beta Was this translation helpful? Give feedback.
-
I just stumbled across this tonight. I have also been working on a system like this, and I had no idea that other people were working on similar systems or that there was a vocabulary built up around this concept. A friend of mine says "There are no new ideas!" But I disagree, I think new ideas happen constantly, but that many people get the same new idea at almost the same time. I have to say, I'm very, very happy to see that my ideas for story generation (carving down a set of possible paths, then choosing one) were not insane, and that many other people were thinking along the same lines. I am so, so relieved that it will not be impossible to communicate the idea to others. The system I have been working on is very similar to this one here. The core philosophy is the same, but it differs in a few small, significant ways. I will briefly detail how my system differs from yours, and I will briefly give some small critiques of the system proposed here. Feel free to ignore my suggestions if you disagree. Differences:
Overall, the major philosophical difference is that I very much aim to keep the definition close to the content. I want this because the main goal I had was de-coupling story passages from each other, to encourage game modding by a dis-organized team of contributors. Critiques:
|
Beta Was this translation helpful? Give feedback.
-
Hey this looks super cool and useful! Happy to do some video tutorials to help ppl use these features when this comes out (if that'd be helpful etc) 😊👍 |
Beta Was this translation helpful? Give feedback.
-
I'd appreciate it if both |
Beta Was this translation helpful? Give feedback.
-
@ChapelR and I have been working on a native storylet API & macro set for SugarCube.
What's everyone's feeling on the following proposals?
Storylet API Specification
Storylet
Static Members & MethodsStorylet.add(passageName | []passageNames, definition)
Register storylet(s). Reusing a name causes the original storylet definition to be replaced.
Definition object:
A storylet definition object should have some of the following properties:
conds
: (optional,[](string | function)
) An array of the storylet's own conditions.groups
: (optional,[]string
) An array of named condition groups that should also be checked when determining availability.priority
: (optional,integer
) The priority given to the storylet whenStorylet.available[Storylets]()
is called. Priority is the relative importance of the storylet. When checking availability, only storylets with a priority equal to the highest priority seen during that check are yielded. Defaults to0
.weight
: (optional,integer
) The weight given to the storylet whenStorylet.random[Storylet]()
is called. Weight is the relative weight of the storylet when calling for a random storylet. A higher weight increases the chance of the storylet to be chosen. Defaults to1
.NOTE: Conditions have access to the current storylet passage name via the
_storyletPassage
temporary variable. Additionally, function conditions are passed the current storylet passage name as their first parameter.NOTE: Specifying no conditions is equivalent to a single condition of
true
—i.e., the storylet will always be available.Storylet.all()
→[]string
Returns an array of passage names for all registered storylets.
Storylet.allStorylets()
→[]<Storylet>
Returns an array of all registered storylets.
Storylet.available()
→[]string
Returns an array of passage names for all storylets whose conditions yield true.
Storylet.availableStorylets()
→[]<Storylet>
Returns an array of all storylets whose conditions yield true.
Storylet.delete(passageName)
→boolean
Deletes the storylet with the given passage name and returns whether the operation was successful.
Storylet.get(passageName)
→<Storylet>
Returns the storylet with the given passage name, or
null
on failure.Storylet.has(passageName)
→boolean
Returns whether the storylet with the given passage name exists.
Storylet.isAvailable()
→boolean
Returns whether any storylets are currently available.
Storylet.random()
→string
Returns a randomly selected passage name from the storylets whose conditions yield true or an empty string, if no storylets are available.
Storylet.randomStorylet()
→<Storylet>
Returns a randomly selected storylet from the storylets whose conditions yield true or
null
, if no storylets are available.Storylet.size
→integer
Returns the number of existing storylets.
Storylet.conds
Static Members & MethodsStorylet.conds.add(groupName, []conds)
Register a group of conditions to be refenced by storylets via their
groups
properties. Reusing a name causes the original group to be replaced.NOTE: The special name
:all
may be used to register a group that applies to all storylets without needing to be refenced via theirgroups
properties.Storylet.conds.delete(groupName)
→boolean
Deletes the condition group with the given name and returns whether the operation was successful.
Storylet.conds.get(groupName)
→[]conds
Returns the condition group with the given name, or
null
on failure.Storylet.conds.has(groupName)
→boolean
Returns whether the condition group with the given name exists.
Storylet.conds.size
→integer
Returns the number of existing condition groups.
<Storylet>
Instance Members & Methods<Storylet>.conds
→[](string | function)
Returns an array of the storylet's own conditions.
<Storylet>.groups
→[]string
Returns an array of the named condition groups associated with the storylet.
<Storylet>.passage
→string
Returns the storylet's passage name.
<Storylet>.priority
↔integer
Provides access to the storylet's priority.
<Storylet>.weight
↔integer
Provides access to the storylet's weight.
<Storylet>.isAvailable()
→boolean
Returns whether the storylet's conditions yield true.
Storylet Macro Specification
SEE: The Storylet API Specification (above) for specific details on some of the following features.
Registering storylet passages.
NOTE: Conditions have access to the current storylet passage name via the
_storyletPassage
temporary variable. Additionally, function conditions are passed the current storylet passage name as their first parameter.Defining storylet condition groups.
The special group name
:all
automatically applies to all storylets.NOTE: Conditions have access to the current storylet passage name via the
_storyletPassage
temporary variable. Additionally, function conditions are passed the current storylet passage name as their first parameter.Using storylets.
Link to a random available storylet. If called multiple times within a turn, will not yield duplicates.
Include a random available storylet.
EDIT(1): Made a few clarifying edits to the OP. I'll make some more as I have time.
Beta Was this translation helpful? Give feedback.
All reactions