tips.t | documentation |
#charset "us-ascii" /* * TADS 3 Tips, by Krister Fundin (fundin@yahoo.com). Provides a uniform * way of providing one-time only tips to the player (and especially to * inexperienced players) when certain things happen in the game. */ #include <adv3.h> /* ---------------------------------------------------------------------- */ /* * The tip manager keeps track of which tips we have shown. Since we don't * want to unnecessarily show any tips more than once, we store this * information both transiently (in the tipManager) and persistently (in * the tip objects themselves). This should make sure that we at least * cover these two types of cases: * * - The player sees a tip, then restarts, undos or restores to an earlier * position. * - The player sees a tip, saves, then resumes play at some later time. */ transient tipManager: InitObject, PostRestoreObject, PostUndoObject /* * Show pending tips. This is called by a PromptDaemon before each new * round of input. */ showTips() { /* * Go through our vector of pending tips. Use a 'for' loop instead * a 'foreach' loop, in case showing one tip triggers another one. */ for (local i = 1 ; i <= pendingTips.length ; i++) { /* show the description of the current tip */ pendingTips[i].showTipDesc(); } /* clear the vector of pending tips */ pendingTips.setLength(0); } /* update tip information after a restore, restart or undo */ execute() { /* go through all tips */ forEachInstance(Tip, function(tip) { /* * see if this one has been shown, according to its own * persistent memory */ if (tip.shown) { /* * It says that it has been shown. If it's not in our list * of shown tips, then add it. */ if (shownTips.indexOf(tip) == nil) shownTips += tip; } else { /* * It says that it hasn't been shown. If it's in our list * of shown tips, then it must have been shown after all. */ if (shownTips.indexOf(tip) != nil) tip.shown = true; } }); } /* a vector of tips to be displayed before the next prompt */ pendingTips = static new Vector(2) /* * A transient list of shown tips. Note that this must be a list and * not a vector. When updating a list, we actually replace it with a * new list, since lists are immutable. This is a transient change - * it affects only the value of the shownTips property. Updating a * vector, however, modifies the vector itself and leaves the property * with the same reference. A vector itself is always persistent, so * this change would be lost after E.G. a restore. */ shownTips = [] ; /* * The Tip class. Each actual tip should be represented by an instance of * this class. To show the tip, just call tipName.showTip(). If the tip * has already been shown, or if the tips have been turned off completely, * then nothing will be displayed. */ class Tip: object /* * The actual text to display when this tip is shown. We'll wrap it in * <.tip> tags automatically, and also add a paragraph break before * it. */ desc = "" /* show this tip */ showTip() { /* see if we should be shown */ if (!shouldShowTip) return; /* * defer the actual displaying of the tip until just before the * next command prompt */ tipManager.pendingTips.append(self); /* note that we have been shown */ makeShown(); } /* display our tip description, I.E. the actual tip */ showTipDesc() { /* display a pargraph break and an opening <.tip> style tag */ "<.p><.tip>"; /* show our description */ desc(); /* close the <.tip> tag */ "<./tip>"; } /* should we show this tip when asked to? */ shouldShowTip() { /* * We'll show it as long as it hasn't been shown before and we * haven't turned the tips off completely. Certain tips might want * to be displayed even when all tips are turned off, if they * contain information specific to a certain story or an extension * that it uses. If so, then this method could be overridden. */ return (!shown && tipMode.isOn); } /* * Mark this tip as shown. This method can be called by outside code * before the tip has been triggered. If the tip informs the player of * a certain command, for instance, then it would become redundant if * the player has already used that command. */ makeShown() { /* set our shown flag */ shown = true; /* also add us to the transient list of shown tips */ tipManager.shownTips += self; } /* flag: has this tip been shown before? */ shown = nil ; /* * A style tag that we enclose tips with. By default, we just use plain * parentheses, just like for notifications and parser messages, but this * could be overridden if we wanted to display something fancier. */ tipStyleTag: StyleTag 'tip' openText = '(' closeText = ')' ; /* * During pre-init, create a PromptDaemon for displaying tips. We don't * want to display them directly when the showTip() method is called, to * allow tips to be triggered from pretty much anywhere without having to * worry about them showing up in the middle of some text. */ PreinitObject execute() { /* * Give this daemon a higher-than-average eventOrder, in case * another PromptDaemon wants to display a tip. The standard tip * about turning of score notification is triggered this way. */ new PromptDaemon(tipManager, &showTips).eventOrder = 200; } ; /* ---------------------------------------------------------------------- */ /* * Next, we want to allow turning all tips on and off during the game. It * should also be possible to turn the tips off for ALL games that use * them, and thus we define a SettingsItem for this purpose. This means * that the player can turn the tips off and then save this setting as the * default. */ tipMode: BinarySettingsItem /* we show tips by default */ isOn = true /* the ID string to use in the configuration file */ settingID = 'tips.showtips' /* show our description */ settingDesc = (libMessages.tipStatusShort(isOn)) ; /* * Define a system action for turning tip mode on/off. */ DefineSystemAction(TipMode) execSystemAction() { /* set the new tip mode */ tipMode.isOn = stat_; /* acknowledge the change */ libMessages.acknowledgeTipStatus(stat_); } ;
TADS 3 Library Manual
Generated on 5/16/2013 from TADS version 3.1.3
Generated on 5/16/2013 from TADS version 3.1.3