mirror of
https://github.com/tbamud/tbamud.git
synced 2025-09-21 21:40:49 +02:00
301 lines
9.4 KiB
Text
301 lines
9.4 KiB
Text
/*
|
|
************************************************************************
|
|
* File: events.doc *
|
|
* *
|
|
* Usage: An explanation of how to use mud events *
|
|
* Written by Joseph Arnusch (Vatiken) (Joseph.Arnusch@gmail.com) *
|
|
*
|
|
* Usage: An explanation of how to use events *
|
|
* Written by Eric Green (ejg3@cornell.edu) *
|
|
************************************************************************
|
|
*/
|
|
|
|
Vatiken's MUD event system
|
|
--------------------------
|
|
|
|
Table of Contents
|
|
-----------------
|
|
1. Purpose
|
|
2. Functions Related to MUD Events
|
|
3. Steps to Create a New MUD Event
|
|
4. Differences between the two systems
|
|
|
|
1. PURPOSE
|
|
|
|
I scribed a "MUD" event system using the "Death Gate Event" system already
|
|
in place to allow for increased ease, and maintainability for both rookie
|
|
and experienced programmers.
|
|
|
|
2. FUNCTIONS RELATED TO MUD EVENTS
|
|
|
|
a) See EVENTFUNC() in the Death Gate Events documentation below
|
|
b) void init_events(void)
|
|
"init_events()" creates the global events list and is the allocated location
|
|
for placing any global events, these may include things like AI, Weather,
|
|
and Combat.
|
|
c) struct mud_event_data * char_has_mud_event(struct char_data * ch, event_id iId)
|
|
"char_has_mud_event()" returns an event in the characters event list that matches
|
|
the supplied "event_id", or NULL if none exists.
|
|
d) NEW_EVENT(event_id, struct, var, time)
|
|
"NEW_EVENT" creates a new event of the "event_id" type, with the supplied structure
|
|
(ch, desc, object, etc..), any addtional "var"s, and is set to activate in
|
|
this amount of "time".
|
|
e) struct mud_event_list[]
|
|
The mud_event_list[] is an array of all the events you've designed into your MUD.
|
|
The reason for this excessive step is primarily for organization and troubleshooting,
|
|
and it takes a mere couple seconds to add to mud_events.c.
|
|
|
|
3. STEPS TO CREATE A NEW MUD EVENT
|
|
|
|
a) Add the new event_id to enum list in mud_events.h
|
|
|
|
typedef enum {
|
|
eNULL,
|
|
ePROTOCOLS, /* The Protocol Detection Event */
|
|
eWHIRLWIND, /* The Whirlwind Attack */
|
|
|
|
eNEWEVENT /* A NEW EVENT */
|
|
} event_id;
|
|
|
|
b) Create the event
|
|
|
|
EVENTFUNC(new_event)
|
|
{
|
|
struct char_data *ch, *tch;
|
|
struct mud_event_data *pMudEvent;
|
|
struct list_data *room_list;
|
|
int count;
|
|
|
|
/* This is just a dummy check, but we'll do it anyway */
|
|
if (event_obj == NULL)
|
|
return 0;
|
|
|
|
...
|
|
|
|
return 0;
|
|
}
|
|
|
|
c) Add the event_id data to mud_event_list[]
|
|
|
|
struct mud_event_list mud_event_index[] = {
|
|
{ "Null" , NULL , -1 }, /* eNULL */
|
|
{ "Protocol" , get_protocols , EVENT_DESC }, /* ePROTOCOLS */
|
|
{ "Whirlwind" , event_whirlwind, EVENT_CHAR } /* eWHIRLWIND */
|
|
|
|
{ "A New Event" , new_event , EVENT_CHAR } /* eNEWEVENT */
|
|
};
|
|
|
|
d) Place a call for the new event
|
|
|
|
if (variableX > variableY)
|
|
NEW_EVENT(eNEWEVENT, ch, NULL, 60 * PASSES_PER_SEC);
|
|
|
|
e) Sit back and enjoy your event triggering in 60 seconds.
|
|
|
|
4. DIFFERENCES BETWEEN THE TWO SYSTEMS
|
|
|
|
The biggest differences between the two systems is that the MUD Event System
|
|
employs certain functions to make it more "dummy proof" without limiting
|
|
functionality.
|
|
|
|
For example:
|
|
a) all memory allocated for a MUD event will be freed when the event
|
|
is no longer in use.
|
|
b) the mud_event_index[] can/will log when events are called, allowing for an
|
|
easy way to debug any problems.
|
|
c) the mud_event structure allows for easy handling of memory that shouldn't
|
|
be freed with the event like the character him/herself.
|
|
d) when a character leaves the game, all mud_events will be cleared without
|
|
manually having to place checks in free_char().
|
|
|
|
The "MUD Event" system should be adequate for 99% of all events that a developer
|
|
may be interested in creating, and still allows access the dg_event event system
|
|
for anything requiring more complicated procedures.
|
|
|
|
========================================================================
|
|
|
|
Death Gate Events
|
|
|
|
|
|
Table of Contents
|
|
-----------------
|
|
1. Event Functions and Event Objects
|
|
2. Functions for Manipulating Events
|
|
3. Steps to Create a New Event Type
|
|
4. An Example Event Type
|
|
5. Tips for Create Events
|
|
|
|
-----------------------------------------------------------------------------
|
|
1. Event Functions and Event Objects
|
|
|
|
|
|
Each event type needs an:
|
|
|
|
Event function:
|
|
|
|
An event function is a function with a prototype of:
|
|
|
|
long (event_function)(void *event_obj)
|
|
|
|
This function is called when the event occurs, and is passed the event
|
|
object (see below). If the function returns a positive value, the event
|
|
is reenqueued using the return value as the number of pulses in the
|
|
future the event will reoccur. If the function returns 0 or a negative
|
|
number, the event is not reenqueued. If the event is not to be
|
|
reenqueued, the event function is responsible for freeing the event
|
|
object. There is a define:
|
|
|
|
#define EVENTFUNC(name) long (name)(void *event_obj)
|
|
|
|
to be used when declaring an event function.
|
|
|
|
Event object:
|
|
|
|
The event object is any structure with the fields to store any data
|
|
needed by the event function. The event object should not be a game
|
|
object (such as a struct char_data), since this object is freed when
|
|
events are canceled (see cancel_event() below). All unique data
|
|
contained by the object should be freed by a call of free(event_obj).
|
|
In other words, don't have event_obj include pointers to other structures
|
|
which aren't pointed to elsewhere. It is also not advisable to have
|
|
pointers in the event object unless the thing they point to has a pointer
|
|
to this event and cancels the event when it is freed. Passing NULL as an
|
|
event object is valid (providing the event function doesn't need any
|
|
data).
|
|
|
|
----------------------------------------------------------------------------
|
|
2. Functions for Manipulating Events
|
|
|
|
|
|
The prototypes for the interface functions for events are provided in
|
|
events.h. They are:
|
|
|
|
void event_init(void);
|
|
This function initializes the event queue for all events. It is only
|
|
called once, at the initialization of the game.
|
|
|
|
struct event *event_create(EVENTFUNC(*func), void *event_obj, long when);
|
|
This function creates a new event. At the current time plus 'when',
|
|
the function call
|
|
|
|
func(event_obj);
|
|
|
|
will be made. A pointer to the created event is returned. Never free()
|
|
the event returned. Use event_cancel instead if you want to get rid of it
|
|
prematurely.
|
|
|
|
void event_cancel(struct event *event);
|
|
This function cancels an event currently in the queue. The event and the
|
|
event_obj are freed by this call.
|
|
|
|
void event_process(void);
|
|
This function is called once each pulse to process any pending events.
|
|
It should not be used outside of the main loop.
|
|
|
|
long event_time(struct event *event);
|
|
Given event, this function returns the number of pulses until the event
|
|
occurs. One example of a place it is used is to get the pulses left before
|
|
an object timer expires, so its current state can be saved and restored
|
|
later.
|
|
|
|
-----------------------------------------------------------------------------
|
|
3. Steps to Create a New Event Type
|
|
|
|
To add a new event type, you do not need to know anything about what's in
|
|
events.c, queue.c, or queue.h, the core of the event code. To create an
|
|
event type:
|
|
|
|
1. Declare an event object structure.
|
|
|
|
2. Create your event function.
|
|
|
|
3. Construct your event object, and call event_create() where needed.
|
|
|
|
4. Any place that the 'owner' of the event can be destroyed, call
|
|
event_cancel().
|
|
|
|
------------------------------------------------------------------------------
|
|
4. An Example Event Type
|
|
|
|
|
|
Example event type:
|
|
|
|
/* the event object for the sniff event */
|
|
struct sniff_event_obj {
|
|
struct char_data *ch;
|
|
byte type;
|
|
};
|
|
|
|
|
|
EVENTFUNC(sniff_event)
|
|
{
|
|
struct sniff_event_obj *seo = (struct sniff_event_obj *) event_obj;
|
|
struct char_data *ch, *victim;
|
|
|
|
ch = seo->ch;
|
|
|
|
GET_CHAR_SNIFF(ch) = NULL;
|
|
|
|
if (type == SNIFF_COLD)
|
|
act("$n sniffs loudly.", FALSE, ch, NULL, NULL, TO_ROOM);
|
|
else
|
|
act("$n sniffs some cocaine.", FALSE, ch, NULL, NULL, TO_ROOM);
|
|
|
|
act("You sniff.", FALSE, ch, NULL, NULL, TO_CHAR);
|
|
|
|
if (--seo->severity <= 0) {
|
|
/* we're done with sniffing */
|
|
free(event_obj);
|
|
}
|
|
else
|
|
return PULSE_SNIFF;
|
|
}
|
|
|
|
|
|
ACMD(do_sniff)
|
|
{
|
|
struct sniff_event_obj *sniff;
|
|
|
|
CREATE(sniff, struct sniff_event_obj, 1);
|
|
sniff->ch = ch;
|
|
sniff->severity = 5;
|
|
if (GET_CLASS(ch) != CLASS_THIEF)
|
|
sniff->type = SNIFF_COLD;
|
|
else
|
|
sniff->type = SNIFF_COCAINE;
|
|
|
|
GET_CHAR_SNIFF(ch) = event_create(sniff_event, sniff, PULSE_SNIFF);
|
|
|
|
send_to_char(OK, ch);
|
|
}
|
|
|
|
|
|
void extract_char(struct char_data *ch)
|
|
{
|
|
|
|
...
|
|
|
|
if (GET_CHAR_SNIFF(ch)) {
|
|
event_cancel(GET_CHAR_SNIFF(ch));
|
|
GET_CHAR_SNIFF(ch) = NULL;
|
|
}
|
|
|
|
...
|
|
}
|
|
|
|
-----------------------------------------------------------------------------
|
|
5. Tips for Create Events
|
|
|
|
|
|
Tips for creating events:
|
|
|
|
o event_obj should always be freed (or reused) in the EVENTFUNC()
|
|
|
|
o Any game object pointed to by event_obj should have a pointer to the
|
|
the event so it can cancel the event if it is extracted.
|
|
|
|
o Any game object with pointers to an event should have the event pointer
|
|
set to NULL in EVENTFUNC and immediately following event_cancel().
|
|
|
|
o Any place a game object is extracted from the game, any events it points to
|
|
should be canceled and its pointer to the events set to NULL.
|