cfad47cfa3/t3compiler/tads3/lib/extensions/custmsg.t

4b825dc642cb6eb9a060e54bf8d69288fbee4904cfad47cfa334b206c65f22086bcc5d63e6f70944
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 = &notProvidingLightMsg
184
;
185
186
modify matchStateUnlit
187
    msgProp = &notProvidingLightMsg
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
;