#charset "Latin1" /* * Module for yes/no answers to the narrator. * 2003/06/17, by Nikos Chantziaras * This file is in the Public Domain. There is no copyright. * * To use this module, simply compile it together with the rest of your * game's source files. */ #include #include /* * To enable the player to answer a question asked by the narrator (NPC * questions are handled by the Tads 3 library), call one of the "set" * methods of the ncYesNo object. The methods are: * * set( STRING_OR_FUNCTION, STRING_OR_FUNCTION ) * * The arguments must be either strings or functions that take no * arguments. The first argument is called/displayed when the player * types YES, the second when the answer is NO. Example: * * dobjFor(Attack) * { * action() * { * "Attacking the troll is pretty dangerous. Are you sure? "; * ncYesNo.set( * // This anonymous function will be called if the player * // anwers with YES. * {: * "You get ready for battle, but the troll kills you * before you can even blink!\b*** You have died ***\b"; * finishGame(finishOptionUndo); * }, * // This string will be displayed if the player anwers NO. * 'Wise decision. ' * ); * } * } * * setAll( STRING_OR_FUNCTION ) * * Same as set(), but the argument is used for both YES and NO. * * setRhetorical() * * This calls setAll() like this: * * self.setAll(self.rhetoricalAnswer); * * The property 'rhetoricalAnswer' contains the string to be displayed * with setRhetorical(). The default is: 'That was a rhetorical * question. ' If you want to display something else, you can simply * set it to something different: * * modify ncYesNo { * rhetoricalAnswer = 'The question was rhetorical. '; * } * * The property 'defaultYesAnswer' contains the string to be displayed * when the player types YES while no question has been asked and the * PC has no current interlocutor. The default is: 'You sound rather * positive. ' * * Similarly, the 'defaultNoAnswer' property defaults to: 'You sound * rather negative. ' * * The player has only one turn to answer to a question. After that, * the reset() method is called, which resets any effects caused by one * of the "set" methods. * * The situation where the PC has a current interlocutor is handled * automaticly. Example: * * >no * I'm glad you disagree. * * >bob, no * Bob does not respond. * [The PC's current interlocutor is now Bob.] * * >no * Bob does not respond. * * >knock on my door * Don't you think knocking on your own door is a bit strange? * * >no * That was a rhetorical question. * [Although the current interlocutor is Bob, we treat NO as the * answer to the narrator's question.] * * >no * Bob does not respond. * [Since the player already answered the narrator's question, NO is * now redirected to Bob.] */ ncYesNo: object { rhetoricalAnswer = 'That was a rhetorical question. '; defaultYesAnswer = 'You sound rather positive. '; defaultNoAnswer = 'You sound rather negative. '; reset() { if (self._active) { self._onYes = nil; self._onNo = nil; self._active = nil; self._myFuse.removeEvent(); self._myFuse = nil; if (self._lastIssuer.isPlayerChar()) { self._lastIssuer.lastInterlocutor = self._lastInterlocutor; } } } set( yes, no ) { if (self._active) self.reset(); self._onYes = yes; self._onNo = no; self._active = true; self._myFuse = new Fuse(self, &reset, 1); self._lastIssuer = gIssuingActor; self._lastInterlocutor = self._lastIssuer.getCurrentInterlocutor(); } setAll( yesOrNo ) { self.set(yesOrNo, yesOrNo); } setRhetorical() { self.setAll(self.rhetoricalAnswer); } // Private members; do not modify or evaluate. _onYes = nil; _onNo = nil; _active = nil; _myFuse = nil; _lastIssuer = nil; _lastInterlocutor = nil; } /* -------------------------------------------------------------------- * Modify YesAction and NoAction to use the ncYesNo system. */ modify YesAction { execAction() { if (gActor.isPlayerChar()) { if (ncYesNo._active) { if (dataType(ncYesNo._onYes) == TypeSString) { say(ncYesNo._onYes); } else { (ncYesNo._onYes)(); } } else { if (gIssuingActor.getCurrentInterlocutor()) { inherited(); } else { say(ncYesNo.defaultYesAnswer); } } } else { inherited(); } } } modify NoAction { execAction() { if (gActor.isPlayerChar()) { if (ncYesNo._active) { if (dataType(ncYesNo._onNo) == TypeSString) { say(ncYesNo._onNo); } else { (ncYesNo._onNo)(); } } else { if (gIssuingActor.getCurrentInterlocutor()) { inherited(); } else { say(ncYesNo.defaultNoAnswer); } } } else { inherited(); } } }