Adonthell 0.4

event.dxt

00001 /*
00002    $Id: event.dxt,v 1.3 2002/12/15 17:23:30 ksterker Exp $
00003 
00004    Copyright (C) 2001/2002 Kai Sterker <kaisterker@linuxgames.com>
00005    Part of the Adonthell Project http://adonthell.linuxgames.com
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License.
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY.
00011 
00012    See the COPYING file for more details.
00013 */
00014 
00015 /*! \page page3 The Event System
00016  
00017  The %event system is divided into three parts. The \ref event_sec1 
00018  keeps track of all registered %event scripts. 
00019  Whenever an %event occurs, the %event handler is notified and executes
00020  all scripts registered for that particular %event. The \ref event_sec2
00021  keeps track of the %events registered by a certain
00022  %object, (e.g. a NPC, a maptile or item) and automatically unregisters
00023  these %events when this %object is deleted. Finally, there are the 
00024  \ref event_sec3 themself, used both as  message 
00025  sent to the %event handler whenever an %event occurs and to register 
00026  an %event script. Each %event has its own data structure with
00027  parameters corresponding to its type. These parameters are
00028  passed to the %event script, so all infomation regarding
00029  an %event is available from within the script as well. The
00030  parameters can further be used to specialize the script so it
00031  reacts to a smaller range of %events.
00032 
00033 
00034  \section event_sec1 Event Handler
00035 
00036  The %event handler is the core component of the %event system.
00037  It provides a method to initialize the %event system and allows
00038  global access to the specialized handlers for individual events.
00039  For that purpose, it stores a list of event_handler_base %objects,
00040  the virtual base class for the specialized handlers, and passes
00041  any %event it receives to the right handler.
00042  
00043  The %event_handler_base class provides three pure virtual methods
00044  that need to be implemented by each specialized handler:
00045  
00046  - register_event() to pass a new %event to the handler. %Events
00047    need to be registered with the handler before they can take
00048    place
00049    
00050  - remove_event() to remove a previously registered %event from
00051    the handler
00052     
00053  - raise_event() to send a message to the handler that will trigger
00054    matching events. 
00055  
00056  
00057  \section event_sec2 Event List
00058 
00059  The event_list is a convenience class for %objects that register
00060  events with the handler. As it is up to each object to save the
00061  events it registers, and to load and re-register them, the %event
00062  list has been written to take care of that.
00063  
00064  To make the %event list independent from specific %event types,
00065  it only works on pointers to the %event base class. That works fine
00066  in all cases, except one. When loading events, the %event list needs
00067  to instanciate the proper %event subclass. For that purpose, the %event
00068  list stores a list of callbacks that return a newly instanciated %event
00069  subclass of a given type. Two macros have been written that take care
00070  of most of the work.
00071 
00072 \code
00073 NEW_EVENT (subclass)
00074 REGISTER_EVENT (type, subclass)
00075 \endcode
00076 
00077  %NEW_EVENT provides the function that will return a newly allocated 
00078  %event. %REGISTER_EVENT will pass this function to the %event list.
00079  For each %event type, these two macros should be added to 
00080  event_handler::init(), the %event system's init method. 
00081 
00082  The %event list provides the following methods:
00083  
00084  - event_list::add_event() adds an %event to the list and registers it 
00085    with the %event handler.
00086  
00087  - event_list::put_state() saves the list with all events inside.
00088  
00089  - event_list::get_state() restores the list with all events and registers 
00090    them with the %event handler.
00091  
00092  
00093  \section event_sec3 Events
00094  
00095  Events have two main purposes. Registered with the %event handler,
00096  they allow to execute either a %python script, a %python or a C/C++
00097  callback in case that %event takes place. But they are also sent
00098  as messages to the handler, to trigger matching events.
00099  
00100  Each specific %event may have its own %data fields and methods,
00101  depending on its purpose. However, all events share a number of
00102  common features, which are implemented by the %event base class.
00103  
00104  The first feature is the %event's action, i.e. what happens if that
00105  %event is triggered. The %event class allows to attach a \link py_object
00106  python script \endlink, a \link py_callback python callback \endlink 
00107  or a C/C++ callback.
00108  
00109  C/C++ callbacks are only useful when the %game engine wants to make
00110  use of the %event system internally. %Python callbacks allow scripts
00111  like \link schedule character schedules \endlink to use the %event 
00112  system. %Event scripts usually define the action of a certain class of 
00113  events. For example an %event script might implement a trap that is 
00114  activated whenever a %character steps on it. This 'trap' script can then 
00115  be used by traps all over the place.
00116   
00117  Apart from the %event's action, the base %event class also provides
00118  means to repeat events or prevent them from repeating. For example,
00119  a trap might only work once. event::set_repeat() allows to specify
00120  how often an %event can be executed. Once that repeat count reaches
00121  zero, executing the event will automatically delete it. This will
00122  also remove it from the %event_handler and %event_list. That way,
00123  events that are used up vanish from the game, just as one would expect.
00124  
00125  Further, the %event class has two pure virtual methods that need
00126  to be implemented by the specific events. They are provided so
00127  that (not so) specialized %event handlers may take care of different
00128  %event types.
00129  
00130  - equals() is used to compare two events for 'equality'. The message
00131    sent to the handler is compared to all registered events to see if
00132    they match.
00133    
00134  - execute() is used once the %event is triggered and should executed
00135    the %event's action.
00136  
00137  
00138  \section event_sec4 Using the Event System
00139  
00140  The %event handler is implemented in the event_handler class.
00141  It totally consists of static members and methods, to make it
00142  easily accessible from any part of the code. Just include
00143  the event_handler.h file. To register a script with the handler 
00144  that is executed whenever the player arrives at the coordinates 
00145  (20, 20) of a map, you'd write:
00146 
00147 \code
00148 // Create the filter and set it's parameters
00149 event *filter = new enter_event;
00150  
00151 filter->x = 20;
00152 filter->y = 20;
00153 filter->c = data::the_player;
00154 
00155 // Set the script to be executed when the event occurs
00156 filter->set_script ("a_script");
00157 
00158 // Finally add the filter to the event list. This will register it with the event handler
00159 add_event (filter);
00160 \endcode
00161  
00162  For a list of available events with their corresponding parameters
00163  see the \link event API documentation \endlink.
00164 
00165  The %event script in that example could look as follows:
00166  
00167 \verbatim
00168 class a_script:
00169     # -- constructor
00170     def __init__ (self, event, <additional arguments>):
00171         # -- the event the script belongs to
00172         self.myself = event
00173         ...
00174 
00175     # -- method called when the event occurs, the parameters
00176     #    depend on the type of the event
00177     def run (self, submap, x, y, direction, character):
00178         print "%s arrived at %i, %i" % (character, x, y)
00179 \endverbatim
00180 
00181  As you can see, you have the possibility to pass extra parameters
00182  to the script constructor. This is limited to strings and integers
00183  though. When you set the argument list from C++, you have to manually 
00184  create a %Python tuple, and you should not forget to decrement its 
00185  reference count when you are done with it. The following code could
00186  be used for the example above:
00187 
00188 \code
00189 // Create our argument tuple that will be passed to the script constructor
00190 PyObject * args = PyTuple_New (2);
00191 PyTuple_SetItem (args, 0, PyInt_FromLong (10));
00192 PyTuple_SetItem (args, 0, PyString_FromString ("2nd argument"));
00193 
00194 // Set the script to be executed when the event occurs
00195 filter->set_script ("a_script", args);
00196 
00197 // We don't need our reference to the tuple anymore
00198 Py_DECREF (args);
00199 \endcode
00200  
00201  The script constructor would then receive two additional arguments. 
00202  This is useful to create generic scripts that can be customized at
00203  runtime. To return to our old trap example, the amount of damage the
00204  trap does could be specified for each trap in this way.
00205  
00206  Now we have registered an %event with the %event handler. But that alone
00207  won't get the %event triggered. So depending on its type, you'll have to
00208  notify the %event handler of an %event's occurance. In case of the \link
00209  enter_event enter event \endlink , you'll want to send a message to the
00210  %event handler whenever a %character reaches a new position on the map.
00211          
00212  \code
00213 // Event structures are also used to pass messages to the event_handler
00214 enter_event message;
00215 
00216 // Fill in the parameters
00217 message.x = mapcharacter::posx ();
00218 message.y = mapcharacter::posy ();
00219 message.submap = mapcharacter::submap ();
00220 message.c = this;
00221 
00222 // Notify the event handler
00223 event_handler::raise_event (&message);
00224 \endcode
00225 
00226 The %event handler will then compare all %events of the given type with the
00227 message it received and execute the %event action of events that match.         
00228 
00229 
00230 \section event_sec5 The Different Event Types
00231 
00232 Various types of events are defined by the %game engine, all
00233 inheriting from the event class defined in event.h.
00234 
00235 \subsection mapevents Map Events
00236 
00237 There are 3 types of map events:
00238 \li enter_event, which are triggered whenever a %character enters a
00239 square,
00240 \li leave_event, which are triggered whenever a %character leaves a
00241 square,
00242 \li action_event, which are triggered when the main %character "acts"
00243 on a given square.
00244 
00245 All these map events inherits from the map_event class, which
00246 contains all the parameters they need:
00247 \li x, the X coordinate of the square the %event happened on,
00248 \li y, the Y coordinate of the square the %event happened on,
00249 \li submap, the number of the submap where the %event happened on,
00250 \li c, a pointer to the %mapcharacter that triggered the %event,
00251 \li dir, the direction the %mapcharacter is facing when the %event
00252     is triggered.
00253 
00254 When a map %event is triggered, the run ()method of the Python script
00255 is called, with the arguments \e submap, \e x, \e y and \e name, which
00256 is the name of the mapcharacter that triggered the %event.
00257 
00258 Map events are repeated forever by default.
00259 
00260 \subsection timeevent Time Event
00261 
00262 The time_event can be used to track relative or absolute %game time.
00263 Relative means, the %event will be triggered after a given amount of time
00264 has passed, starting at the moment it is created. Absolute means a fixed
00265 point in time, i.e. a certain hour at a certain day.
00266 
00267 Time events are not repeated by default. They can be told to repeat though,
00268 and it is also possible to specify the delay between two occurances.
00269 
00270 Time events pass no arguments to the run() method of the Python script.
00271 The script can easily get the current %game time from the gamedate class. 
00272 
00273 
00274 \section event_sec6 Saving and Restoring Events
00275 
00276 As described in the \ref event_sec2 section, events can be saved to disk
00277 and restored at a later point. For this to work, a few restrictions have
00278 to be made, especially regarding any %python arguments that get passed to
00279 script or callback. Events that contain a C/C++ callback cannot be saved
00280 at all, as it is not possible to restore that callback.
00281 
00282 For events with an attached %python script, the only restriction is that
00283 the argument needs to be a tuple, containing only string and/or integer 
00284 %objects. On saving, the name of the script and this argument tuple are 
00285 saved to disk. On loading, the arguments are loaded, and the script is
00286 instanciated with those arguments.
00287 
00288 The same restriction concerning arguments applies to events with an
00289 attached %python callback. However, when saving the callback, only the 
00290 name of the function or method is saved, but not the instance it belongs
00291 to. To restore the callback, it is neccessary to restore that instance 
00292 first. Then a pointer to it needs to be assigned to py_callback::instance,
00293 which is a static member of the %py_callback class. Only then can the
00294 callback be restored properly.
00295 
00296 */