Adonthell
0.4
Main Page
Related Pages
Classes
Files
File List
File Members
event.dxt
1
/*
2
$Id: event.dxt,v 1.3 2002/12/15 17:23:30 ksterker Exp $
3
4
Copyright (C) 2001/2002 Kai Sterker <kaisterker@linuxgames.com>
5
Part of the Adonthell Project http://adonthell.linuxgames.com
6
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY.
11
12
See the COPYING file for more details.
13
*/
14
15
/*! \page page3 The Event System
16
17
The %event system is divided into three parts. The \ref event_sec1
18
keeps track of all registered %event scripts.
19
Whenever an %event occurs, the %event handler is notified and executes
20
all scripts registered for that particular %event. The \ref event_sec2
21
keeps track of the %events registered by a certain
22
%object, (e.g. a NPC, a maptile or item) and automatically unregisters
23
these %events when this %object is deleted. Finally, there are the
24
\ref event_sec3 themself, used both as message
25
sent to the %event handler whenever an %event occurs and to register
26
an %event script. Each %event has its own data structure with
27
parameters corresponding to its type. These parameters are
28
passed to the %event script, so all infomation regarding
29
an %event is available from within the script as well. The
30
parameters can further be used to specialize the script so it
31
reacts to a smaller range of %events.
32
33
34
\section event_sec1 Event Handler
35
36
The %event handler is the core component of the %event system.
37
It provides a method to initialize the %event system and allows
38
global access to the specialized handlers for individual events.
39
For that purpose, it stores a list of event_handler_base %objects,
40
the virtual base class for the specialized handlers, and passes
41
any %event it receives to the right handler.
42
43
The %event_handler_base class provides three pure virtual methods
44
that need to be implemented by each specialized handler:
45
46
- register_event() to pass a new %event to the handler. %Events
47
need to be registered with the handler before they can take
48
place
49
50
- remove_event() to remove a previously registered %event from
51
the handler
52
53
- raise_event() to send a message to the handler that will trigger
54
matching events.
55
56
57
\section event_sec2 Event List
58
59
The event_list is a convenience class for %objects that register
60
events with the handler. As it is up to each object to save the
61
events it registers, and to load and re-register them, the %event
62
list has been written to take care of that.
63
64
To make the %event list independent from specific %event types,
65
it only works on pointers to the %event base class. That works fine
66
in all cases, except one. When loading events, the %event list needs
67
to instanciate the proper %event subclass. For that purpose, the %event
68
list stores a list of callbacks that return a newly instanciated %event
69
subclass of a given type. Two macros have been written that take care
70
of most of the work.
71
72
\code
73
NEW_EVENT (subclass)
74
REGISTER_EVENT (type, subclass)
75
\endcode
76
77
%NEW_EVENT provides the function that will return a newly allocated
78
%event. %REGISTER_EVENT will pass this function to the %event list.
79
For each %event type, these two macros should be added to
80
event_handler::init(), the %event system's init method.
81
82
The %event list provides the following methods:
83
84
- event_list::add_event() adds an %event to the list and registers it
85
with the %event handler.
86
87
- event_list::put_state() saves the list with all events inside.
88
89
- event_list::get_state() restores the list with all events and registers
90
them with the %event handler.
91
92
93
\section event_sec3 Events
94
95
Events have two main purposes. Registered with the %event handler,
96
they allow to execute either a %python script, a %python or a C/C++
97
callback in case that %event takes place. But they are also sent
98
as messages to the handler, to trigger matching events.
99
100
Each specific %event may have its own %data fields and methods,
101
depending on its purpose. However, all events share a number of
102
common features, which are implemented by the %event base class.
103
104
The first feature is the %event's action, i.e. what happens if that
105
%event is triggered. The %event class allows to attach a \link py_object
106
python script \endlink, a \link py_callback python callback \endlink
107
or a C/C++ callback.
108
109
C/C++ callbacks are only useful when the %game engine wants to make
110
use of the %event system internally. %Python callbacks allow scripts
111
like \link schedule character schedules \endlink to use the %event
112
system. %Event scripts usually define the action of a certain class of
113
events. For example an %event script might implement a trap that is
114
activated whenever a %character steps on it. This 'trap' script can then
115
be used by traps all over the place.
116
117
Apart from the %event's action, the base %event class also provides
118
means to repeat events or prevent them from repeating. For example,
119
a trap might only work once. event::set_repeat() allows to specify
120
how often an %event can be executed. Once that repeat count reaches
121
zero, executing the event will automatically delete it. This will
122
also remove it from the %event_handler and %event_list. That way,
123
events that are used up vanish from the game, just as one would expect.
124
125
Further, the %event class has two pure virtual methods that need
126
to be implemented by the specific events. They are provided so
127
that (not so) specialized %event handlers may take care of different
128
%event types.
129
130
- equals() is used to compare two events for 'equality'. The message
131
sent to the handler is compared to all registered events to see if
132
they match.
133
134
- execute() is used once the %event is triggered and should executed
135
the %event's action.
136
137
138
\section event_sec4 Using the Event System
139
140
The %event handler is implemented in the event_handler class.
141
It totally consists of static members and methods, to make it
142
easily accessible from any part of the code. Just include
143
the event_handler.h file. To register a script with the handler
144
that is executed whenever the player arrives at the coordinates
145
(20, 20) of a map, you'd write:
146
147
\code
148
// Create the filter and set it's parameters
149
event *filter = new enter_event;
150
151
filter->x = 20;
152
filter->y = 20;
153
filter->c = data::the_player;
154
155
// Set the script to be executed when the event occurs
156
filter->set_script ("a_script");
157
158
// Finally add the filter to the event list. This will register it with the event handler
159
add_event (filter);
160
\endcode
161
162
For a list of available events with their corresponding parameters
163
see the \link event API documentation \endlink.
164
165
The %event script in that example could look as follows:
166
167
\verbatim
168
class a_script:
169
# -- constructor
170
def __init__ (self, event, <additional arguments>):
171
# -- the event the script belongs to
172
self.myself = event
173
...
174
175
# -- method called when the event occurs, the parameters
176
# depend on the type of the event
177
def run (self, submap, x, y, direction, character):
178
print "%s arrived at %i, %i" % (character, x, y)
179
\endverbatim
180
181
As you can see, you have the possibility to pass extra parameters
182
to the script constructor. This is limited to strings and integers
183
though. When you set the argument list from C++, you have to manually
184
create a %Python tuple, and you should not forget to decrement its
185
reference count when you are done with it. The following code could
186
be used for the example above:
187
188
\code
189
// Create our argument tuple that will be passed to the script constructor
190
PyObject * args = PyTuple_New (2);
191
PyTuple_SetItem (args, 0, PyInt_FromLong (10));
192
PyTuple_SetItem (args, 0, PyString_FromString ("2nd argument"));
193
194
// Set the script to be executed when the event occurs
195
filter->set_script ("a_script", args);
196
197
// We don't need our reference to the tuple anymore
198
Py_DECREF (args);
199
\endcode
200
201
The script constructor would then receive two additional arguments.
202
This is useful to create generic scripts that can be customized at
203
runtime. To return to our old trap example, the amount of damage the
204
trap does could be specified for each trap in this way.
205
206
Now we have registered an %event with the %event handler. But that alone
207
won't get the %event triggered. So depending on its type, you'll have to
208
notify the %event handler of an %event's occurance. In case of the \link
209
enter_event enter event \endlink , you'll want to send a message to the
210
%event handler whenever a %character reaches a new position on the map.
211
212
\code
213
// Event structures are also used to pass messages to the event_handler
214
enter_event message;
215
216
// Fill in the parameters
217
message.x = mapcharacter::posx ();
218
message.y = mapcharacter::posy ();
219
message.submap = mapcharacter::submap ();
220
message.c = this;
221
222
// Notify the event handler
223
event_handler::raise_event (&message);
224
\endcode
225
226
The %event handler will then compare all %events of the given type with the
227
message it received and execute the %event action of events that match.
228
229
230
\section event_sec5 The Different Event Types
231
232
Various types of events are defined by the %game engine, all
233
inheriting from the event class defined in event.h.
234
235
\subsection mapevents Map Events
236
237
There are 3 types of map events:
238
\li enter_event, which are triggered whenever a %character enters a
239
square,
240
\li leave_event, which are triggered whenever a %character leaves a
241
square,
242
\li action_event, which are triggered when the main %character "acts"
243
on a given square.
244
245
All these map events inherits from the map_event class, which
246
contains all the parameters they need:
247
\li x, the X coordinate of the square the %event happened on,
248
\li y, the Y coordinate of the square the %event happened on,
249
\li submap, the number of the submap where the %event happened on,
250
\li c, a pointer to the %mapcharacter that triggered the %event,
251
\li dir, the direction the %mapcharacter is facing when the %event
252
is triggered.
253
254
When a map %event is triggered, the run ()method of the Python script
255
is called, with the arguments \e submap, \e x, \e y and \e name, which
256
is the name of the mapcharacter that triggered the %event.
257
258
Map events are repeated forever by default.
259
260
\subsection timeevent Time Event
261
262
The time_event can be used to track relative or absolute %game time.
263
Relative means, the %event will be triggered after a given amount of time
264
has passed, starting at the moment it is created. Absolute means a fixed
265
point in time, i.e. a certain hour at a certain day.
266
267
Time events are not repeated by default. They can be told to repeat though,
268
and it is also possible to specify the delay between two occurances.
269
270
Time events pass no arguments to the run() method of the Python script.
271
The script can easily get the current %game time from the gamedate class.
272
273
274
\section event_sec6 Saving and Restoring Events
275
276
As described in the \ref event_sec2 section, events can be saved to disk
277
and restored at a later point. For this to work, a few restrictions have
278
to be made, especially regarding any %python arguments that get passed to
279
script or callback. Events that contain a C/C++ callback cannot be saved
280
at all, as it is not possible to restore that callback.
281
282
For events with an attached %python script, the only restriction is that
283
the argument needs to be a tuple, containing only string and/or integer
284
%objects. On saving, the name of the script and this argument tuple are
285
saved to disk. On loading, the arguments are loaded, and the script is
286
instanciated with those arguments.
287
288
The same restriction concerning arguments applies to events with an
289
attached %python callback. However, when saving the callback, only the
290
name of the function or method is saved, but not the instance it belongs
291
to. To restore the callback, it is neccessary to restore that instance
292
first. Then a pointer to it needs to be assigned to py_callback::instance,
293
which is a static member of the %py_callback class. Only then can the
294
callback be restored properly.
295
296
*/
event.dxt
Generated by
1.8.4