Another API change

This commit is contained in:
David Masad
2021-01-28 20:54:56 -05:00
parent 4c353ecfe3
commit 37c5740060
4 changed files with 61 additions and 17 deletions

View File

@ -72,14 +72,14 @@ Finally, we get to the custom properties. In this case there's just one:
* `character`: This is the specific character that'll be bound to this storylet instance.
Now that we have the storylet generator, all that's left to do is to query it in the appropriate Twine passage, and then do something with each possible storylet. We can get the array of available instantiated storylets with `window.SM.getAllStorylets()`.
Now that we have the storylet generator, all that's left to do is to query it in the appropriate Twine passage, and then do something with each possible storylet. We can get the array of available instantiated storylets with `window.SM.getStorylets()`.
One typical thing to do with this list is create a link associated with each possible storylet for the player to choose from. We can do it like this:
```
:: Start
You stand at the edge of the grand ballroom in the Duchess's palace.<br>
<<set _possibleStorylets = window.SM.getAllStorylets()>>
<<set _possibleStorylets = window.SM.getStorylets()>>
<<for _story range _possibleStorylets>>
<<capture _story>>
[[_storylet.description|_storylet.passage][$currentStorylet=_storylet]]<br>
@ -87,7 +87,7 @@ You stand at the edge of the grand ballroom in the Duchess's palace.<br>
<</for>>
```
This creates one link per available storylet. Each link will have the storylet description as its text, link to the storylet's passage, and when selected will story the storylet's data in the `$currentStorylet` variable, so that the storylet passage itself can access it. This pattern is (expected to be) common enough that there's a widget for it: `<<ShowStoryletLinks>>`. (**TODO:** Make this a macro). We may also not want to show *all* the available storylets. When there are just three guests it isn't so bad, but if the party has five, or ten, or more NPCs, giving the player the entire list will get overwhelming fast. We can randomly choose a subset, to emulate how people randomly circulate during the party. Instead, maybe we want to choose only some number of storylets to display. We can do this with `window.SM.getNStorylets(n)` where `n` is the number of storylets to get. Storylets are selected in order of priority, so that the list is filled with higher-priority storylets first.
This creates one link per available storylet. Each link will have the storylet description as its text, link to the storylet's passage, and when selected will story the storylet's data in the `$currentStorylet` variable, so that the storylet passage itself can access it. This pattern is (expected to be) common enough that there's a widget for it: `<<ShowStoryletLinks>>`. (**TODO:** Make this a macro). We may also not want to show *all* the available storylets. When there are just three guests it isn't so bad, but if the party has five, or ten, or more NPCs, giving the player the entire list will get overwhelming fast. We can randomly choose a subset, to emulate how people randomly circulate during the party. Instead, maybe we want to choose only some number of storylets to display. We can do this by passing a number to `getStorylets`indicating the maximum number of storylets to get. Storylets are selected in order of priority, so that the list is filled with higher-priority storylets first.
#### Putting it all together
@ -133,7 +133,7 @@ StoryManager.storylets["Conversation"] = {
:: Start
You stand at the edge of the grand ballroom in the Duchess's palace.<br>
<<set _possibleStories = window.SM.getNStorylets(3)>>
<<set _possibleStories = window.SM.getStorylets(3)>>
<<ShowStoryletLinks _possibleStories>>
@ -145,6 +145,10 @@ You make polite conversation with $talkingTo.name. <br>
To compile this with Tweego, run:
```
tweego storymanager.js storymanager-widgets.tw examples\at_the_party.tw -o at_the_party.html
> tweego storymanager.js storymanager-widgets.tw examples\at_the_party.tw -o at_the_party.html
```
### Adding interruptions
Is it even a real party if you aren't buttonholed by another guest at some point or another? In many games you'll want to allow some storylets to override the other options and require the player to engage with them now. We do this via a storylet that has the `interrupt==true` property.

View File

@ -121,19 +121,39 @@ StoryManager.getAllStorylets = function() {
return allStorylets;
}
StoryManager.getNStorylets = function(n) {
StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true)
{
/*
Get N storylets, prioritizing the highest-priority ones first.
Get n storylets, prioritizing the highest-priority ones first.
n: if not null, return at most n storylets
tag: Only get storylets matching this tag
respect_interrupt: if true, any interrupt storylet overrides n and priority
For now assume that priorities are integers, but it would be nice
to be more flexible.
*/
let allStorylets = this.getAllStorylets();
n = Math.min(n, allStorylets.length);
if (n == 0) return [];
let allStorylets;
if (tag == null) allStorylets = this.getAllStorylets();
// TODO: get tagged storylets
// Check for interruptions
// TODO: Handle more than one interruption
if (respect_interrupt)
for (let storylet in allStorylets)
if (storylet.interrupt) return [storylet];
// Get n stories in priority order
if (n != null) {
n = Math.min(n, allStorylets.length);
if (n == 0) return [];
}
else n = allStorylets.length;
let selectedStorylets = [];
// First sort by ascending priority:
allStorylets.sort((a, b) => b.priority - a.priority);
let currentPriority = allStorylets[0].priority;
while (selectedStorylets.length < n) {
let priorityStorylets = allStorylets.filter(s => s.priority==currentPriority);
@ -180,7 +200,7 @@ StoryManager.storylets["Conversation"] = {
&lt;&lt;/capture&gt;&gt;
&lt;&lt;/for&gt;&gt;
&lt;&lt;/widget&gt;&gt;</tw-passagedata><tw-passagedata pid="2" name="Start" tags="" position="225,100" size="100,100">You stand at the edge of the grand ballroom in the Duchess&#39;s palace.&lt;br&gt;
&lt;&lt;set _possibleStories = window.SM.getNStorylets(3)&gt;&gt;
&lt;&lt;set _possibleStories = window.SM.getStorylets(3)&gt;&gt;
&lt;&lt;ShowStoryletLinks _possibleStories&gt;&gt;</tw-passagedata><tw-passagedata pid="3" name="Conversation" tags="" position="350,100" size="100,100">&lt;&lt;set $talkingTo = $currentStorylet.character&gt;&gt;
You make polite conversation with $talkingTo.name. &lt;br&gt;
[[Keep circulating | Start]]</tw-passagedata></tw-storydata>

View File

@ -37,7 +37,7 @@ StoryManager.storylets["Conversation"] = {
:: Start
You stand at the edge of the grand ballroom in the Duchess's palace.<br>
<<set _possibleStories = window.SM.getNStorylets(3)>>
<<set _possibleStories = window.SM.getStorylets(3)>>
<<ShowStoryletLinks _possibleStories>>

View File

@ -18,19 +18,39 @@ StoryManager.getAllStorylets = function() {
return allStorylets;
}
StoryManager.getNStorylets = function(n) {
StoryManager.getStorylets = function(n=null, tag=null, respect_interrupt=true)
{
/*
Get N storylets, prioritizing the highest-priority ones first.
Get n storylets, prioritizing the highest-priority ones first.
n: if not null, return at most n storylets
tag: Only get storylets matching this tag
respect_interrupt: if true, any interrupt storylet overrides n and priority
For now assume that priorities are integers, but it would be nice
to be more flexible.
*/
let allStorylets = this.getAllStorylets();
n = Math.min(n, allStorylets.length);
if (n == 0) return [];
let allStorylets;
if (tag == null) allStorylets = this.getAllStorylets();
// TODO: get tagged storylets
// Check for interruptions
// TODO: Handle more than one interruption
if (respect_interrupt)
for (let storylet in allStorylets)
if (storylet.interrupt) return [storylet];
// Get n stories in priority order
if (n != null) {
n = Math.min(n, allStorylets.length);
if (n == 0) return [];
}
else n = allStorylets.length;
let selectedStorylets = [];
// First sort by ascending priority:
allStorylets.sort((a, b) => b.priority - a.priority);
let currentPriority = allStorylets[0].priority;
while (selectedStorylets.length < n) {
let priorityStorylets = allStorylets.filter(s => s.priority==currentPriority);