242 |
243 | This is intended to be similar to the way browsers function with event
244 | handlers on HTML tags, such as `onClick`. The actual semantics are
245 | difficult to replicate exactly, and there may be use-cases that are
246 | impossible, but for most uses, this will do the right thing.
247 |
248 | #### data-can-choose
249 |
250 | If defined, this should be the body of a function that will be
251 | compiled and attached to the situations canChoose method. See the
252 | description of `canView`, above, for details of how the value in this
253 | attribute is interpreted.
254 |
255 | #### data-priority
256 |
257 | If given, this is parsed as a number and set as the situation's
258 | `priority` value.
259 |
260 | #### data-frequency
261 |
262 | If given, this is parsed as a number and set as the situation's
263 | `frequency` value.
264 |
265 | #### data-display-order
266 |
267 | If given, this is parsed as a number and set as the situation's
268 | `displayOrder` value.
269 |
270 | #### data-tags
271 |
272 | If given this should be a set of tags to label the situation with. The
273 | string is split at commas, spaces and tabs. So "foo, bar cube
274 | dock-trog" is parsed as four tags: "foo", "bar", "cube" and
275 | "dock-trog".
276 |
277 | #### data-heading
278 |
279 | If given, then this heading will be used as the `heading` property for
280 | the SimpleSituation. If no `data-option-text` is given, the heading
281 | will also be used in choice blocks.
282 |
283 | #### data-choices
284 |
285 | If given, this should be a list of items to use in generating an
286 | implicit set of situation choices, exactly as for the `choices`
287 | property of `SimpleSituation`. The values of this list is parsed
288 | exactly as for `data-tags`, above, splitting at commas, spaces and
289 | tags.
290 |
291 | #### data-min-choices
292 |
293 | If `data-choices` is given, this value can also be specified. If so,
294 | it is interpreted as an integer and passed to the `minChoices` option
295 | of `SimpleSituation`.
296 |
297 |
298 | #### data-max-choices
299 |
300 | If `data-choices` is given, this value can also be specified. If so,
301 | it is interpreted as an integer and passed to the `maxChoices` option
302 | of `SimpleSituation`.
--------------------------------------------------------------------------------
/games/media/games/tutorial/tutorial.game.en.js:
--------------------------------------------------------------------------------
1 | // ---------------------------------------------------------------------------
2 | // Edit this file to define your game. It should have at least four
3 | // sets of content: undum.game.situations, undum.game.start,
4 | // undum.game.qualities, and undum.game.init.
5 | // ---------------------------------------------------------------------------
6 |
7 | /* A unique id for your game. This is never displayed. I use a UUID,
8 | * but you can use anything that is guaranteed unique (a URL you own,
9 | * or a variation on your email address, for example). */
10 | undum.game.id = "be1c95b9-cbc7-48c6-8e6a-89837aa9113e";
11 |
12 | /* A string indicating what version of the game this is. Versions are
13 | * used to control saved-games. If you change the content of a game,
14 | * the saved games are unlikely to work. Changing this version number
15 | * prevents Undum from trying to load the saved-game and crashing. */
16 | undum.game.version = "1.0";
17 |
18 | /* A variable that changes the fade out speed of the option text on
19 | * a mobile. */
20 | undum.game.mobileHide = 2000
21 |
22 | /* A variable that changes the options fade out speed. */
23 | undum.game.fadeSpeed = 1500
24 |
25 | /* A variable that changes the slide up speed after clicking on an
26 | * option. */
27 | undum.game.slideUpSpeed = 500
28 |
29 | /* The situations that the game can be in. Each has a unique ID. */
30 | undum.game.situations = {
31 | start: new undum.SimpleSituation(
32 | "
Starting Out with Undum
\
33 |

\
34 |
Welcome to the Undum tutorial. Undum is a tool for writing\
35 | hypertext interactive fiction. It has some unique features\
36 | and a visual design that encourages narrative games.
\
37 | \
38 |
Hypertext interactive fiction is the digital equivalent of the\
39 | Choose Your Own Adventure (CYOA) books that were popular in the\
40 | 1980s. The story is told in chunks, and you select from a range\
41 | of options to move it forward. Unlike the book form, however, the\
42 | digital form gives you far more flexibility to tell rich stories\
43 | and introduce more interesting game elements.
\
44 | \
45 |
Click this link to\
46 | continue...
"
47 | ),
48 |
49 | // NB: The 'hub' situation which is the main list of topics, is
50 | // defined wholly in the HTML file, and doesn't have an entry in
51 | // the game.situations dictionary in this file.
52 |
53 | // For variety, here we define a situation using the top-level
54 | // Situation type. This is a neat approach to generate text by
55 | // looking it up in the HTML document. For static text that makes
56 | // more sense than writing it longhand.
57 | situations: new undum.Situation({
58 | enter: function(character, system, from) {
59 | system.write($("#s_situations").html());
60 | },
61 | tags: ["topic"],
62 | optionText: "What Undum Games are Made Of",
63 | displayOrder: 1
64 | }),
65 | todo: new undum.SimpleSituation(
66 | "
Two things can happen in a situation. The character either\
67 | leaves the situation and enters another one, or\
68 | they carry out some action. Actions may\
69 | perform some processing, they may display some results, but\
70 | ultimately they put the character back into the same situation\
71 | again.
\
72 | \
73 |
When you are designing your game, use situations to reflect a\
74 | change in what the character can do. So you would change situation if\
75 | the character pulls a lever to open a trapdoor, for example. Actions\
76 | are intended for situations where the character can examine things\
77 | more closely, or maybe top up their magic by drinking a potion.\
78 | Things that don't affect the state of the world around them.
\
79 | \
80 |
Situations generate content when they are entered,\
81 | exited, and when they receive an action (the\
82 | italicised words are the names of the three methods that do this).\
83 | You can write code to generate content in any way you like, so the\
84 | content that is displayed can be totally dynamic: taking into\
85 | account the current state of the character.\
86 | Content is just plain HTML, so you use regular HTML tags to make\
87 | things bold or italic, or to include\
88 | images. This gives you a lot of flexibility. For example, since Undum\
89 | targets HTML5 browsers, you could use the audio or\
90 | video tags to include rich media.
\
91 | \
92 |
Make sure you've carried out the action above,\
93 | then return to the topic list.
",
94 | {
95 | actions: {
96 | 'do-something': "
You carried out the action, well done.\
97 | You'll notice that the links for this\
98 | situation are still active. This means you\
99 | can click to perform the action again.
"
100 | }
101 | }
102 | ),
103 | links: new undum.SimpleSituation(
104 | "
Between each chunk of new text, Undum inserts a discreet line\
105 | in the margin. This allows you to see at a glance everything that\
106 | has been output as a result of your last click.\
107 | It is particularly useful for small devices, or when\
108 | lots of content has appeared. The window also scrolls so the start\
109 | of the new content is as near to the top of the window as possible.\
110 | This is also designed to help you read more naturally.
\
111 | \
112 |
If you've been watching carefully, you will have noticed that\
113 | parts of the text have been disappearing when you move between\
114 | situations. This isn't a bug! One of the aims of Undum is to give\
115 | game designers the ability to make the transcript of\
116 | the game read as a coherent piece of narrative. However, you often\
117 | need chunks of text that do nothing but offer the reader choices.\
118 | Undum defines a special CSS class to add to your HTML for this\
119 | (remember generated content is just HTML). It is transient,\
120 | and can be applied to paragraphs, divs, or just\
121 | spans (such as this one).
\
122 | \
123 |
You may also have noticed that, when you move situations, all the\
124 | links in the previous situation turn into regular text. This is to\
125 | stop you backtracking and trying previous options when you've already\
126 | committed to one. In other H-IF systems, this is\
127 | done by completely removing the content from previous pages.\
128 | That prevents you going back and reading your story, however.
\
129 | \
130 |
The 'Different Kinds of Links' topic has more\
131 | about these links.\
132 | Let's return to the topic list.
",
133 | {
134 | heading: "Disappearing Content",
135 | diplayOrder: 2,
136 | tags: ["topic"]
137 | }
138 | ),
139 | sticky: new undum.SimpleSituation(
140 | "
There are three types of link in Undum. The first two we've seen\
141 | in previous topics:\
142 | links to change situation and links to carry out an action. When you\
143 | include a link in your output, Undum parses it and wires it up\
144 | correctly. If you create a link with a HTML href attribute\
145 | containing just a name ('ballroom', for\
146 | example) this will send the character to the situation with that\
147 | name. Links\
148 | with two components ('ballroom/view-painting', for example) send\
149 | the character to a new situation and then carry out the\
150 | named action ('view-painting' in this case). To carry out an action\
151 | in the current situation, you can replace the situation name with a\
152 | dot (so it would be './view-painting'). In all cases, if the\
153 | character is already in that situation, then the situation's\
154 | enter method won't be called again.
\
155 | \
156 |

\
157 |
The third type of link, then, is a general hyperlink. If your\
158 | link doesn't consist of a single element or pair of elements, as\
159 | above, then Undum will guess that you have a normal hyperlink. As\
160 | in this link.\
161 | If you have a link that does look like an Undum link, you\
162 | can still force Undum not to interpret it as an action or situation\
163 | move, by adding the CSS class raw to the HTML a tag.\
164 | links that don't have the raw class, but that are considered\
165 | to be non-Undum links (like the link above), will have raw\
166 | added to them before display. This could allow you to style external\
167 | links differently, as we have done here.
\
168 | \
169 |
In the last situation I said you can prevent links from being\
170 | turned into regular text when you move situations. This is done\
171 | by another CSS class: sticky. When you\
172 | leave this situation, you'll notice the\
173 | external link stays active. This can allow you to have options that\
174 | stay valid throughout the narrative, for example, such as a spell to\
175 | teleport home.
",
176 | {
177 | tags: ["topic"],
178 | displayOrder: 3,
179 | heading: "Different Kinds of Links"
180 | }
181 | ),
182 | oneshot: new undum.SimpleSituation(
183 | "
There is one final option for links. If you give a link\
184 | the once CSS class, then that link will disappear\
185 | after it is clicked. This is used (as in\
186 | this link) for\
187 | actions that you only want to be possible once. There is no\
188 | point using 'once' on situation links because they'll be turned\
189 | into text as soon as you click them anyway (unless they are also\
190 | sticky, of course).
Once links are useful\
191 | for actions such as examining an object more carefully. You\
192 | don't want lots of repeated descriptions, so making the link\
193 | a once link is more user friendly.
\
194 |
If you have more than one link to the same action, then all\
195 | matching links will be removed, so you don't have to worry about\
196 | the player having an alternative way to carry out the action.
\
197 |
After you've clicked the link, let's\
198 | move on.
",
199 | {
200 | actions: {
201 | "one-time-action": "
As I said, one time actions are\
202 | mostly used to describe something in\
203 | more detail, where you don't want the\
204 | same descriptive text repeated over and\
205 | over
"
206 | }
207 | }
208 | ),
209 | qualities: new undum.SimpleSituation(
210 | "
Let's talk about the character.\
211 | The character is described by a series of qualities. These\
212 | are numeric values that can describe anything from natural abilities\
213 | to how much of a resource the character controls. Qualities are\
214 | shown in the box on the right of the text.
\
215 | \
216 |
The qualities there are those you started the game with. When you\
217 | go to the next situation, keep your\
218 | eyes on the character panel. You'll notice I'll give you a boost to\
219 | your stamina quality. This process is animated and highlighted to\
220 | draw your attention to it. You could also get a boost of skill\
221 | by carrying out this action as many\
222 | times as you like.
",
223 | {
224 | heading: "Qualities and the Character",
225 | tags: ["topic"],
226 | displayOrder: 4,
227 | actions: {
228 | "skill-boost": function(character, system, action) {
229 | system.setQuality("skill", character.qualities.skill+1);
230 | }
231 | },
232 | exit: function(character, system, to) {
233 | system.setQuality("stamina", character.qualities.stamina+1);
234 | }
235 | }
236 | ),
237 | "quality-types": new undum.SimpleSituation(
238 | "
Not all the qualities in the character panel are displayed as\
239 | numeric. Internally they are all numeric, but different qualities\
240 | get to choose how to display themselves. So 'Luck', for example, is\
241 | displayed as words (based on the FUDGE RPG's adjective scale),\
242 | and 'Novice' is using just a check-mark.
\
243 | \
244 |
To see how Luck changes, try using this\
245 | luck-boosting action or this\
246 | luck-reducing action. Notice that\
247 | luck uses a numeric bonus when it runs out of words. There are a range\
248 | of different display types provided with Undum, and you can easily\
249 | add your own too.
\
250 | \
251 |
When you leave this situation,\
252 | I'll set 'Novice' to zero. Watch\
253 | the character panel, and you'll see that Novice decides it doesn't\
254 | need to be displayed any more and will be removed. You will also see\
255 | that when the last\
256 | quality in a group is removed ('Novice' is in the 'Progress' group),\
257 | then the group heading is also removed. You can tell Undum what\
258 | group each quality belongs to, and what order they should be listed.\
259 |
",
260 | {
261 | actions: {
262 | "luck-boost": function(character, system, action) {
263 | system.setQuality("luck", character.qualities.luck+1);
264 | },
265 | "luck-reduce": function(character, system, action) {
266 | system.setQuality("luck", character.qualities.luck-1);
267 | }
268 | },
269 | exit: function(character, system, to) {
270 | system.setQuality("novice", 0);
271 | }
272 | }
273 | ),
274 | "character-text": new undum.SimpleSituation(
275 | "
Character Text
\
276 |
Above the list of qualities is a short piece of text, called\
277 | the character-text. This describes the character in some way. It\
278 | can be set by any action or when entering or leaving a situation.\
279 | It is just regular HTML content, as for all text in Undum. It can\
280 | also contain Undum links, so this is another place you can put\
281 | actions that the character can carry out over a long period of time.\
282 |
\
283 |
Let's go back to the\
284 | topic list. As you do, I'll change the\
285 | character text. Notice that it is highlighted, just the same as\
286 | when a quality is altered.
",
287 | {
288 | exit: function(character, system, to) {
289 | system.setCharacterText(
290 | "
We're nearing the end of the road.
"
291 | );
292 | }
293 | }
294 | ),
295 | progress: new undum.SimpleSituation(
296 | "
Sometimes you want to make the change in a quality into a more\
297 | significant event. You can do this by animating the change in\
298 | quality. If you boost your\
299 | stamina, you will see the stamina change in the normal\
300 | way in the character panel. But you will also see a progress\
301 | bar appear and animate below.
",
302 | {
303 | tags: ["topic"],
304 | heading: "Showing a Progress Bar",
305 | displayOrder: 5,
306 | actions: {
307 | // I'm going indirect here - the link carries out an
308 | // action, which then uses doLink to directly change
309 | // the situation. This isn't the recommended way (I
310 | // could have just changed situation in the link), but
311 | // it illustrates the use of doLink.
312 | "boost-stamina-action": function(character, system, action) {
313 | system.doLink("boost-stamina");
314 | }
315 | },
316 | exit: function(character, system, to) {
317 | system.animateQuality(
318 | 'stamina', character.qualities.stamina+1
319 | );
320 | }
321 | }
322 | ),
323 | "boost-stamina": new undum.SimpleSituation(
324 | "
\
325 |
\
326 | The progress bar is also useful in situations where the\
327 | character block is displaying just the whole number of a quality,\
328 | whereas some action changes a fraction. If the quality is displaying\
329 | the character's level, for example, you might want to show a progress\
330 | bar to indicate how near the character is to levelling up.
\
331 | \
332 |
After a few seconds, the progress bar disappears, to keep the\
333 | focus on the text. Undum isn't designed for games where a lot of\
334 | statistic management is needed. If you want a change to be part\
335 | of the permanent record of the game, then write it in text.
\
336 | \
337 |
Let's return to the topic list.
"
338 | ),
339 | // Again, we'll retrieve the text we want from the HTML file.
340 | "saving": new undum.Situation({
341 | enter: function(character, system, from) {
342 | system.write($("#s_saving").html());
343 | },
344 | tags: ["topic"],
345 | displayOrder: 6,
346 | optionText: "Saving and Loading"
347 | }),
348 |
349 | "implicit-boost": new undum.SimpleSituation(
350 | "
Your luck has been boosted, check the\
351 | list of options to see if they have changed.
",
352 | {
353 | tags: ["example"],
354 | enter: function(character, system, from) {
355 | system.animateQuality("luck", character.qualities.luck+1)
356 | system.doLink('example-choices');
357 | },
358 | optionText: "Boost Your Luck",
359 | displayOrder: 1,
360 | canView: function(character, system, host) {
361 | return character.qualities.luck < 4;
362 | }
363 | }
364 | ),
365 | "implicit-drop": new undum.SimpleSituation(
366 | "
Your luck has been reduced, check the\
367 | list of options to see if they have changed.
",
368 | {
369 | tags: ["example"],
370 | enter: function(character, system, from) {
371 | system.animateQuality("luck", character.qualities.luck-1)
372 | system.doLink('example-choices');
373 | },
374 | optionText: "Reduce Your Luck",
375 | displayOrder: 2,
376 | canView: function(character, system, host) {
377 | return character.qualities.luck > -4;
378 | }
379 | }
380 | ),
381 | "high-luck-only": new undum.SimpleSituation(
382 | "
Your luck is higher than 'fair'. The link to this \
383 | situation would not\
384 | have appeared if it were lower.
",
385 | {
386 | tags: ["example"],
387 | enter: function(character, system, from) {
388 | system.doLink('example-choices');
389 | },
390 | optionText: "High Luck Option",
391 | displayOrder: 3,
392 | canView: function(character, system, host) {
393 | return character.qualities.luck > 0;
394 | }
395 | }
396 | ),
397 | "low-luck-only": new undum.SimpleSituation(
398 | "
Your luck is lower than 'fair'. The link to this situation \
399 | appears whether\
400 | it is low or high, but can only be chosen if it is low. It does this\
401 | by defining a canChoose method.
",
402 | {
403 | tags: ["example"],
404 | enter: function(character, system, from) {
405 | system.doLink('example-choices');
406 | },
407 | optionText: "Low Luck Option (requires low luck to be clickable)",
408 | displayOrder: 3,
409 | canChoose: function(character, system, host) {
410 | return character.qualities.luck < 0;
411 | }
412 | }
413 | ),
414 |
415 | "last": new undum.SimpleSituation(
416 | "
Where to Go Now
\
417 |
So that's it. We've covered all of Undum. This situation is the\
418 | end, because it has no further links. The 'The End' message is\
419 | just in the HTML output of this situation, it isn't anything special\
420 | to Undum
\
421 | \
422 |
I've added an\
423 | inspiration quality to your character list. Its time for you to\
424 | crack open the game file and write your own story.
\
425 |
The End
",
426 | {
427 | tags: ["topic"],
428 | optionText: "Finish the Tutorial",
429 | displayOrder: 8,
430 | enter: function(character, system, from) {
431 | system.setQuality("inspiration", 1);
432 | system.setCharacterText(
433 | "
You feel all inspired, why not have a go?
"
434 | );
435 | }
436 | }
437 | )
438 | };
439 |
440 | // ---------------------------------------------------------------------------
441 | /* The Id of the starting situation. */
442 | undum.game.start = "start";
443 |
444 | // ---------------------------------------------------------------------------
445 | /* Here we define all the qualities that our characters could
446 | * possess. We don't have to be exhaustive, but if we miss one out then
447 | * that quality will never show up in the character bar in the UI. */
448 | undum.game.qualities = {
449 | skill: new undum.IntegerQuality(
450 | "Skill", {priority:"0001", group:'stats'}
451 | ),
452 | stamina: new undum.NumericQuality(
453 | "Stamina", {priority:"0002", group:'stats'}
454 | ),
455 | luck: new undum.FudgeAdjectivesQuality( // Fudge as in the FUDGE RPG
456 | "
Luck",
457 | {priority:"0003", group:'stats'}
458 | ),
459 |
460 | inspiration: new undum.NonZeroIntegerQuality(
461 | "Inspiration", {priority:"0001", group:'progress'}
462 | ),
463 | novice: new undum.OnOffQuality(
464 | "Novice", {priority:"0002", group:'progress', onDisplay:"✓"}
465 | )
466 | };
467 |
468 | // ---------------------------------------------------------------------------
469 | /* The qualities are displayed in groups in the character bar. This
470 | * determines the groups, their heading (which can be null for no
471 | * heading) and ordering. QualityDefinitions without a group appear at
472 | * the end. It is an error to have a quality definition belong to a
473 | * non-existent group. */
474 | undum.game.qualityGroups = {
475 | stats: new undum.QualityGroup(null, {priority:"0001"}),
476 | progress: new undum.QualityGroup('Progress', {priority:"0002"})
477 | };
478 |
479 | // ---------------------------------------------------------------------------
480 | /* This function gets run before the game begins. It is normally used
481 | * to configure the character at the start of play. */
482 | undum.game.init = function(character, system) {
483 | character.qualities.skill = 12;
484 | character.qualities.stamina = 12;
485 | character.qualities.luck = 0;
486 | character.qualities.novice = 1;
487 | character.qualities.inspiration = 0;
488 | system.setCharacterText("
You are starting on an exciting journey.
");
489 | };
490 |
--------------------------------------------------------------------------------
/games/media/games/tutorial/tutorial.game.ru.js:
--------------------------------------------------------------------------------
1 | // Перевод на русский: Oreolek, 2013
2 | // ---------------------------------------------------------------------------
3 | // Отредактируйте этот файл, чтобы описать вашу игру. Он должен иметь не
4 | // менее четырёх разделов данных: undum.game.situations, undum.game.start,
5 | // undum.game.qualities, и undum.game.init.
6 | // ---------------------------------------------------------------------------
7 |
8 | /* Уникальный идентификатор вашей игры. Он никогда не отображается.
9 | * Я использую UUID, но вы можеет использовать всё что гарантированно
10 | * уникально (URL, которым вы владеете, или вариацию вашего адреса
11 | * e-mail, например).*/
12 | undum.game.id = "349baf43-9ade-49a8-86d0-24e3de3ce042";
13 |
14 | /* A string indicating what version of the game this is. Versions are
15 | * used to control saved-games. If you change the content of a game,
16 | * the saved games are unlikely to work. Changing this version number
17 | * prevents Undum from trying to load the saved-game and crashing. */
18 | undum.game.version = "1.0";
19 |
20 | /* Ситуации, в которых может быть игра. Каждая имеет уникальный ID. */
21 |
22 | // Строки локализации
23 | undum.language["ru"]["start_title"] = "Знакомство с Undum";
24 | undum.language["ru"]["situations_title"] = "Из чего сделаны игры Undum";
25 | undum.language["ru"]["links_title"] = "Смена наполнения";
26 | undum.language["ru"]["sticky_title"] = "Разные виды ссылок";
27 | undum.language["en"]["qualities_title"] = "Qualities and the Character";
28 | undum.language["ru"]["qualities_title"] = "Качества и персонаж";
29 | undum.language["en"]["progress_title"] = "Showing a Progress Bar";
30 | undum.language["ru"]["progress_title"] = "Отображение прогресса";
31 | undum.language["en"]["saving_title"] = "Saving and Loading";
32 | undum.language["ru"]["saving_title"] = "Сохранение и загрузка";
33 | undum.language["en"]["last_title"] = "Finish the Tutorial";
34 | undum.language["ru"]["last_title"] = "Закончить обучение";
35 |
36 | undum.game.situations = {
37 | start: new undum.SimpleSituation(
38 | "
"+"start_title".l()+"
\
39 |

\
40 |
Добро пожаловать в обучающую игру по Undum. Undum - это инструмент для написания\
41 | гипертекстовой интерактивной литературы. Он обладает некоторыми уникальными возможностями\
42 | и визуальным дизайном, который поддерживает повествующие игры.
\
43 | \
44 |
Гипертекстовая интерактивная литература - это цифровой эквивалент книгам\
45 | Choose Your Own Adventure (CYOA), которые были популярны в\
46 | 1980х. История рассказывается кусочками, и вы выбираете из нескольких \
47 | вариантов, чтобы продвинуть её дальше. Тем не менее, в отличие от книжной формы, цифровая\
48 | версия даёт вам намного больше гибкости, чтобы рассказать богатые истории\
49 | и представить более интересные элементы игры.
\
50 | \
51 |
А сейчас давайте продолжим обучение.\
52 | Нажмите на эту ссылку, чтобы продвинуться дальше.
"
53 | ),
54 | // NB: Ситуация 'hub', основной список тем, задана полностью в HTML, и не редактируется вручную
55 | // через словарь game.situations в этом файле.
56 |
57 | // Для разнообразия, здесь мы задаём ситуацию, используя высокоуровневый тип Situation.
58 | // Это прекрасный подход, чтобы сгенерировать текст, просто найдя его в HTML документе.
59 | // Для статичного текста в этом больше смысла, чем записывать его просто так.
60 | situations: new undum.Situation({
61 | enter: function(character, system, from) {
62 | system.write($("#s_situations").html());
63 | },
64 | tags: ["topic"],
65 | optionText: "situations_title".l(),
66 | displayOrder: 1
67 | }),
68 | todo: new undum.SimpleSituation(
69 | "
В ситуации может произойти две вещи. Либо персонаж\
70 | покидает ситуацию и входит в другую, либо\
71 | он выполняет некоторое действие. Действия могут\
72 | выполнять некоторые вычисления, могут выводить какие-нибудь результаты, но\
73 | все они возвращают персонажа обратно в ту же ситуацию.
\
74 | \
75 |
Когда вы создаёте свою игру, используйте ситуации, чтобы отразить\
76 | изменения в том, что може сделать персонаж. Так, вы можете изменить ситуацию если персонаж\
77 | тянет рычаг, чтобы открыть люк, например. Действия\
78 | предназначены для ситуаций, где персонаж может изучать вещи более пристально\
79 | , а может быть улучшить свою магию, выпив зелья.\
80 | Это вещи, которые не влияют на мир вокруг них.
\
81 | \
82 |
Ситуации генерируют содержимое, когда в них входят (метод enter),\
83 | выходят (exit), и когда они получают действие (act).\
84 | Вы можете написать код, который будет генерировать текст любым удобным вам способом, \
85 | чтобы отображаемое содержимое могло быть полностью динамичным, \
86 | принимая во внимание текущее состояние персонажа.
\
87 | Содержимое - это обычный HTML, поэтому вы можете использовать все HTML теги, чтобы выделить\
88 | что-то в тексте или добавить иллюстрации.Это даёт вам огромную гибкость. Например, так как Undum\
89 | нацелен на HTML 5, вы можете использовать теги audio или\
90 | video, чтобы вставить музыкальное или видео оформление.
\
91 | \
92 |
Убедитесь в том, что вы выполнили действие выше,\
93 | а затем продолжайте.
",
94 | {
95 | actions: {
96 | 'do-something': "
Браво, вы выполнили действие.\
97 | Заметьте, что ссылки для этой ситуации всё ещё активны.\
98 | Это означает,что вы можете нажать на них, чтобы\
99 | выполнить действие ещё раз.
"
100 | }
101 | }
102 | ),
103 | links: new undum.SimpleSituation(
104 | "
Между каждым кусочком нового текста Undum вставляет отчётливую линию\
105 | на полях. Она позволяет вам быстро увидеть всё, что было выдано\
106 | в качестве результата вашего последнего клика.\
107 | Это очень удобно для маленьких устройств, или когда появилось\
108 | очень много текста. Также окно перемещается таким образом, что начало\
109 | нового содержимого приходится настолько близко к верхнему краю окна, насколько возможно.\
110 | Это также сделано для того, чтобы помочь вам читать натуральнее.
\
111 | \
112 |
Если вы внимательно смотрели, вы заметили, что некоторые части\
113 | текста исчезали, когда вы выходили из ситуаций. Это не баг!\
114 | Одна из целей Undum - это дать геймдизайнерам возможность сделать\
115 | запись игры связным рассказом.\
116 | Тем не менее, вам часто нужны кусочки текста, которые ничего не делают, но просто\
117 | предлагают читателю выбор.\
118 | Для этого Undum определяет специальный CSS класс для добавления в ваш HTML\
119 | (помните, сгенерированное содержимое - это просто HTML). Этот класс называется transient\
120 | и может быть применён к параграфам, div'ам или просто\
121 | span'ам (как вот этот).
\
122 | \
123 |
также вы могли заметить, что, когда вы перемещаетесь в другую ситуацию, все ссылки\
124 | в предыдущей превращаются в обычный текст. Это сделано для того, чтобы не дать вам\
125 | отступить и попробовать предыдущие варианты ответа, когда вы уже выбрали один из них.\
126 | В других системах гипертекстовой интерактивной литературы это делается при помощи полной очистки предыдущих страниц.\
127 | Но это не позволяет вам вернуться и перечитать вашу историю.
\
128 | \
129 |
Тема \""+"sticky_title".l()+"\" содержит больше информации об этих ссылках.\
130 | Вернёмся к списку тем.
.",
131 | {
132 | heading: "links_title".l(),
133 | diplayOrder: 2,
134 | tags: ["topic"]
135 | }
136 | ),
137 | sticky: new undum.SimpleSituation(
138 | "
В Undum существует три типа ссылок. Мы уже видели первые два:\
139 | ссылки смены ситцаций и ссылки, вызывающие действие. Когда вы\
140 | включаете ссылку в ваш текст, undum распознаёт её и оформляет\
141 | подобающим образом. Если вы создаёте ссылку с атрибутом HTML href,\
142 | содержащим только имя ('зал', например), то она отправит персонажа\
143 | в ситуацию с этим именем. Ссылки с двумя компонентами ('зал/посмотреть-картину')\
144 | отправят персонажа в новую ситуацию и тогда вызовут действие в\
145 | текущей ситуации. Вы можете заменить имя ситуации точкой ('./посмотреть-картину'). В\
146 | любом случае, если персонаж уже находится в этой ситуации, то её метод enter\
147 | ещё раз вызываться не будет.
\
148 | \
149 |

\
150 |
Наконец, третий тип ссылок - это обычная гиперссылка. Если ваша\
151 | ссылка не состоит из одного элемента или пары элементов, как описано выше, то\
152 | Undum догадается, что вы имели в виду обычную гиперссылку. Например, \
153 | как в этом случае.\
154 | Если ваша ссылка всё-таки выглядит как ссылка Undum, то вы\
155 | всё ещё можете заставить Undum не интерпретировать её как ситуацию или действие, добавив\
156 | CSS класс raw к тегу HTML a.\
157 | Ссылкам, которые не относятся к классу raw, но угадываются как\
158 | не-Undum, класс raw добавится автоматически перед отображением.\
159 | Это позволит вам выделить внешние ссылки особым образом, как мы сделали в этой игре.
\
160 | \
161 |
В последней ситуации я сказал, что вы можете остановить ссылки от превращения в обычный текст, когда\
162 | вы меняете ситуацию. Это делается при помощи другого класса\
163 | CSS: sticky. Когда вы\
164 | покинете эту ситуацию, вы заметите, что внешняя ссылка осталась активной.\
165 | Это позволяет вам предлагать ссылки, которые останутся рабочими в течение всего рассказа,\
166 | например, ссылка заклинания телепортации домой.
",
167 | {
168 | tags: ["topic"],
169 | displayOrder: 3,
170 | heading: "sticky_title".l()
171 | }
172 | ),
173 | oneshot: new undum.SimpleSituation(
174 | "
Ещё одна последняя настройка ссылок. Если вы назначите ссылке CSS класс\
175 | once, то она исчезнет после нажатия. Это используется \
176 | (проверьте сами) для\
177 | действий, которые вы хотите сделать однократными. Нет смысла использовать\
178 | 'once' на ссылках ситуаций, потому что они всё равно превратятся в текст, как только вы на них нажмёте\
179 | ( конечно, если они не помечены как sticky).
Однократные ссылки полезны\
180 | для таких действий, как внимательное изучение объекта. Вам не захочется\
181 | повторять описание много раз, поэтому сделать ссылку однократной было бы\
182 | дружелюбнее для пользователя.
\
183 |
Если у вас более, чем одна ссылка относится к одному действию, то все соответсвующие ссылки\
184 | будут удалены, так что вам не придётся заботиться о игроке, который найдёт способ\
185 | ещё раз вызвать действие.
\
186 |
После того, как вы нажмёте на ссылку, мы \
187 | продолжим.
",
188 | {
189 | actions: {
190 | "one-time-action": "
Как я уже говорил, однократные действия\
191 | в большинстве своём используются для описания\
192 | чего-то в деталях, когда вы не хотите повторять\
193 | один и тот же текст описания в разных местах рассказа.
"
194 | }
195 | }
196 | ),
197 | qualities: new undum.SimpleSituation(
198 | "
Хватит о ситуациях, давайте поговорим о персонаже. Персонаж описывается\
199 | при помощи серии качеств. Это численные значения, которые могут описать\
200 | всё от врождённых способностей до количества ресурсов,подконтрольных персонажу.\
201 | Качества показаны в блоке справа от текста.
\
202 | \
203 |
Качества в этом блоке - это те, с которыми вы начали игру. Когда вы\
204 | перейдёте к следующей ситуации, не отводите глаз\
205 | от панели персонажа. Вы заметите, что я подниму ваше качество Ловкости.\
206 | Этот процесс анимирован и подсвечен, чтобы привлечь ваше внимание.\
207 | Также вы можете получить повышение Силы, выполнив\
208 | это действие столько раз, сколько захочется.
",
209 | {
210 | heading: "qualities_title".l(),
211 | tags: ["topic"],
212 | displayOrder: 4,
213 | actions: {
214 | "skill-boost": function(character, system, action) {
215 | system.setQuality("skill", character.qualities.skill+1);
216 | }
217 | },
218 | exit: function(character, system, to) {
219 | system.setQuality("stamina", character.qualities.stamina+1);
220 | }
221 | }
222 | ),
223 | "quality-types": new undum.SimpleSituation(
224 | "
Не все качества в панели персонажа отображаются как числа. Внутри они\
225 | все числовые, но разные качества могут выбирать, как отображать себя. Например,\
226 | Удача отображается словами (на основе шкалы прилагательных FUDGE RPG)\
227 | ,а «Новичок» использует лишь галочку.
\
228 | \
229 |
Чтобы увидеть, как изменяется Удача, попробуйте использовать это\
230 | удачное действие или это\
231 | неудачное действие. Заметьте, как Удача\
232 | использует числовой бонус, когда у неё заканчиваются слова. В Undum\
233 | существует несколько различных видов отображения, и вы можете легко добавить своё.
\
234 | \
235 |
Когда вы покинете эту ситуацию,\
236 | я поставлю «Новичок» на ноль. Смотрите на панель персонажа, и вы\
237 | увидите, что Новичок решает, что ему более не нужно быть видимым, и удаляет себя.\
238 | Вы также увидите,что,когда последнее качество в группе удаляется(а «Новичок» находится в группе «Прогресс»),\
239 | тогда заголовок группы также удаляется. Вы можете сообщить Undum, какой группе\
240 | принадлежит каждое из качеств, и в каком порядке они должны стоять.\
241 |
",
242 | {
243 | actions: {
244 | "luck-boost": function(character, system, action) {
245 | system.setQuality("luck", character.qualities.luck+1);
246 | },
247 | "luck-reduce": function(character, system, action) {
248 | system.setQuality("luck", character.qualities.luck-1);
249 | }
250 | },
251 | exit: function(character, system, to) {
252 | system.setQuality("novice", 0);
253 | }
254 | }
255 | ),
256 | "character-text": new undum.SimpleSituation(
257 | "
Текст персонажа
\
258 |
Над списком качеств находится коротенький кусочек текста, называемый\
259 | текстом персонажа. Он как-то описывает героя. Он может быть задан\
260 | любым действием или когда вы входите в или покидаете ситуацию.\
261 | Это обычное содержимое HTML, как и любой другой текст в Undum.\
262 | Он также может содержать ссылки Undum, так что это - ещё одно место, куда\
263 | вы можете поместить действия, которые персонаж может выполнять в течение долгого периода времени.\
264 |
\
265 |
Давайте вернёмся к списку.\
266 | А пока вы это сделаете, я сменю\
267 | текст персонажа. Заметьте, как он подсвечивается, в точности как и качество,\
268 | когда изменяется.
",
269 | {
270 | exit: function(character, system, to) {
271 | system.setCharacterText(
272 | "
Мы приближаемся к концу дороги.
"
273 | );
274 | }
275 | }
276 | ),
277 | progress: new undum.SimpleSituation(
278 | "
Иногда вы хотите сделать изменение качества более заметным событием.\
279 | Вы можете сделать это, анимировав его. Если вы\
280 | поднимете вашу Ловкость,\
281 | то вы увидите, что Ловкость изменяется как обычно в панели персонажа.\
282 | Но вы также увидите появление и анимацию полоски прогресса чуть ниже.
",
283 | {
284 | tags: ["topic"],
285 | heading: "progress_title".l(),
286 | displayOrder: 5,
287 | actions: {
288 | // Здесь я иду по неявному пути - ссылка выдаёт действие,
289 | // которое затем использует doLink, чтобы напрямую изменить
290 | // ситуацию. Это не рекомендованный путь (я мог бы
291 | // просто изменить ситуацию по ссылке, но он демонстрирует
292 | // использование doLink.
293 | "boost-stamina-action": function(character, system, action) {
294 | system.doLink("boost-stamina");
295 | }
296 | },
297 | exit: function(character, system, to) {
298 | system.animateQuality(
299 | 'stamina', character.qualities.stamina+1
300 | );
301 | }
302 | }
303 | ),
304 | "boost-stamina": new undum.SimpleSituation(
305 | "
Полоса прогресса также удобна в ситуациях, где блок персонажа\
306 | показывает только общее число качеств, а тем временем какое-нибудь действие меняет\
307 | одно из них. Например, вы можете захотеть показать прогресс персонажа к следующему уровню - \
308 | имея уровень персонажа качеством, конечно.
\
309 | \
310 |

\
311 |
После нескольких секунд, полоса прогресса исчезает, чтобы оставить\
312 | внимание на тексте. Undum не сделан для игр, где нужно большое управление\
313 | статистиками. Если вы хотите, чтобы изменение было частью постоянной\
314 | записи игры, напишите его в тексте.
\
315 | \
316 |
Давайте почитаем про что-нибудь ещё.
"
317 | ),
318 | // Опять, мы получаем текст из HTML файла.
319 | "saving": new undum.Situation({
320 | enter: function(character, system, from) {
321 | system.write($("#s_saving").html());
322 | },
323 | tags: ["topic"],
324 | displayOrder: 6,
325 | optionText: "saving_title".l(),
326 | }),
327 | "implicit-boost": new undum.SimpleSituation(
328 | "
Ваша Удача была увеличена, проверьте список \
329 | ссылок, вдруг они изменились?.
",
330 | {
331 | tags: ["example"],
332 | enter: function(character, system, from) {
333 | system.animateQuality("luck", character.qualities.luck+1)
334 | system.doLink('example-choices');
335 | },
336 | optionText: "Увеличить вашу Удачу",
337 | displayOrder: 1,
338 | canView: function(character, system, host) {
339 | return character.qualities.luck < 4;
340 | }
341 | }
342 | ),
343 | "implicit-drop": new undum.SimpleSituation(
344 | "
Ваша Удача была уменьшена, проверьте список \
345 | ссылок, вдруг они изменились?.
",
346 | {
347 | tags: ["example"],
348 | enter: function(character, system, from) {
349 | system.animateQuality("luck", character.qualities.luck-1)
350 | system.doLink('example-choices');
351 | },
352 | optionText: "Уменьшить вашу Удачу",
353 | displayOrder: 2,
354 | canView: function(character, system, host) {
355 | return character.qualities.luck > -4;
356 | }
357 | }
358 | ),
359 | "high-luck-only": new undum.SimpleSituation(
360 | "
Ваша Удача выше чем 'нормально'. Ссылка на эту ситуацию не появилась бы, \
361 | если бы вам она была меньше.
",
362 | {
363 | tags: ["example"],
364 | enter: function(character, system, from) {
365 | system.doLink('example-choices');
366 | },
367 | optionText: "Выбор Большой Удачи",
368 | displayOrder: 3,
369 | canView: function(character, system, host) {
370 | return character.qualities.luck > 0;
371 | }
372 | }
373 | ),
374 | "low-luck-only": new undum.SimpleSituation(
375 | "
Ваша Удача ниже, чем 'нормально'. Ссылка на эту ситуацию появляется \
376 | в любом случае, но вы можете выбрать её только если вы сбросите Удачу.\
377 | Это проверяет метод canChoose.
",
378 | {
379 | tags: ["example"],
380 | enter: function(character, system, from) {
381 | system.doLink('example-choices');
382 | },
383 | optionText: "Выбор Низкой Удачи (треубет низкую Удачу для нажатия)",
384 | displayOrder: 3,
385 | canChoose: function(character, system, host) {
386 | return character.qualities.luck < 0;
387 | }
388 | }
389 | ),
390 |
391 | "last": new undum.SimpleSituation(
392 | "
Куда теперь
\
393 |
Итак, это всё. Мы показали весь Undum. Эта ситуация - конечная, поскольку\
394 | в ней нет дальнейших ссылок. Сообщение «Конец» - это просто HTML вывод ситуации.\
395 | В нём нет ничего особенного для Undum.
\
396 | \
397 |
Я добавил качество вдохновления в ваш листок персонажа.\
398 | Настало время для вас вскрыть файл с игрой и написать свою собственную историю.
\
399 |
Конец
",
400 | {
401 | tags: ["topic"],
402 | optionText: "last_title".l(),
403 | displayOrder: 8,
404 | enter: function(character, system, from) {
405 | system.setQuality("inspiration", 1);
406 | system.setCharacterText(
407 | "
Вы чувствуете себя вдохновлённым, почему бы не попробовать?
"
408 | );
409 | }
410 | }
411 | )
412 | };
413 |
414 | // ---------------------------------------------------------------------------
415 | /* Идентификатор стартовой ситуации. */
416 | undum.game.start = "start";
417 |
418 | // ---------------------------------------------------------------------------
419 | /* Здесь мы определяем все качества, присущие нашим персонажам.
420 | * Мы не должны быть исчерпывающими, но если мы что-то пропустим, то
421 | * это качество никогда не покажется в панели персонажа. */
422 | undum.game.qualities = {
423 | skill: new undum.IntegerQuality(
424 | "Сила", {priority:"0001", group:'stats'}
425 | ),
426 | stamina: new undum.NumericQuality(
427 | "Ловкость", {priority:"0002", group:'stats'}
428 | ),
429 | luck: new undum.FudgeAdjectivesQuality( // Fudge as in the FUDGE RPG
430 | "
Удача",
431 | {priority:"0003", group:'stats'}
432 | ),
433 |
434 | inspiration: new undum.IntegerQuality(
435 | "Вдохновение", {priority:"0001", group:'progress'}
436 | ),
437 | novice: new undum.OnOffQuality(
438 | "Новичок", {priority:"0002", group:'progress', onDisplay:"✓"}
439 | )
440 | };
441 |
442 | // ---------------------------------------------------------------------------
443 | /* Качества отображаются по группам в панели персонажа. Эта функция определяет группы,
444 | * их заголовки (которые могут быть null - нет заголовка), и порядок.
445 | * Качества без группы появляются в конце. Описание качества,
446 | * приналежащее к несуществующей группе, является ошибкой.*/
447 | undum.game.qualityGroups = {
448 | stats: new undum.QualityGroup(null, {priority:"0001"}),
449 | progress: new undum.QualityGroup('Прогресс', {priority:"0002"})
450 | };
451 |
452 | // ---------------------------------------------------------------------------
453 | /* Эта функция запускается перед началом игры. Обычно она используется
454 | * для того, чтобы настроить персонажа перед игрой. */
455 | undum.game.init = function(character, system) {
456 | character.qualities.skill = 12;
457 | character.qualities.stamina = 12;
458 | character.qualities.luck = 0;
459 | character.qualities.novice = 1;
460 | system.setCharacterText("
Вы начинаете захватывающее путешествие.
");
461 | };
462 |
--------------------------------------------------------------------------------
/games/media/games/tutorial/tutorial.game.de.js:
--------------------------------------------------------------------------------
1 | // ---------------------------------------------------------------------------
2 | // Bearbeite diese Datei, um dein Spiel zu erstellen. Sie sollte
3 | // mindestens die folgenden vier Abschnitte enthalten:
4 | // undum.game.situations, undum.game.start,
5 | // undum.game.qualities, und undum.game.init.
6 | // ---------------------------------------------------------------------------
7 |
8 | /* Eine eindeutige Kennung fuer das Spiel (wird nicht im Spiel angezeigt)
9 | * Man kann eine UUID benutzen oder etwas anderes, was garantiert einzigartig
10 | * ist, z.B. eine eigene URL oder eine Variation der eigenen E-Mail-Adresse). */
11 | undum.game.id = "349baf43-9ade-49a8-86d0-24e3de3ce072";
12 |
13 | /* Eine Zeichenkette, die angibt, um welche Version des Spiels es sich handelt.
14 | * Dies ist wichtig fuers Speichern und Laden: Wenn man den Inhalt eines Spiels
15 | * aendert, funktioniert ein gespeicherter Spielstand wahrscheinlich nicht mehr.
16 | * Wenn man nach einer Aenderung des Inhalts diese Versionsnummer ebenfalls
17 | * aendert, dann wird damit verhindert, dass Undum einen Spielstand aus einer
18 | * alten Version zu laden versucht und dabei eventuell abstuerzt. */
19 | undum.game.version = "1.0";
20 |
21 | /* Die Situationen, in denen das Spiel sich befinden kann. Jede hat eine eindeutige Kennung. */
22 | undum.game.situations = {
23 | start: new undum.SimpleSituation(
24 | "
Los geht's mit Undum
\
25 |

\
26 |
Willkommen beim Undum-Tutorium. Mit Undum kann man\
27 | interaktive Literatur in Hypertext-Form schreiben. Seine Features\
28 | und seine visuelle Gestaltung sind dazu gedacht, Spiele zu machen, die eine\
29 | Geschichte erzählen.
\
30 | \
31 |
Interaktive Literatur im Hypertext-Format ist im Grunde eine digitale\
32 | Ausgabe der beliebten Spielbücher. Die Geschichte wird in kleinen\
33 | Abschnitten erzählt, und der Spieler wählt eine von mehreren\
34 | Möglichkeiten aus, wie es weitergehen soll. Anders als die Bücher\
35 | von früher ist die digitale Ausgabe aber viel flexibler - man kann\
36 | variantenreichere Geschichten erzählen und interessantere\
37 | Spiel-Elemente einbauen.
\
38 | \
39 |
Erstmal geht's jetzt mit dem Tutorium weiter.\
40 | Klick auf diesen Link, um fortzufahren.
"
41 | ),
42 | // Zur Abwechslung definieren wir hier mal eine Situation mit Hilfe des
43 | // allgemeinen "Situation"-Datentyps. Auf diese Weise erzeugen wir
44 | // Text, indem wir ihn aus der HTML-Datei des Spiels ziehen. Das ist bei statischem Text
45 | // sinnvoller als ihn hier komplett auszuschreiben.
46 | rooms: new undum.Situation({
47 | enter: function(character, system, from) {
48 | system.write($("#s_rooms").html());
49 | }
50 | }),
51 | todo: new undum.SimpleSituation(
52 | "
Zwei Dinge können in einer Situation passieren. Entweder\
53 | verlässt die Spielfigur diese Situation und gerät\
54 | in eine andere, oder sie führt eine Aktion aus.\
55 | Aktionen können z.B. Daten verarbeiten und Ergebnisse anzeigen,\
56 | aber letztlich kehrt die Spielfigur dabei immer wieder in dieselbe Situation\
57 | zurück.
\
58 | \
59 |
Wenn du dein Spiel entwirfst, dann benutze Situationen, um darzustellen,\
60 | dass die Spielfigur nun etwas Neues tun kann. Wechsle z.B. in eine neue\
61 | Situation, wenn der Spieler einen Hebel zieht und dadurch eine Falltür\
62 | öffnet. Aktionen sind dagegen für Situationen gedacht, in denen\
63 | die Spielfigur Dinge genauer untersuchen kann, oder z.B. einen Zaubertrank\
64 | trinken kann, um ihren Magie-Wert aufzustocken. Kurz gesagt Handlungen,\
65 | die den Zustand der Umgebung nicht verändern.
\
66 | \
67 |
Situationen erzeugen Text, wenn man in sie hineingerät (enter),\
68 | wenn man sie verlässt (exit), und wenn man in ihnen\
69 | eine Aktion ausführt (act) (die kursiv gesetzten\
70 | Begriffe sind die Namen der drei Methoden, die im Code dafür benutzt werden).\
71 | Wenn man möchte, kann man mit eigenem Code den erzeugten\
72 | Inhalt beliebig verändern; der Inhalt ist dynamisch, dadurch\
73 | kann man z.B. den momentanen Zustand der Spielfigur berücksichtigen.\
74 | Der Inhalt besteht einfach aus normalem HTML, also kann man die\
75 | üblichen HTML-Tags benutzen, um Text\
76 | fett oder kursiv zu machen,\
77 | oder um Bilder einzubauen. Hier hast du viele Möglichkeiten,\
78 | z.B. könntest du audio oder\
79 | video Tags nehmen, um Multimedia-Inhalte anzuzeigen\
80 | (Undum ist auf HTML5 ausgelegt).
\
81 | \
82 |
Probiere bitte die Aktion oben aus,\
83 | dann geht's weiter.
",
84 | {
85 | actions: {
86 | // wenn eine Aktions-Kennung einen Bindestrich enthaelt wie die Folgende,
87 | // dann sollte sie in (einfachen oder doppelten) Anfuehrungsstrichen stehen
88 | 'do-something': "
Du hast die Aktion ausgeführt, gut gemacht.\
89 | Wie du siehst, sind die Links für diese\
90 | Situation immer noch aktiv. Das bedeutet,\
91 | dass du sie noch einmal anklicken und damit\
92 | die Aktion ausführen kannst.
"
93 | }
94 | }
95 | ),
96 | links: new undum.SimpleSituation(
97 | "
Veränderlicher Inhalt
\
98 |
Vor jedem neuen Textabschnitt fügt Undum eine\
99 | kleine Linie am Rand ein. Damit kann der Spieler auf einen Blick\
100 | erfassen, was durch den letzten Klick neu ausgegeben wurde.\
101 | Das ist besonders auf mobilen Geräten mit kleinen Bildschirmen\
102 | nützlich, oder wenn eine Menge Text auf einmal\
103 | dazugekommen ist. Die Anzeige wird außerdem so gescrollt,\
104 | dass der Anfang des neuen Abschnitts nah am oberen Fensterrand\
105 | ist.\
106 | Dies soll einen natürlichen Lesefluss ermöglichen.
\
107 | \
108 |
Wenn du genau hingeschaut hast, ist dir bestimmt aufgefallen,\
109 | dass Teile des Textes verschwunden sind, als in neue Situationen\
110 | gewechselt wurde. Das ist kein Bug! Es ist eines der Ziele von Undum,\
111 | dass Entwickler ihr Spiel so gestalten können, dass das\
112 | Transkript des Spielablaufs sich wie eine durchgehende, kohärente\
113 | Erzählung liest. Allerdings benötigt man oft Textschnipsel, die\
114 | nur dazu da sind, dem Spieler Auswahlmöglichkeiten anzuzeigen.\
115 | Undum stellt dafür eine besondere CSS-Klasse bereit, die man in\
116 | den eigenen HTML-Inhalt einbaut (wie gesagt, sämtlicher Inhalt\
117 | besteht ja einfach aus HTML). Diese Klasse heißt transient\
118 | ('vorübergehend') und man kann sie auf Absätze, divs, oder\
119 | spans (so wie hier) anwenden.
\
120 | \
121 |
Vielleicht ist dir auch aufgefallen, dass beim Wechsel in eine neue\
122 | Situation alle Links in der vorherigen Situation sich in normalen Text verwandeln.\
123 | Das verhindert, dass der Spieler zurückgeht und eine andere Option\
124 | ausprobiert, nachdem er sich bereits für eine entschieden hat.\
125 | In anderen Hypertext-Systemen wird das oft so gehandhabt, dass\
126 | der Inhalt früherer Seiten komplett gelöscht wird.\
127 | Allerdings kann man in solchen Systemen dann nicht mehr\
128 | zurückblättern, um die gesamte Geschichte zu lesen.
\
129 | \
130 |
Gleich erfährst du mehr über diese Links\
131 | und wie du ihre Wirkungsweise ändern kannst.
"
132 | ),
133 | sticky: new undum.SimpleSituation(
134 | "
Links
\
135 |
Es gibt drei Arten von Links in Undum. Zwei kennen wir schon:\
136 | Links, mit denen man in eine neue Situation wechselt, und Links,\
137 | die eine Aktion ausführen. Wenn du einen Link in deinen\
138 | Ausgabetext einbaust, dann verarbeitet Undum den Link und\
139 | sorgt für die richtige Verbindung. Wenn du einen Link machst,\
140 | in dem das HTML-Attribut href nur einen Namen\
141 | enthält (z.B. 'ballsaal'), dann schickt der Link die Spielfigur\
142 | zu der Situation, die diesen Namen hat. Links mit zwei Teilen\
143 | ('ballsaal/betrachte-gemaelde', z.B.) schicken die Spielfigur in\
144 | die so benannte Situation und führen dann\
145 | die genannte Aktion aus ('betrachte-gemaelde').\
146 | Um innerhalb der momentanen Situation eine Aktion\
147 | ausführen zu lassen, kannst du den Situationsnamen durch\
148 | einen Punkt ersetzen (z.B. so: './betrachte-gemaelde').\
149 | In allen Fällen gilt: Wenn die Spielfigur schon in der Situation\
150 | ist, dann wird deren enter-Methode nicht noch einmal aufgerufen.
\
151 | \
152 |

\
153 |
Die dritte Art von Link ist ein allgemeiner Hyperlink. Wenn dein\
154 | Link nicht aus nur einem Element bzw. zwei Elementen besteht wie\
155 | oben, dann vermutet Undum, dass es sich um einen normalen Hyperlink\
156 | handelt, so wie bei diesem.\
157 | Wenn du einen Link hast, der wie ein Undum-Link aussieht,\
158 | kannst du Undum trotzdem zwingen, ihn nicht als Aktions- oder\
159 | Situations-Link zu behandeln, indem du dem HTML a-Tag\
160 | die CSS-Klasse raw hinzufügst.\
161 | Denjenigen Links, die nicht die raw-Klasse haben, und die aber als\
162 | Nicht-Undum-Links angesehen werden (wie der oben), wird raw\
163 | hinzugefügt, bevor sie angezeigt werden. Das erlaubt dir, externe\
164 | Links in einem anderen Stil darzustellen (siehe oben).
\
165 | \
166 |
In der letzten Situation wurde erwähnt, dass man verhindern\
167 | kann, dass Links bei einem Situationswechsel in normalen Text verwandelt\
168 | werden. Das geht mit einer weiteren CSS-Klasse: sticky ('klebrig').\
169 | Wenn du diese Situation verlässt, wirst du sehen,\
170 | dass der externe Link aktiv bleibt. Dadurch ist es möglich, Optionen\
171 | anzubieten, die während der gesamten Geschichte gültig bleiben, z.B.\
172 | einen Zauberspruch, mit dem die Spielfigur sich nach Hause teleportieren kann.
"
173 | ),
174 | oneshot: new undum.SimpleSituation(
175 | "
Es gibt noch folgende Variante für die Link-Darstellung:\
176 | Wenn man einem Link die CSS-Klasse once ('einmal') verpasst,\
177 | dann verschwindet der Link, nachdem er angeklickt wurde. Das kannst\
178 | du (wie bei diesem Link)\
179 | für Aktionen benutzen, die nur einmal ausführbar sein\
180 | sollen. Bei Situations-Links ist once witzlos, denn die werden ja\
181 | sowieso in normalen Text verwandelt, sobald sie angeklickt wurden\
182 | (außer natürlich, wenn sie als sticky\
183 | deklariert sind).
Die once-Links eignen sich z.B.\
184 | für eine Aktion wie das genaue Untersuchen eines Gegenstands.\
185 | Es sähe nicht schön aus, wenn so eine Beschreibung eines\
186 | Gegenstands mehrfach wiederholt würde - ein\
187 | once-Link ist da benutzerfreundlicher.
\
188 |
Wenn mehr als ein Link zu derselben Aktion führt,\
189 | dann werden alle diese Links deaktiviert, also brauchst du\
190 | dir keine Sorgen zu machen, dass der Spieler die Aktion\
191 | noch einmal auf anderem Wege ausführen könnte.
\
192 |
Nachdem du oben auf den Link geklickt hast, können wir\
193 | weitermachen.
",
194 | {
195 | actions: {
196 | "one-time-action": "
Wie gesagt, einmalige Aktionen\
197 | werden oft dazu genutzt, Dinge detaillierter\
198 | zu beschreiben; man möchte dabei nicht,\
199 | dass ein und derselbe Beschreibungstext\
200 | über und über wiederholt wird.
"
201 | }
202 | }
203 | ),
204 | qualities: new undum.SimpleSituation(
205 | "
Eigenschaften
\
206 |
Genug von Situationen! Lass uns über die Spielfigur sprechen.\
207 | Die Spielfigur wird durch ihre qualities ('Eigenschaften')\
208 | bestimmt. Das sind Zahlenwerte, die für alles mögliche\
209 | stehen können, z.B. Fähigkeiten oder Ressourcen,\
210 | die die Figur besitzt. Die Eigenschaften werden in dem Feld\
211 | rechts neben dem Haupttext angezeigt.
\
212 | \
213 |
Die Eigenschaften dort sind bei Spielbeginn zugewiesen worden. Wenn\
214 | du gleich zur nächsten Situation gehst,\
215 | schau genau auf das Feld. Wie du siehst, bekommst du\
216 | einen Stärke-Bonus. Dieser Vorgang wird animiert und hervorgehoben,\
217 | damit der Spieler darauf aufmerksam wird. Wenn du möchtest,\
218 | kannst du dir auch noch mit dieser Aktion\
219 | einen Gewandtheits-Bonus holen - so oft wie du willst.
",
220 | {
221 | actions: {
222 | "skill-boost": function(character, system, action) {
223 | system.setQuality("skill", character.qualities.skill+1);
224 | }
225 | },
226 | exit: function(character, system, to) {
227 | system.setQuality("stamina", character.qualities.stamina+1);
228 | }
229 | }
230 | ),
231 | // wenn eine Situations-Kennung einen Bindestrich enthaelt wie die Folgende,
232 | // dann sollte sie in Anfuehrungsstrichen stehen
233 | "quality-types": new undum.SimpleSituation(
234 | "
Nicht alle Eigenschaften werden im Spielfiguren-Feld als\
235 | Zahlen aufgelistet. Intern sind sie zwar alle Zahlen, aber sie\
236 | können verschieden angezeigt werden. 'Glück' z.B.\
237 | wird in Worten dargestellt (die auf der Skala aus dem\
238 | FUDGE-Rollenspielsystem beruhen), und 'Novize' hat nur\
239 | ein Häkchen.
\
240 | \
241 |
Du kannst sehen, wie sich das Glück verändert, wenn\
242 | du mal diese glücks-erhöhende\
243 | und diese glücks-verringernde\
244 | Aktion probierst. Wenn die Wort-Skala ausgeschöpft ist, wird\
245 | ein zahlenmäßer Bonus bzw. Malus angehängt.\
246 | Undum bringt eine Reihe verschiedener Anzeigetypen mit, und man\
247 | kann auch einfach eigene hinzufügen.
\
248 | \
249 |
Wenn du diese Situation verlässt,\
250 | wird 'Novize' auf Null gesetzt. Im Spielfiguren-Feld kannst du gleich sehen,\
251 | dass 'Novize' verschwindet, und wenn die letzte Eigenschaft aus einer\
252 | Gruppe entfernt wird ('Novize' ist in der Gruppe 'Fortschritt'), dann\
253 | verschwindet die Gruppen-Überschrift ebenfalls. Man kann selbst\
254 | festlegen, zu welcher Gruppe jede Eigenschaft gehört, und in\
255 | welcher Reihenfolge sie aufgelistet werden sollen.\
256 |
",
257 | {
258 | actions: {
259 | "luck-boost": function(character, system, action) {
260 | system.setQuality("luck", character.qualities.luck+1);
261 | },
262 | "luck-reduce": function(character, system, action) {
263 | system.setQuality("luck", character.qualities.luck-1);
264 | }
265 | },
266 | exit: function(character, system, to) {
267 | system.setQuality("novice", 0);
268 | }
269 | }
270 | ),
271 | "character-text": new undum.SimpleSituation(
272 | "
Spielfiguren-Text
\
273 |
Über der Liste mit den Eigenschaften steht ein kurzer Text,\
274 | den wir den Spielfigur-Text ('character-text') nennen wollen. Dieser kann\
275 | dazu genutzt werden, eine kurze Beschreibung der Spielfigur zu geben.\
276 | Der Text kann durch eine Aktion oder beim Wechsel zwischen Situationen\
277 | geändert werden. Es handelt sich, wie auch sonst überall in\
278 | Undum, um normales HTML. Man kann auch hier Undum-Links einbauen,\
279 | z.B. Aktionen, die die Spielfigur zu jedem Zeitpunkt ausführen kann.\
280 |
\
281 |
Lass uns zur\
282 | nächsten Situation gehen.\
283 | Währenddessen ändere ich den Spielfiguren-Text. Er wird dabei\
284 | hervorgehoben, so wie wenn man eine Eigenschaft ändert.
",
285 | {
286 | exit: function(character, system, to) {
287 | system.setCharacterText(
288 | "
Wir nähern uns dem Ende des Wegs.
"
289 | );
290 | }
291 | }
292 | ),
293 | progress: new undum.SimpleSituation(
294 | "
Fortschritt anzeigen
\
295 |
Manchmal möchte man, dass es als wichtiges Ereignis\
296 | wahrgenommen wird, wenn sich eine Eigenschaft ändert. Deshalb\
297 | kann man die Änderung auch animiert darstellen. Wenn du\
298 | deine Stärke steigerst,\
299 | wirst du die Änderung wie üblich im Spielfiguren-Feld sehen,\
300 | aber zusätzlich erscheint unten eine animierte Fortschrittsanzeige.
",
301 | {
302 | actions: {
303 | // Hier gehen wir einen indirekten Weg - der Link fuehrt eine Aktion aus,
304 | // die ihrerseits doLink benutzt, um die Situation direkt zu aendern.
305 | // Das ist nicht die empfohlene Methode (man haette die Situation
306 | // einfach im Link aendern koennen), aber sie zeigt, wie man doLink verwendet.
307 | "boost-stamina-action": function(character, system, action) {
308 | system.doLink("boost-stamina");
309 | }
310 | },
311 | exit: function(character, system, to) {
312 | system.animateQuality(
313 | 'stamina', character.qualities.stamina+1
314 | );
315 | }
316 | }
317 | ),
318 | "boost-stamina": new undum.SimpleSituation(
319 | "
Die Fortschrittsanzeige ist auch nützlich, wenn im\
320 | Spielfigur-Feld der Wert einer Eigenschaft als ganze Zahl\
321 | angezeigt wird, und eine Aktion nur eine Nachkomma-Stelle der\
322 | Eigenschaft ändert. Wenn eine Eigenschaft z.B. die\
323 | Erfahrungsstufe der Spielfigur anzeigt und die Figur dann einige\
324 | Erfahrungspunkte hinzugewinnt, dann kann man die\
325 | Fortschrittsanzeige benutzen, um anzuzeigen, wie nah die\
326 | Figur an der nächsthöheren Stufe ist.
\
327 | \
328 |

\
329 |
Nach ein paar Sekunden verschwindet die Fortschrittsanzeige,\
330 | damit der Leser nicht zu sehr vom Text abgelenkt wird. Undum ist\
331 | nicht unbedingt dafür gemacht, z.B. ein Strategiespiel\
332 | darzustellen, bei dem man ständig viele Statistiken im Blick haben\
333 | muss. Wenn eine Eigenschaftsänderung ein permanenter Teil\
334 | der aufgezeichneten Geschichte werden soll, dann sollte sie im\
335 | Text auftauchen.
\
336 | \
337 |
Nun sind wir bald am Ende des Weges angelangt. Bisher\
338 | haben wir uns jedoch nur linear durch dieses Tutorium fortbewegt - \
339 | von einer Situation zur nächsten, ganz ohne Entscheidungen.\
340 | Undum ist aber natürlich darauf ausgelegt, Erzählungen zu\
341 | schreiben, die sich verzweigen und wieder zusammenfließen.
\
342 | \
343 |
Hier ein winziges Beispiel zur\
344 | Veranschaulichung - wähle einen der Zweige:
\
345 |
\
349 |
Der Optionen-Block oben ist eine normale HTML\
350 | 'unordered list' (ul-Tag) mit der speziellen\
351 | options-Klasse. Klick auf eine der Zeilen (die gesamte Breite\
352 | ist anklickbar), um die entsprechende Option zu wählen.
"
353 | ),
354 | one: new undum.SimpleSituation(
355 | "
Option Eins
\
356 |
Du hast Option Eins gewählt, was wahrscheinlich auch besser so ist, denn\
357 | Option Zwei ist in schlecht gereimtem Koptisch verfasst.\
358 |
\
359 |
Von hier ist es nur ein kleiner Schritt zum\
360 | Rest des Tutoriums.
"
361 | ),
362 | "two": new undum.SimpleSituation(
363 | "
Option Zwei
\
364 |
Du hast Option Zwei gewählt - die gefällt mir auch am besten.\
365 | Die Photos, die bei Option Eins auftauchen, sind einfach zu verstörend.\
366 | Fingernägel sollte man nicht auf so eine Art verbiegen...
\
367 |
Von hier ist es nur ein kleiner Schritt zum\
368 | Rest des Tutoriums.
"
369 | ),
370 | // An dieser Stelle ziehen wir den gewuenschten Text wieder aus der HTML-Datei.
371 | "saving": new undum.Situation({
372 | enter: function(character, system, from) {
373 | system.write($("#s_saving").html());
374 | }
375 | }),
376 | "last": new undum.SimpleSituation(
377 | "
Wie geht es nun weiter
\
378 |
So, das war's mit unserem Rundgang durch Undum. Diese Situation\
379 | ist das Ende, denn sie stellt keine weiteren Links bereit. Der 'Ende'-Hinweis unten ist\
380 | einfach Teil des ausgegebenen HTMLs in dieser Situation, er ist nicht speziell\
381 | in Undum eingebaut.
\
382 | \
383 |
Deine Figur hat jetzt eine Eigenschaft hinzugewonnen - Inspiration!\
384 | Zeit für dich, die Spieldatei zu öffnen und deine eigene Geschichte\
385 | zu schreiben!
\
386 |
Ende
",
387 | {
388 | enter: function(character, system, from) {
389 | system.setQuality("inspiration", 1);
390 | system.setCharacterText(
391 | "
Du fühlst dich inspiriert - versuch's doch auch einmal!
"
392 | );
393 | }
394 | }
395 | )
396 | };
397 |
398 | // ---------------------------------------------------------------------------
399 | /* Die Kennung der Start-Situation. */
400 | undum.game.start = "start";
401 |
402 | // ---------------------------------------------------------------------------
403 | /* Hier definieren wir die Eigenschaften (qualities) unserer Hauptfigur.
404 | * Wir muessen sie nicht erschoepfend auflisten, aber wenn eine hier nicht
405 | * auftaucht, dann wird sie nicht in der "Spielfigur"-Leiste der Benutzeroberflaeche angezeigt. */
406 | undum.game.qualities = {
407 | skill: new undum.IntegerQuality(
408 | "Gewandtheit", {priority:"0001", group:'stats'}
409 | ),
410 | stamina: new undum.NumericQuality(
411 | "
Stärke", {priority:"0002", group:'stats'}
412 | ),
413 | luck: new undum.FudgeAdjectivesQuality( // Fudge bezieht sich auf das FUDGE-Rollenspielsystem
414 | "
Glück",
415 | {priority:"0003", group:'stats'}
416 | ),
417 | inspiration: new undum.NonZeroIntegerQuality(
418 | "Inspiration", {priority:"0001", group:'progress'}
419 | ),
420 | novice: new undum.OnOffQuality(
421 | "Novize", {priority:"0002", group:'progress', onDisplay:"✓"}
422 | )
423 | };
424 |
425 | // ---------------------------------------------------------------------------
426 | /* Die Eigenschaften werden in der "Spielfigur"-Leiste in Gruppen angezeigt.
427 | * Hier werden die Gruppen festgelegt und ihre Reihenfolge und ihre Ueberschriften
428 | * bestimmt (wobei null bedeutet, dass die Gruppe keine Ueberschrift hat).
429 | * Eigenschaftsdefinitionen ohne Gruppe erscheinen am Ende.
430 | * Wenn eine Eigenschaftsdefinition einer nicht-existenten Gruppe
431 | * zugeordnet wird, ist das ein Fehler. */
432 | undum.game.qualityGroups = {
433 | stats: new undum.QualityGroup(null, {priority:"0001"}),
434 | progress: new undum.QualityGroup('Fortschritt', {priority:"0002"})
435 | };
436 |
437 | // ---------------------------------------------------------------------------
438 | /* Diese Funktion wird vor dem Start des Spiels ausgefuehrt. Normalerweise
439 | * konfiguriert man hiermit die Eigenschaften der Hauptfigur bei Spielbeginn. */
440 | undum.game.init = function(character, system) {
441 | character.qualities.skill = 12;
442 | character.qualities.stamina = 12;
443 | character.qualities.luck = 0;
444 | character.qualities.novice = 1;
445 | character.qualities.inspiration = 0;
446 | system.setCharacterText("
Du bist am Beginn einer aufregenden Reise.
");
447 | };
448 |
--------------------------------------------------------------------------------
/docs/src/API.md:
--------------------------------------------------------------------------------
1 | # Javascript API
2 |
3 | # `Character`
4 |
5 | The character is created for you, but is passed into most of the
6 | functions that you define. It consists of an object with no methods
7 | and two properties:
8 |
9 | #### `qualities`
10 |
11 | The qualities object maps quality identifiers to their current
12 | value. Your code finds the current value associated with a quality by
13 | reading from this object, for example:
14 |
15 | var gold = character.qualities.gold;
16 |
17 | To set a quality, you have two choices. If you know the quality you
18 | want to set will not appear in the user interface, then you can set it
19 | directly:
20 |
21 | character.qualities.gold += 1;
22 |
23 | If it does appear on-screen, then this approach will mean that the
24 | character panel doesn't update, and the screen will be out of sync
25 | with the actual value. Instead it is better to use the `System` method
26 | `setQuality`, which also updates the UI:
27 |
28 | system.setQuality('gold', character.qualities.gold+1);
29 |
30 | It is fine to use `setQuality` if the quality isn't visible, making
31 | this the preferred option for all quality modifications.
32 |
33 | #### `sandbox`
34 |
35 | Not every bit of data you want to associate with a character fits
36 | nicely into a quality. The sandbox is a general storage space for any
37 | further data you want to store in the course of your game, for
38 | example:
39 |
40 | character.sandbox.roomsSearched.push('bathroom');
41 |
42 | Sandbox data is never visible to the user, so you can use any data
43 | structures you like here, to any depth.
44 |
45 | # `System`
46 |
47 | The system represents the interface between your code and the
48 | user-interface. You don't create your own `System` object, it is
49 | passed into your code.
50 |
51 | #### `clearContent(elementSelector)`
52 |
53 | *Since version 2*
54 |
55 | Removes all content from the page, clearing the main content area.
56 |
57 | Although Undum is designed to keep the flow of the narrative on one
58 | page, sometimes you do need to start a new page, and this allows you
59 | to do so.
60 |
61 | The `elementSelector` is options. If you give it, then the DOM element
62 | matching the selector is cleared, rather than the whole document.
63 |
64 | #### `write(content, elementSelector)`
65 |
66 | Writes new content to the main flow of the story. The content you pass
67 | in must be either valid DOM elements already, or else be a string
68 | containing text in Display Content format.
69 |
70 | The `elementSelector` is optional. If you provide it, then the new
71 | content will be added after the DOM element in the document that
72 | matches the selector. This allows you to do out-of-order addition of
73 | content. Simply add a paragraph with an id in your game, then later
74 | you can give this id as a selector to write, and the new content will
75 | be inserted immediately following that paragraph, regardless of how
76 | much extra content has been added since that point. If no selector is
77 | given then `#content` is used, i.e. the content is added at the end of
78 | the document. The `writeBefore` method inserts content at the start of
79 | the document, or before a selector.
80 |
81 | The story will scroll to the start of the insertion point. If you do
82 | not wish to animate this scrolling, but just jump right there, you can
83 | switch off jQuery's animation system by adding `jQuery.fx.off=true` to
84 | your initialization code. This is particularly useful when debugging.
85 |
86 | #### `writeHeading(content, elementSelector)`
87 |
88 | Writes new content into the story and formats it as a heading. This
89 | method work exactly as `write`, but wraps the content you provide into
90 | a `h1` html tag.
91 |
92 | #### `writeBefore(content, elementSelector)`
93 |
94 | Writes content into the story. This method is identical to `write`,
95 | above, except that the content is written at the start of the story,
96 | or if a selector is given, inserted before the matching element. On
97 | browsers that support it, the story will be scrolled to the insertion
98 | point.
99 |
100 | #### `writeInto(content, elementSelector)`
101 |
102 | Writes content into the element matched by `elementSelector`. When
103 | used without specifying a selector, this method is identical to
104 | `write`. When a selector is supplied, the content is written as an
105 | additional child node of the matched element, instead of as a new
106 | node just after that element, as is the case with `write`.
107 |
108 | #### `replaceWith(content, elementSelector)`
109 |
110 | Replaces an element with `content`. If `elementSelector` isn't
111 | supplied, this will replace the entire situation with the given
112 | `content`. If it is, the matched element will be replaced, including
113 | the matched set of tags; `content` slides in place of the matched
114 | element in the DOM.
115 |
116 | #### `writeChoices(listOfSituationIds)`
117 |
118 | *Since version 2*
119 |
120 | Creates a standard block of choices, one for each of the given
121 | situation ids. The text used in the links will be whatever is returned
122 | by the situation's `optionText` method. In addition, if the
123 | situation's `canChoose` method returns `false`, then the option will
124 | be displayed, but will not be clickable.
125 |
126 | #### `getSituationIdChoices(listOfIdsOrTags, minChoices, maxChoices)`
127 |
128 | *Since version 2*
129 |
130 | This function is a complex and powerful way of compiling implicit
131 | situation choices. You give it a list of situation ids and situation
132 | tags. Tags should be prefixed with a hash # to differentiate them from
133 | situation ids. The function then considers all matching situations in
134 | descending priority order, calling their canView functions and
135 | filtering out any that should not be shown, given the current
136 | state. Without additional parameters the function returns a list of
137 | the situation ids at the highest level of priority that has any valid
138 | results. So, for example, if a tag #places matches three situations,
139 | one with priority 2, and two with priority 3, and all of them can be
140 | viewed in the current context, then only the two with priority 3 will
141 | be returned. This allows you to have high-priority situations that
142 | trump any lower situations when they are valid, such as situations
143 | that force the player to go to one destination if the player is out of
144 | money, for example.
145 |
146 | If a `minChoices` value is given, then the function will attempt to
147 | return at least that many results. If not enough results are available
148 | at the highest priority, then lower priorities will be considered in
149 | turn, until enough situations are found. In the example above, if we
150 | had a minChoices of three, then all three situations would be
151 | returned, even though they have different priorities. If you need to
152 | return all valid situations, regardless of their priorities, set
153 | minChoices to a large number, such as `Number.MAX_VALUE`, and leave
154 | maxChoices undefined.
155 |
156 | If a `maxChoices` value is given, then the function will not return any
157 | more than the given number of results. If there are more than this
158 | number of results possible, then the highest priority resuls will be
159 | guaranteed to be returned, but the lowest priority group will have to
160 | fight it out for the remaining places. In this case, a random sample
161 | is chosen, taking into account the frequency of each situation. So a
162 | situation with a frequency of 100 will be chosen 100 times more often
163 | than a situation with a frequency of 1, if there is one space
164 | available. Often these frequencies have to be taken as a guideline,
165 | and the actual probabilities will only be approximate. Consider three
166 | situations with frequencies of 1, 1, 100, competing for two
167 | spaces. The 100-frequency situation will be chosen almost every time,
168 | but for the other space, one of the 1-frequency situations must be
169 | chosen. So the actual probabilities will be roughly 50%, 50%,
170 | 100%. When selecting more than one result, frequencies can only be a
171 | guide.
172 |
173 | Before this function returns its result, it sorts the situations in
174 | increasing order of their `displayOrder` properties.
175 |
176 |
177 | #### `doLink(URL)`
178 |
179 | Carries out the action associated with the given URL, as if it had
180 | been the `href` of a HTML link that the user clicked. This allows you
181 | to procedurally change situation and carry out actions from your code.
182 |
183 | #### `rnd`
184 |
185 | This holds a general purpose random number generator. It is an object
186 | derived from the `Random` prototype, so see `Random` below for details
187 | on its API.
188 |
189 | #### `time`
190 |
191 | This is a numeric value holding the current time, in seconds, since
192 | the player began playing the game. This value is correctly propagated
193 | across saves, so it is the only way you should track timing. In
194 | particular you should never call `new Date()` and use that value to
195 | determine the outcome of any event. You can use the current date to
196 | display the current date, for example, but not to control what actions
197 | or situations are available. See the section on Loading and Saving for
198 | more details of why this is important.
199 |
200 | #### `setQuality(qualityId, newValue)`
201 |
202 | Sets the character's given quality to the given value. This function
203 | also updates the character panel, animating the change in value if
204 | that is necessary. Do not directly set quality values in the
205 | character, because the user-interface will not detect and reflect
206 | those changes.
207 |
208 | #### `animateQuality(qualityId, newValue, options)`
209 |
210 | Like `setQuality`, this function changes the current value of the
211 | given quality. In addition, however, it displays a progress bar that
212 | shows to the user how the value has changed. The `options` parameter
213 | should be an object containing options for how the bar should
214 | display. The available options are:
215 |
216 | - `from`: The proportion along the progress bar where the animation
217 | starts. Defaults to 0, valid range is 0-1.
218 |
219 | - `to`: The proportion along the progress bar where the animation
220 | ends. Defaults to 1, valid range is 0-1.
221 |
222 | - `showValue`: If `true` (the default) then the new value of the
223 | quality is displayed above the progress bar.
224 |
225 | - `displayValue`: If this is given, and `showValue` is `true`, then
226 | the given value is used above the progress bar. If this isn't
227 | given, and `showValue` is `true`, then the display value will be
228 | calculated from the `QualityDefinition`, as normal. This option is
229 | useful for qualities that don't have a definition, because they
230 | don't normally appear in the UI.
231 |
232 | - `title`: The title of the progress bar. If this is not given, then
233 | the title of the quality is used. As for `displayValue` this is
234 | primarily used when the progress bar doesn't have a
235 | `QualityDefinition`, and therefore doesn't have a title.
236 |
237 | - `leftLabel`, `rightLabel`: Underneath the progress bar you can place
238 | two labels at the left and right extent of the track. These can
239 | help to give scale to the bar. So if the bar signifies going from
240 | 10.2 to 10.5, you might label the left and right extents with "10"
241 | and "11" respectively and have the `from` and `to` value be 0.2 and
242 | 0.5 respectively. If these are not given, then the labels will be
243 | omitted.
244 |
245 | #### `setCharacterText(content)`
246 |
247 | Sets the block of character text that appears in the character
248 | panel. As for the `write` method, this text should be either valid DOM
249 | elements, or a string meeting the Display Content requirements.
250 |
251 | #### `clearLinks(URL)`
252 |
253 | Call this function with an Undum link URL (e.g. `ballroom`, or
254 | `ballroom/open-cabinet`). It will remove all occurrences of that link
255 | from the page. This is equivalent to what happens when you change
256 | situation, or when you click a link marked with the `once` CSS
257 | class. It allows you to control what options are available
258 | dynamically, from your code.
259 |
260 | ## `Random`
261 |
262 | The `Random` object provides a set of tools for simple random number
263 | generation, in a way that is guaranteed to work with the Loading and
264 | Saving functionality in Undum. An instance of `Random` is provided in
265 | the `rnd` property of the `System` object, so you will never need to
266 | create your own. It has the following methods:
267 |
268 | #### `random()`
269 |
270 | Generates a random number between 0 and 1, where 0 is inclusive, and 1
271 | is exclusive. You can use this to check against known probabilities,
272 | such as:
273 |
274 | if (system.rnd.random() > 0.5) {
275 | ...
276 | }
277 |
278 | To check for a 50/50 chance.
279 |
280 | #### `randomInt(min, max)`
281 |
282 | Return a random number between the given two values, where both values
283 | are inclusive. So `randomInt(2,3)` generates either 2 or 3.
284 |
285 | #### `dice(n, dx, plus)`
286 |
287 | Rolls _n_ dice with _dx_ sides and adds _plus_ to the result. This
288 | allows you to easily get results for rolls from regular RPG-style
289 | games, such as 3d6+2. The `plus` parameter may be negative or
290 | positive.
291 |
292 | #### `aveDice(n, plus)`
293 |
294 | Rolls _n_ averaging dice, and adds _plus_ to the result. Averaging dice
295 | are a special type of d6 with sides marked [2,3,3,4,4,5]. They represent
296 | the fact that most people are fairly average, and results should not lie
297 | at the extremes.
298 |
299 | #### `diceString(definition)`
300 |
301 | Rolls dice according to the given definition string. The string should
302 | be of the form xdy+z, where the x component and z component are
303 | optional. This rolls x dice of with y sides, and adds z to the result,
304 | the z component can also be negative: xdy-z. The y component can be
305 | either a number of sides, or can be the special values 'F', for a
306 | fudge die (with 3 sides, +,0,-), '%' for a 100 sided die, or 'A' for
307 | an averaging die (with sides 2,3,3,4,4,5).
308 |
309 | # `Situation`
310 |
311 | The `Situation` object is the prototype of all the situations in your
312 | game. It can be used directly, or through its more common derived
313 | type, `SimpleSituation`. The base `Situation` gives you maximum
314 | flexibility, but `SimpleSituation` provides more functionality and can
315 | produce terser code.
316 |
317 | #### `new Situation(options)`
318 |
319 | Creates a new situation. The options array can specify your
320 | implementation for any or all of the following methods of this class:
321 |
322 | - `enter`
323 | - `exit`
324 | - `act`
325 | - `optionText`
326 | - `canView`
327 | - `canChoose`
328 |
329 | (see below for explanations of those methods). This allows
330 | you to easily create situations that override certain behaviors with
331 | code such as:
332 |
333 | Situation({
334 | enter: function(character, system, from) {
335 | ... your implementation ...
336 | }
337 | });
338 |
339 | without having to subclass `Situation` to provide your own
340 | implementations.
341 |
342 | In addition the following options can be passed in.
343 |
344 | - `tags`: A list of tags with which to label this situation. These are
345 | primarily used to generate implicit lists of choices with
346 | `System.getSituationIdChoices`. Tags are arbitrary strings. You can
347 | pass a list of strings, or a single string. If you pass a single
348 | string, it will be split at spaces, commas and tabs to form a list of
349 | tags. For this reason, tags normally do not contain spaces, commas or
350 | tabs (though if you pass in a list, and don't expect Undum to do the
351 | splitting for you, you can include any characters you like in a tag).
352 |
353 | - `optionText` (as a string): If given as a string, rather than a
354 | function, this text will be returned whenever `optionText(...)` is
355 | called.
356 |
357 | - `displayOrder`: A numeric value, defaults to 1. When displaying
358 | lists of implicitly generated choices, the options be displayed in
359 | increasing value of this parameter.
360 |
361 | - `priority`: Can be any number, defaults to 1. When generating lists
362 | of choices implicitly, situations are considered in descending
363 | priority order. If higher priority situations can be displayed, lower
364 | priority situations will be hidden. See `System.getSituationIdChoices`
365 | for details of the algorithm.
366 |
367 | - `frequency`: Any number, defaults to 1. When generating lists of
368 | implicit choices, where there are more choices available that slots to
369 | display them, situations will be chosen randomly, with a probability
370 | based on this value. See `System.getSituationIdChoices` for details of
371 | the algorithm.
372 |
373 | #### `enter(character, system, from)`
374 |
375 | This is called when Undum enters a situation. The `character` and
376 | `system` are instances of `Character` and `System` as described
377 | above. The `from` parameter is a string containing the situation
378 | identifier for the situation that we're arriving from.
379 |
380 | This method is the most commonly overridden. It is commonly used to
381 | describe the current situation (by sending content to
382 | `system.write()`) and to update the character (by calling
383 | `system.setQuality()` or by changing data in the character's `sandbox`
384 | object)..
385 |
386 | #### `exit(character, system, to)`
387 |
388 | This method takes the same `character` and `system` parameters as
389 | `enter`. Its third parameter, `to`, is a string containing the
390 | identifier of the situation we're exiting to.
391 |
392 | #### `act(character, system, action)`
393 |
394 | This method again takes the same `character` and `system` parameters
395 | as before. Its third parameter is a string containing the action
396 | identifier corresponding to the link the player clicked. It is common
397 | to use an `if` statement or a `switch` to query this action identifier
398 | and decide what to do accordingly. For situations in which many
399 | different actions are possible, consider using the `SimpleSituation`
400 | prototype, which provides this switching behavior for you.
401 |
402 | #### `optionText(character, system, hostSituation)`
403 |
404 | This method is called by `System.writeChoices` to generate a label for
405 | links to this situation. The `hostSituation` is the situation that has
406 | asked for the choices to be displayed.
407 |
408 | #### `canView(character, system, hostSituation)`
409 |
410 | This method is called by `System.getSituationIdChoices` to determine
411 | whether this situation can be part of a list of choices in the current
412 | game state. It should return true or false.
413 |
414 | #### `canChoose(character, system, hostSituation)`
415 |
416 | This method is called by `System.writeChoices` to determine whether a
417 | link should be added to allow the user to enter this situation. If
418 | not, the choice will still appear, but will not be clickable.
419 |
420 |
421 |
422 | ## SimpleSituation
423 |
424 | This prototype builds on the basic `Situation`, providing tools to
425 | make it easy to output content in the `enter` method, and to switch
426 | between different functions depending on the action identifier passed
427 | into the `act` method. The `exit` method of `SimpleSituation` is
428 | exactly as for the base type `Situation`.
429 |
430 | #### `new SimpleSituation(content, options)`
431 |
432 | Creates a new simple situation that will display the given content
433 | when its `enter` method is called. The given options dictionary
434 | provides further control of the behavior of this type. Valid options
435 | are:
436 |
437 | - `enter`: Providing an enter function in the `options` parameter
438 | allows you to add additional behavior to the enter method. Your
439 | custom function will be called *in addition to* and *after* the
440 | default content is written to the screen. You cannot override
441 | `SimpleSituation`'s `enter` method by providing this function. To
442 | override the method, you would have to create a derived type. If
443 | you provide an `enter` function, it should have the same form as
444 | `Situation.enter`.
445 |
446 | - `act`: Pass in a function to add additional behavior to the act
447 | method. As for `enter`, your method is called *in addition to* and
448 | *after* the built-in functionality.
449 |
450 | - `exit`: Because `SimpleSituation` has no default behavior for
451 | `exit`, any function you pass in here will be the only exit
452 | behavior for the object you are creating.
453 |
454 | - `heading`: The `content` that you specify will be written out
455 | verbatim. You can include headings in this content. Often it is
456 | more convenient to pass in just the text in the `content`
457 | parameter. In that case you may define this `heading` parameter to
458 | display a heading before the text. Unlike `content`, this doesn't
459 | need to conform to the Display Content requirements.
460 |
461 | - `actions`: This should be an object that maps action identifiers to
462 | responses. A response should be either some Display Content to
463 | write to the screen, or a function that will process that
464 | request. These functions should have the same signature as the
465 | `Situation.act` method. Each function will only be called if the
466 | situation receives a call to `act` with its corresponding
467 | identifier. This allows you to simply define functions that only
468 | get called when particular actions happen.
469 |
470 | - `choices`: An optional list of tags and situation-ids, with tags
471 | prefixed by a has symbol to distinguish them from situation ids. If
472 | given, this will cause the SimpleSituation to output an implicit block
473 | of choices after the content.
474 |
475 | - `minChoices`: If you have given a `choices` definition, you can set
476 | this to an integer value to change the number of choices that will
477 | appear. See `System.getSituationIdChoices` for more information on
478 | how this affects the output.
479 |
480 | - `maxChoices`: If you have given a `choices` definition, you can set
481 | this to an integer value to change the number of choices that will
482 | appear. See `System.getSituationIdChoices` for more information on
483 | how this affects the output.
484 |
485 | An example `SimpleSituation` definition might be:
486 |
487 | new SimpleSituation(
488 | "
...content...
",
489 | {
490 | heading: "Title",
491 | actions: {
492 | listen: function(character, system, action) {
493 | if (character.qualities.hearing > 5) {
494 | system.write("
You hear a tinkling inside.
");
495 | } else {
496 | system.write("
You hear nothing.
");
497 | }
498 | },
499 | search: "
You find nothing.
"
500 | }
501 | }
502 | );
503 |
504 | notice how the `listen` function is responsible for its own output,
505 | where the `search` property is a string in Display Content format,
506 | ready for output.
507 |
508 | #### Functions in `SimpleSituation`
509 |
510 | Both the `content` and the `heading` of a simple situation can be
511 | provided either as plain text, or as a function. If you provide a
512 | function, then it will be called with no arguments, and it should
513 | return a string to use for the output. This enables `SimpleSituation`
514 | to be used with other formatting and templating systems.
515 |
516 | # QualityDefinition
517 |
518 | Quality definitions tell Undum how and where to display a quality in
519 | the character panel. Each quality definition has one method, `format`,
520 | which is responsible for converting a numeric quality value into a
521 | displayable quantity.
522 |
523 | You define your qualities in your `undum.game.qualities` property.
524 |
525 |
526 | #### `new QualityDefinition(title, options)`
527 |
528 | Creates a new `QualityDefinition`. It is rare to call this constructor
529 | yourself, most often one of the derived types of `QualityDefinition`
530 | are used. They are defined below.
531 |
532 | The `title` should be a string, and can contain HTML. It is used to
533 | label the quality in the character panel. It can be any string, it
534 | doesn't have to be in Display Content format.
535 |
536 | Options are passed in in the `options` parameter. The following
537 | options are available.
538 |
539 | - `priority`: A string used to sort qualities within their
540 | groups. When the system displays a list of qualities they will be
541 | sorted by this string. If you don't give a priority, then the title
542 | will be used, so you'll get alphabetic order. Normally you either
543 | don't give a priority, or else use a priority string containing
544 | 0-padded numbers (e.g. "00001").
545 |
546 | - `group`: The identifier of a group in which to display this
547 | parameter. If a group is given, then it must be defined in your
548 | `undum.game.qualityGroups` property.
549 |
550 | - `extraClasses`: These classes will be attached to the `
` tag
551 | that surrounds the quality when it is displayed. A common use for
552 | this is to add icons representing the quality. In your CSS define a
553 | class for each icon, then pass those classes into the appropriate
554 | quality definitions.
555 |
556 | #### `format(character, value)`
557 |
558 | This is called by Undum to get a human readable string representing
559 | the given quality value for the given character. The method may return
560 | an empty string if the value has no need to be displayed, or it may
561 | return `null` if the quantity itself shouldn't be displayed. The
562 | difference here is significant. If your `QualityDefinition` returns
563 | the empty string, then the quality will appear in the character panel,
564 | but it will have no value marked. If it returns `null`, then it will
565 | be removed from the character panel entirely.
566 |
567 | Most commonly the `character` parameter is ignored, but in your own
568 | derived types you can take advantage of being able to access other
569 | information about the character.
570 |
571 | You may call this function yourself, but there is commonly no need. It
572 | will be called by Undum any time the corresponding quality needs to be
573 | displayed.
574 |
575 | ## `IntegerQuality`
576 |
577 | This is a derived type of `QualityDefinition` that displays the
578 | quality value by rounding it down to the nearest integer. This is
579 | ideal for most numeric statistics.
580 |
581 | ## `NonZeroIntegerQuality`
582 |
583 | This is a derived type of `IntegerQuality` that only displays its
584 | value when it is non-zero. If it is non-zero then it formats in the
585 | same way as `IntegerQuality`. Whereas `IntegerQuality` whould show
586 | zero values as '0', this type of quality displays nothing.
587 |
588 | ## `NumericQuality`
589 |
590 | This is a derived type of `QualityDefinition` that displays the
591 | quality value directly, as a full floating point value.
592 |
593 | ## `WordScaleQuality`
594 |
595 | Sometimes you want qualities displayed in words rather than
596 | numbers. This is a derived type of `QualityDefinition` that allows you
597 | to define words corresponding to possible quality values.
598 |
599 | #### `new WordScaleQuality(title, words, options)`
600 |
601 | The `title` parameter is exactly as for `QualityDefinition`.
602 |
603 | The `words` parameter determines what words will be used. It should be
604 | an array of strings. By default the first string will be used to
605 | represent a value of zero (after rounding down), and the second string
606 | a value of 1, and so on to the end of the array. Values outside the
607 | array are treated differently depending on the value of `useBonuses`
608 | in the `options` parameter.
609 |
610 | The `options` parameter supports the same three options as
611 | `QualityDefinition`. It also takes the following additional
612 | parameters:
613 |
614 | - `offset`: With offset=0 (the default), a quantity value of 0 will
615 | map to the first word, and so on. If offset is non-zero then the
616 | value given will correspond to the first word in the list. So if
617 | offset=4, then the first word in the list will be used for value=4,
618 | the second for value=5. You can specify a non-integer offset value,
619 | in this case the offset is applied *before* the value is rounded
620 | down.
621 |
622 | - `useBonuses`: If this is true (the default), then values outside the
623 | range of words will be constructed from the word and a numeric
624 | bonus. So with offset=0 and five words, the last of which is
625 | 'amazing', a score of six would give 'amazing+1'. if this is
626 | false, then the bonus would be omitted, so anything beyond
627 | 'amazing' is still 'amazing'.
628 |
629 | ## `FudgeAdjectivesQuality`
630 |
631 | This is a derived type of `WordScaleQuality` that doesn't require you
632 | to specify the words you wish to use. It uses the word scale from the
633 | Fudge RPG: "terrible", "poor", "mediocre", "fair", "good", "great" and
634 | "superb".
635 |
636 | #### `new FudgeAdjectivesQuality(title, options)`
637 |
638 | The parameters `title` and `options` are as for the `WordScaleQuality`
639 | constructor. The `offset` option defaults to -3, however (in
640 | `WordScaleQuality` it defaults to 0), making "fair" the display value
641 | for 0.
642 |
643 | ## `OnOffQuality`
644 |
645 | An `OnOffQuality` returns `null` from its `format` method
646 | (i.e. removes itself from the character panel) when the corresponding
647 | quality value is zero. Otherwise it returns the empty string (i.e. it
648 | is shown in the panel, but doesn't have a value label). See
649 | `QualityDisplay.format` above for more details on this distinction.
650 |
651 | #### `new OnOffQuality(title, options)`
652 |
653 | The constructor for this type is the same as for `QualityDefinition`
654 | from which it is derived. It accepts one extra option:
655 |
656 | - `onDisplay`: If given, then rather than displaying the empty string,
657 | it displays the given string when its corresponding value is
658 | non-zero. This can be used to display a check-mark, for example
659 | (`{onDisplay:"✓"}`), or even a HTML `img` tag.
660 |
661 | ## YesNoQuality
662 |
663 | A `YesNoQuality` displays one of two strings depending whether its
664 | value is zero or not.
665 |
666 | #### `new YesNoQuality(title, options)`
667 |
668 | The constructor for this type is the same as for `QualityDefinition`
669 | from which it is derived. It accepts two extra options:
670 |
671 | - `yesDisplay`, `noDisplay`: Either or both of these may be given. If
672 | they are given, then they should be set to a string, which will be
673 | used to indicate non-zero or zero values, respectively. By default
674 | "yes" and "no" are used.
675 |
676 | # `QualityGroup`
677 |
678 | A quality group defines a set of qualities that should be displayed
679 | together in the character panel, under an optional subheading. You
680 | could use quality groups to distinguish between qualities representing
681 | a character's innate abilities and their equipment, for example.
682 |
683 | You define your quality groups in your `undum.game.qualityGroups`
684 | property.
685 |
686 |
687 | #### `new QualityGroup(title, options)`
688 |
689 | Constructs a new quality group that will have the given `title` for a
690 | subheading. The title may be `null`, indicating that this group does
691 | not need a heading.
692 |
693 | The `options` parameter should be an object with the given optional
694 | parameters:
695 |
696 | - `priority`: A string used to sort quality groups. When the system
697 | displays more than one quality group, they will be sorted by this
698 | string. If you don't give a priority, then the title will be used,
699 | so you'll get alphabetic order. Normally you either don't give a
700 | priority, or else use a priority string containing 0-padded numbers
701 | (e.g. "00001").
702 |
703 | - `extraClasses`: These classes will be attached to the `
` tag
704 | that surrounds the entire quality group when it is displayed. You
705 | can use this in addition to your CSS to radically change the way
706 | certain qualities are displayed.
707 |
--------------------------------------------------------------------------------