| | 1 | #charset "us-ascii" |
| | 2 | |
| | 3 | #include <adv3.h> |
| | 4 | #include <en_us.h> |
| | 5 | |
| | 6 | |
| | 7 | /* |
| | 8 | * custmsg.t |
| | 9 | *. by Eric Eve (eric.eve@hmc.ox.ac.uk) |
| | 10 | *. Version 1.1 - 28-Mar-08 |
| | 11 | * |
| | 12 | * A small extension that makes it easier to customize or suppress certain |
| | 13 | * library-generated pieces of descriptive text. |
| | 14 | * |
| | 15 | * (1) If postureReportable is set to nil on an ActorState, the |
| | 16 | * library-generated postureDesc() (e.g. "Mavis is sitting on the wooden |
| | 17 | * chair. ") is no longer incorporated into the description in response to |
| | 18 | * an EXAMINE command. |
| | 19 | * |
| | 20 | * (2) Openable now has an openStatusReportable property (analogous to |
| | 21 | * lockStatusReportable on Lockable) that makes it easy to suppress the |
| | 22 | * "it's open" and "it's closed" messages that get tagged onto the end of |
| | 23 | * the descriptions of Openable objects. |
| | 24 | * |
| | 25 | * (3) It's now easier to customize or suppress the "(providing light)" |
| | 26 | * and "(lit)" messages that appear after the names of LightSources in |
| | 27 | * inventory listings and the like; just override the providingLightMsg on |
| | 28 | * the object in question. The mechanism can be extended to use other |
| | 29 | * properties on other classes of objects using author-defined ThingStates. |
| | 30 | * |
| | 31 | * (4) The new Thing property specialContentsListedInExamine can be set |
| | 32 | * to nil to suppress the listing of any contents that uses a specialDesc. |
| | 33 | */ |
| | 34 | |
| | 35 | /* Version 1.1 adds the openStatusReportable property to ContainerDoor */ |
| | 36 | |
| | 37 | |
| | 38 | /* |
| | 39 | * The modifications to Actor and ActorState allow authors to opt in to |
| | 40 | * including a postureDesc (e.g, "Mavis is sitting on the wooden chair. ") |
| | 41 | * when a stateDesc is already provided, instead of having to opt out. |
| | 42 | */ |
| | 43 | |
| | 44 | modify Actor |
| | 45 | replace examineStatus() |
| | 46 | { |
| | 47 | /* |
| | 48 | * If I'm an NPC, show where I'm sitting/standing/etc. (If I'm |
| | 49 | * the PC, we don't usually want to show this explicitly to avoid |
| | 50 | * redundancy. The player is usually sufficiently aware of the |
| | 51 | * PC's posture by virtue of being in control of the actor, and |
| | 52 | * the information also tends to show up often enough in other |
| | 53 | * places, such as on the status line and in the room |
| | 54 | * description.) |
| | 55 | * |
| | 56 | * Also, we only show this if the curState's postureReportable |
| | 57 | * property is true. This allows redundant posture descriptions |
| | 58 | * to be suppressed if the current ActorState's stateDesc already |
| | 59 | * mentions them. |
| | 60 | */ |
| | 61 | if (!isPlayerChar() && curState.postureReportable) |
| | 62 | postureDesc; |
| | 63 | |
| | 64 | |
| | 65 | /* show the status from our state object */ |
| | 66 | curState.stateDesc; |
| | 67 | |
| | 68 | |
| | 69 | /* inherit the default handling to show our contents */ |
| | 70 | inherited(); |
| | 71 | } |
| | 72 | ; |
| | 73 | |
| | 74 | modify ActorState |
| | 75 | |
| | 76 | /* |
| | 77 | * By default the actor's postureDesc() is displayed between its desc |
| | 78 | * and the stateDesc on the current ActorState. If the stateDesc |
| | 79 | * already mentions the actor's posture this may be redundant; changing |
| | 80 | * postureReportable to nil suppresses the display of the |
| | 81 | * postureDesc(). |
| | 82 | */ |
| | 83 | postureReportable = true |
| | 84 | ; |
| | 85 | |
| | 86 | //------------------------------------------------------------------------------ |
| | 87 | |
| | 88 | /* |
| | 89 | * The following modification to ThingState is designed to make it easier to |
| | 90 | * customize state-dependent messages such as '(providing light)' or |
| | 91 | * '(being worn)'. The mechanism should be readily extensible to |
| | 92 | * author-defined ThingStates. |
| | 93 | */ |
| | 94 | |
| | 95 | modify LightSource |
| | 96 | /* |
| | 97 | * The message that's appended to our name in inventory listings and the |
| | 98 | * like when we're lit; the default in the English language library is |
| | 99 | * '(providing light)'. To suppress the message altogether, set this |
| | 100 | * property to nil. To replace it with another message, omit the |
| | 101 | * parentheses, e.g. on a flashlight you might define: |
| | 102 | * |
| | 103 | * providingLightMsg = 'currently switched on' |
| | 104 | */ |
| | 105 | providingLightMsg = lightSourceStateOn.listName_ |
| | 106 | notProvidingLightMsg = lightSourceStateOff.listName_ |
| | 107 | ; |
| | 108 | |
| | 109 | modify Matchstick |
| | 110 | /* |
| | 111 | * The message that's appended to our name in inventory listings and the |
| | 112 | * like when we're lit; the default in the English language library is |
| | 113 | * '(lit)'. To suppress the message altogether, set this |
| | 114 | * property to nil. To replace it with another message, omit the |
| | 115 | * parentheses, e.g. : |
| | 116 | * |
| | 117 | * providingLightMsg = 'now ablaze' |
| | 118 | */ |
| | 119 | providingLightMsg = matchStateLit.listName_ |
| | 120 | notProvidingLightMsg = matchStateUnlit.listName_ |
| | 121 | ; |
| | 122 | |
| | 123 | modify Wearable |
| | 124 | /* |
| | 125 | * The messages that's appended to our name in listing when we're worn |
| | 126 | * or unworn. By default this will be '(worn)' or nothing; but the |
| | 127 | * wornMsg won't be used if we're appearing in a list of items |
| | 128 | * introduced as being worn (e.g. "You are wearing..."). |
| | 129 | */ |
| | 130 | wornMsg = wornState.listName_ |
| | 131 | unwornMsg = unwornState.listName_ |
| | 132 | ; |
| | 133 | |
| | 134 | |
| | 135 | modify ThingState |
| | 136 | listName(lst) |
| | 137 | { |
| | 138 | /* |
| | 139 | * if we have a msgProp and there's one item in our list, use the |
| | 140 | * msgProp of that item to provide our state-dependent text. |
| | 141 | */ |
| | 142 | if(msgProp != nil && lst.length() == 1) |
| | 143 | return (lst[1]).(msgProp); |
| | 144 | |
| | 145 | /* Otherwise, use our listName_ (as in the standard library) */ |
| | 146 | return listName_; |
| | 147 | } |
| | 148 | |
| | 149 | /* |
| | 150 | * The property on the object being described that will provide the |
| | 151 | * text for any state-dependent extra description, such as 'providing |
| | 152 | * light'. If this is defined, it should be set to a property pointer, |
| | 153 | * e.g. &providingLightMsg. If it is left at nil ThingState will behave |
| | 154 | * just as it does in the standard library. |
| | 155 | */ |
| | 156 | msgProp = nil |
| | 157 | ; |
| | 158 | |
| | 159 | modify lightSourceStateOn |
| | 160 | msgProp = &providingLightMsg |
| | 161 | ; |
| | 162 | |
| | 163 | modify matchStateLit |
| | 164 | msgProp = &providingLightMsg |
| | 165 | ; |
| | 166 | |
| | 167 | modify wornState |
| | 168 | msgProp = &wornMsg |
| | 169 | ; |
| | 170 | |
| | 171 | /* |
| | 172 | * Although the following three ThingStates don't display any state-related |
| | 173 | * text in the standard library, equivalent modifications are added here |
| | 174 | * to make it easy to add object-specific state information (e.g. |
| | 175 | * 'currently switched off' on a flashlight) if so desired). This does not |
| | 176 | * affect the standard library behaviour unless a game author chooses to |
| | 177 | * override the notProvidingLightMsg_ property anywhere. These two |
| | 178 | * ThingStates can also be given a listName_ property if a globally |
| | 179 | * applicable message is required (e.g. 'unlit' for every unlit matchstick) |
| | 180 | */ |
| | 181 | |
| | 182 | modify lightSourceStateOff |
| | 183 | msgProp = ¬ProvidingLightMsg |
| | 184 | ; |
| | 185 | |
| | 186 | modify matchStateUnlit |
| | 187 | msgProp = ¬ProvidingLightMsg |
| | 188 | ; |
| | 189 | |
| | 190 | modify unwornState |
| | 191 | msgProp = &unwornMsg |
| | 192 | ; |
| | 193 | |
| | 194 | |
| | 195 | /* |
| | 196 | * Note that the same coding pattern can be used if desired on custom |
| | 197 | * ThingStates. E.g. |
| | 198 | * |
| | 199 | *. class MyCustomClass: Thing |
| | 200 | *. allStates = [sillyState, sensibleState] |
| | 201 | *. getState = sillyState |
| | 202 | *. sillyMsg = sillyState.listName_ |
| | 203 | *. sensibleMsg = sensibleState.listName_ |
| | 204 | *. ; |
| | 205 | *. |
| | 206 | *. sillyState: ThingState 'silly' |
| | 207 | *. stateTokens = ['silly'] |
| | 208 | *. msgProp = &sillyMsg |
| | 209 | *. ; |
| | 210 | *. |
| | 211 | *. sensibleState: ThingState 'sensible' |
| | 212 | *. stateTokens = ['sensible'] |
| | 213 | *. msgProp = &sensibleMsg |
| | 214 | *. ; |
| | 215 | * |
| | 216 | * Note, however, that there is no need to define the msgProps if the |
| | 217 | * ThingStates are being created for a single object, or if all the |
| | 218 | * objects they will apply to are to use the same state-specific messages; |
| | 219 | * in these cases ThingStates may be defined and used just as they are in |
| | 220 | * the standard library. For example, if we never wanted to vary the |
| | 221 | * 'silly' and 'sensible' messages on different objects, there would be no |
| | 222 | * need (and not point) to define sillyMsg and sensibleMsg on |
| | 223 | * MyCustomClass, and no need to define msgProp on sillySrate and |
| | 224 | * sensibleState. |
| | 225 | * |
| | 226 | */ |
| | 227 | |
| | 228 | |
| | 229 | //------------------------------------------------------------------------------ |
| | 230 | |
| | 231 | modify Openable |
| | 232 | /* |
| | 233 | * openStatusReportable works on analogy with lockStatusReportable on |
| | 234 | * Lockable. It allows us to suppress the 'it's open' and 'it's closed' |
| | 235 | * messages that follow the description of an Openable object (by |
| | 236 | * setting this property to nil). By default this property is true, |
| | 237 | * giving the standard library behaviour. |
| | 238 | * |
| | 239 | * It may also be useful to set this property to the value of an |
| | 240 | * expression, e.g.: |
| | 241 | * |
| | 242 | * openStatusReportable = (isOpen) |
| | 243 | * |
| | 244 | * would result in the 'it's open' message being appended when we're |
| | 245 | * open, but nothing being appended when we're closed. |
| | 246 | */ |
| | 247 | openStatusReportable = (canInherit() ? inherited() : true) |
| | 248 | ; |
| | 249 | |
| | 250 | modify openableContentsLister |
| | 251 | showListEmpty(pov, parent) |
| | 252 | { |
| | 253 | if(parent.openStatusReportable) |
| | 254 | "\^<<parent.openStatus>>. "; |
| | 255 | } |
| | 256 | showListPrefixWide(itemCount, pov, parent) |
| | 257 | { |
| | 258 | if(parent.openStatusReportable) |
| | 259 | "\^<<parent.openStatus>>, and"; |
| | 260 | else |
| | 261 | "\^<<parent.theName>>"; |
| | 262 | " contain<<parent.verbEndingSEd>> "; |
| | 263 | } |
| | 264 | ; |
| | 265 | |
| | 266 | /* |
| | 267 | * Make openStatusReportable work on ContainerDoor in the same way as it |
| | 268 | * works on Openable. |
| | 269 | */ |
| | 270 | |
| | 271 | modify ContainerDoor |
| | 272 | openStatusReportable = (canInherit() ? inherited() : true) |
| | 273 | |
| | 274 | /* |
| | 275 | * If we set OpenStatusReportable is set to nil, we may want to |
| | 276 | * incorporate the open/closed state into our owm description. We |
| | 277 | * borrow openDesc from Openable to facilitate this. |
| | 278 | */ |
| | 279 | openDesc = (delegated Openable) |
| | 280 | |
| | 281 | |
| | 282 | replace examineStatus() |
| | 283 | { |
| | 284 | /* add our open status, if it is reportable */ |
| | 285 | if(openStatusReportable) |
| | 286 | say(isOpen |
| | 287 | ? gLibMessages.currentlyOpen : gLibMessages.currentlyClosed); |
| | 288 | |
| | 289 | /* add the base class behavior */ |
| | 290 | inherited(); |
| | 291 | } |
| | 292 | |
| | 293 | ; |
| | 294 | |
| | 295 | //------------------------------------------------------------------------------ |
| | 296 | |
| | 297 | modify Thing |
| | 298 | examineSpecialContents() |
| | 299 | { |
| | 300 | if(specialContentsListedInExamine) |
| | 301 | inherited; |
| | 302 | } |
| | 303 | |
| | 304 | /* |
| | 305 | * specialContentsListedInExamine works analogously to |
| | 306 | * contentsListedInExamine, except that if it is nil it is the listing |
| | 307 | * of this object's special contents (i.e. any contained object that |
| | 308 | * uses a specialDesc or initSpecialDesc, including actors) that will |
| | 309 | * be suppressed. |
| | 310 | */ |
| | 311 | |
| | 312 | specialContentsListedInExamine = true |
| | 313 | ; |