| /* | |
| * Reaction objects extension. | |
| * | |
| * This creates BeforeAction and AfterAction objects, and a framework to use | |
| * them, rather like AskTellTopic. The idea is that instead of filling your | |
| * beforeAction and afterAction methods with sphaghetti code, all you have to | |
| * do is define a set of BeforeAction and AfterAction objects and nest them in | |
| * the objects that needs to react to things. | |
| * | |
| * The main two types of Reaction objects are BeforeAction and AfterAction. | |
| * These can be nested in any kind of Thing in your game world, as well as in | |
| * any ActorState. The extension also provides RoomBeforeAction and | |
| * RoomAfterAction objects, which can be used with any Room (including | |
| * NestedRooms). | |
| * | |
| * All Reaction objects provide the same set of properties. actor, action, | |
| * dobj, and iobj allow you to decide when the Reaction should happen. If they | |
| * are defined, they must match the current action before the Reaction will | |
| * run. They can be either a single object or a list of objects. If you use a | |
| * list, matching any of the items in the list will allow the Reaction to run. | |
| * You can also define a condition, which lets you add any extra restrictions | |
| * you want. | |
| * | |
| * If isOneOff is true, the reaction will only happen once; otherwise it will | |
| * happen every time it is active. If isDone is true, the reaction will no | |
| * longer run. If isOneOff is true, isDone will be automatically set when the | |
| * reaction first runs, but you can also set it manually if you want to. If | |
| * stopAction is true, the reaction will exit() the current action. | |
| * | |
| * When a Reaction is active, it will run the code in its react() method. | |
| * Alternatively, you can create a Reaction that also inherits from an | |
| * EventList class; in that case, the EventList will run when the Reaction is | |
| * active. | |
| * | |
| * You can determine the order Reactions happen in by changing their priority. | |
| * The higher the priority, the sooner the reaction will happen. The default | |
| * is 100. | |
| * | |
| * Some example code: | |
| * | |
| * linda: Person | |
| * 'linda' | |
| * 'Linda' | |
| * isProperName = true | |
| * isHer = true | |
| * isMad = nil | |
| * ; | |
| * | |
| * + AfterAction | |
| * actor = gPlayerChar | |
| * action = ExamineAction | |
| * dobj = linda | |
| * isOneOff = true | |
| * react() { | |
| * "Linda catches your eye. <q>Hey, quit starin' at me!</q> she snaps. "; | |
| * linda.isMad = true; | |
| * } | |
| * ; | |
| * | |
| * + AfterAction | |
| * actor = gPlayerChar | |
| * action = ExamineAction | |
| * dobj = linda | |
| * condition = (linda.isMad) | |
| * isOneOff = true | |
| * priority = 150 // runs earlier than the other AfterActions | |
| * react() { | |
| * "You don't even see Linda's fist coming. Flat on your back, you stare | |
| * up at her in confusion.<.p> | |
| * <q>I told you to keep your sneaky eyes off me!</q> she says, and | |
| * stalks out of the room. "; | |
| * linda.moveIntoForTravel(nil); | |
| * gPlayerChar.hasHeadache = true; | |
| * } | |
| * | |
| * + BeforeAction | |
| * actor = gPlayerChar | |
| * action = TakeAction | |
| * dobj = stackOfCash | |
| * stopAction = true | |
| * react() { | |
| * "Linda slaps your hand away. <q>Hands off!</q> "; | |
| * } | |
| * ; | |
| * | |
| * This extension is open source software licensed under the MIT Licence: | |
| * | |
| * Copyright (c) 2013 Emily Boegheim | |
| * | |
| * Permission is hereby granted, free of charge, to any person obtaining a | |
| * copy of this software and associated documentation files (the "Software"), | |
| * to deal in the Software without restriction, including without limitation | |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| * and/or sell copies of the Software, and to permit persons to whom the | |
| * Software is furnished to do so, subject to the following conditions: | |
| * | |
| * The above copyright notice and this permission notice shall be included in | |
| * all copies or substantial portions of the Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
| * DEALINGS IN THE SOFTWARE. | |
| * | |
| * Change history: | |
| * | |
| * 0.2 | |
| * - changed priority ordering from lowest-first to highest-first and made the | |
| * default priority 100 to match similar properties in adv3 | |
| * - simplified handling of the "condition" property | |
| * - fixed a remarkably stupid bug where I'd done all the work to implement | |
| * RoomBeforeAction and RoomAfterAction classes except, y'know, actually | |
| * *implement* those classes | |
| * - changed Reaction.isActive to always return nil if isDone is true | |
| * (previously this only worked if isOneOff was also true, but authors | |
| * might want to set isDone manually on other kinds of Reactions as well) | |
| * - added credits module | |
| * | |
| * 0.1 | |
| * - first public beta release | |
| */ | |
| /* Info on the extension, so it will show up in the list of credits. */ | |
| reactionsModuleID: ModuleID | |
| name = 'Reactions' | |
| byline = 'by Emily Boegheim' | |
| htmlByline = 'by <a href="mailto:emily.boegheim@gmail.com">Emily | |
| Boegheim</a>' | |
| version = '0.2' | |
| ; | |
| /* | |
| * First the base class: Reaction. Provides default properties and isActive | |
| * handling. | |
| */ | |
| class Reaction: object | |
| actor = nil | |
| action = nil | |
| dobj = nil | |
| iobj = nil | |
| condition = true | |
| /* some reactions should only happen once */ | |
| isOneOff = nil | |
| isDone = nil | |
| /* | |
| * Which list should this Reaction belong to? This needs to be overridden | |
| * for each subclass. Authors using the extension shouldn't need to change | |
| * this unless they are creating their own Reaction subclasses. | |
| */ | |
| reactionObjList = nil | |
| /* | |
| * Check to see if the Reaction is active. By default, a Reaction is | |
| * active when, if any of its action-matching properties (actor, action, | |
| * dobj, iobj) have a value, those defined match those in existence. The | |
| * properties can be either lists (in which case any of the items in the | |
| * list may match) or a single object/class (in which case it must match | |
| * specifically). | |
| * | |
| * This class also provides a "condition" property, which must evaluate | |
| * to true. | |
| * | |
| * For more complex conditions, authors may simply override this function | |
| * to return whatever result they wish. | |
| */ | |
| isActive() | |
| { | |
| /* not if it's over and done with */ | |
| if (isDone) | |
| return nil; | |
| /* check the conditions */ | |
| if (actor != nil && ((actor.ofKind(List) && !actor.indexOf(gActor)) | |
| || (actor.ofKind(Thing) && actor != gActor))) | |
| return nil; | |
| if (action != nil && ((action.ofKind(List) && !actionInList()) || | |
| (action.ofKind(Action) && !gAction.ofKind(action)))) | |
| return nil; | |
| if (dobj != nil && ((dobj.ofKind(List) && !dobj.indexOf(gDobj)) | |
| || (dobj.ofKind(Thing) && dobj != gDobj))) | |
| return nil; | |
| if (iobj != nil && ((iobj.ofKind(List) && !iobj.indexOf(gIobj)) | |
| || (iobj.ofKind(Thing) && iobj != gIobj))) | |
| return nil; | |
| return condition; | |
| } | |
| /* Check whether the current action is in this object's action list. */ | |
| actionInList() | |
| { | |
| foreach (local cur in action) | |
| { | |
| if (gAction.ofKind(cur)) | |
| return true; | |
| } | |
| return nil; | |
| } | |
| /* | |
| * If this property is set to true, the action will be stopped after | |
| * this object has performed its reaction. | |
| */ | |
| stopAction = nil | |
| /* | |
| * Assuming we're active, react. This method should not be overridden | |
| * by authors, as it does a little housekeeping. | |
| */ | |
| exec() | |
| { | |
| /* | |
| * If we inherit from Script, run the script; otherwise let the | |
| * react() method handle it. Stop the action afterwards if | |
| * necessary. | |
| */ | |
| if (ofKind(Script)) | |
| doScript(); | |
| else | |
| react(); | |
| /* If this is a one-off reaction, note that it's done. */ | |
| if (isOneOff) | |
| isDone = true; | |
| /* If this reaction stops the action, stop it now. */ | |
| if (stopAction) | |
| exit; | |
| } | |
| /* A method for authors to override - called by exec(). */ | |
| react() | |
| { | |
| /* by default, do nothing */ | |
| } | |
| /* | |
| * We may want some objects to react before others, so a priority | |
| * property. The lower the priority, the sooner this object will be | |
| * called. The default is 100, for no reason other than to be consistent | |
| * with adv3's handling of similar properties. | |
| */ | |
| priority = 100 | |
| /* | |
| * For consistency with adv3 classes, a method to return the actor to | |
| * which this ReAction object belongs. | |
| */ | |
| getActor() | |
| { | |
| /* if nested in an ActorState or something similar */ | |
| if (location.ofKind(ActorState)) | |
| return location.getActor(); | |
| /* otherwise just return whatever it's nested in */ | |
| return location; | |
| } | |
| ; | |
| /* The Reaction subclasses. */ | |
| class BeforeAction: Reaction | |
| reactionObjList = &beforeObjList | |
| ; | |
| class AfterAction: Reaction | |
| reactionObjList = &afterObjList | |
| ; | |
| class RoomBeforeAction: Reaction | |
| reactionObjList = &roomBeforeObjList | |
| ; | |
| class RoomAfterAction: Reaction | |
| reactionObjList = &roomAfterObjList | |
| ; | |
| /* | |
| * Preinitialisation must make sure each object in the game gets lists of | |
| * its BeforeAction and AfterAction objects. | |
| */ | |
| reactionObjsPreinit: PreinitObject | |
| /* | |
| * Run through all the Reaction objects in the game and place them in the | |
| * correct list in their parent objects. Then sort the lists. | |
| */ | |
| execute() | |
| { | |
| /* Add all objects descended from Reaction to their owners' lists. */ | |
| forEachInstance(Reaction, new function(x) { | |
| local prop = x.reactionObjList(); | |
| x.location.(prop) = x.location.(prop).append(x); | |
| }); | |
| /* Sort the lists. */ | |
| local func = {a, b: a.priority - b.priority}; | |
| for (local obj = firstObj(Thing); obj != nil; | |
| obj = nextObj(obj, Thing)) { | |
| sortLists(obj, func); | |
| } | |
| for (local obj = firstObj(ActorState); obj != nil; | |
| obj = nextObj(obj, ActorState)) { | |
| sortLists(obj, func); | |
| } | |
| } | |
| sortLists(obj, func) | |
| { | |
| /* All the lists that need to be sorted. */ | |
| local lists = [&beforeObjList, &afterObjList]; | |
| if (obj.ofKind(BasicLocation)) | |
| { | |
| lists += [&roomBeforeObjList, &roomAfterObjList]; | |
| } | |
| /* Sort each of the lists for the given object. */ | |
| foreach (local l in lists) | |
| { | |
| if (obj.(l).length > 0) | |
| obj.(l) = obj.(l).sort(true, func); | |
| } | |
| } | |
| execBeforeMe = [adv3LibPreinit] | |
| ; | |
| /* Now to teach objects how to use their brand-spanking new Reaction objects. */ | |
| modify Thing | |
| /* | |
| * The lists of BeforeAction or AfterAction objects. None by default, | |
| * of course. | |
| */ | |
| beforeObjList = [] | |
| afterObjList = [] | |
| /* | |
| * The beforeAction method must check whether this object has any | |
| * BeforeAction objects, and if so, whether any of them are active. Tell | |
| * any active ones to react. | |
| */ | |
| beforeAction() | |
| { | |
| foreach (local obj in beforeObjList) { | |
| if (obj.isActive) | |
| obj.exec(); | |
| } | |
| } | |
| /* Same deal for afterAction. */ | |
| afterAction() | |
| { | |
| foreach (local obj in afterObjList) { | |
| if (obj.isActive) | |
| obj.exec(); | |
| } | |
| } | |
| ; | |
| modify BasicLocation | |
| /* The lists of RoomBeforeAction and RoomAfterAction objects. */ | |
| roomBeforeObjList = [] | |
| roomAfterObjList = [] | |
| /* | |
| * The roomBeforeAction method must check whether this object has any | |
| * RoomBeforeAction objects, and if so, whether any of them are active. | |
| * Tell any active ones to react. | |
| */ | |
| roomBeforeAction() | |
| { | |
| foreach (local obj in roomBeforeObjList) { | |
| if (obj.isActive) | |
| obj.exec(); | |
| } | |
| } | |
| /* Same deal for roomAfterAction. */ | |
| roomAfterAction() | |
| { | |
| foreach (local obj in roomAfterObjList) { | |
| if (obj.isActive) | |
| obj.exec(); | |
| } | |
| } | |
| ; | |
| /* | |
| * Actors have special beforeAction handling, which we need to preserve | |
| * while still including the default Thing handling. Rather arbitrarily, | |
| * we'll let the Actor handling (including checking the current | |
| * ActorState's handling) run before the Thing handling. | |
| */ | |
| modify Actor | |
| beforeAction() | |
| { | |
| inherited(); | |
| inherited Thing(); | |
| } | |
| afterAction() | |
| { | |
| inherited(); | |
| inherited Thing(); | |
| } | |
| ; | |
| /* | |
| * ActorStates should treat beforeAction and afterAction the same way Things | |
| * do. | |
| */ | |
| modify ActorState | |
| /* | |
| * The lists of BeforeAction or AfterAction objects. None by default, | |
| * of course. | |
| */ | |
| beforeObjList = [] | |
| afterObjList = [] | |
| /* | |
| * Delegate beforeAction and afterAction to the equivalent methods of | |
| * Thing. | |
| */ | |
| beforeAction() | |
| { | |
| delegated Thing(); | |
| } | |
| afterAction() | |
| { | |
| delegated Thing(); | |
| } | |
| ; | |
| /* | |
| * Keyrings have special beforeAction and afterAction handling, which we | |
| * need to preserve while still including the default Thing handling. | |
| */ | |
| modify Keyring | |
| beforeAction() | |
| { | |
| inherited(); | |
| inherited Thing(); | |
| } | |
| afterAction() | |
| { | |
| inherited(); | |
| inherited Thing(); | |
| } | |
| ; | |
Xet Storage Details
- Size:
- 14.4 kB
- Xet hash:
- f3508b9f6dfcb9242cb6b96e42bd1311cef907555bb0ac1d51000ecc8434d52f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.